canvas

一、canvas基本使用

1.1 <canvas>元素

<canvas id="tutorial" width="300" height="300"></canvas> 

<canvas>看起来和<img>标签一样,只是 <canvas> 只有两个可选的属性 width、heigth 属性,而没有 src、alt 属性。

如果不给<canvas>设置widht、height属性时,则默认 width为300、height为150,单位都是px。也可以使用css属性来设置宽高,但是如宽高属性和初始比例不一致,他会出现扭曲。所以,建议永远不要使用css属性来设置<canvas>的宽高。

由于某些较老的浏览器(尤其是IE9之前的IE浏览器)或者浏览器不支持HTML元素<canvas>,在这些浏览器上你应该总是能展示替代内容。

支持<canvas>的浏览器会只渲染<canvas>标签,而忽略其中的替代内容。不支持 <canvas> 的浏览器则 会直接渲染替代内容。

<canvas> 你的浏览器不支持canvas,请升级你的浏览器 </canvas> 

<canvas> <img src=" " alt="">  </canvas> 

结束标签</canvas>不可省

与 <img>元素不同,<canvas>元素需要结束标签(</canvas>)。如果结束标签不存在,则文档的其余部分会被认为是替代内容,将不会显示出来。

1.2 渲染上下文

<canvas>会创建一个固定大小的画布,会公开一个或多个 渲染上下文(画笔),使用 渲染上下文来绘制和处理要展示的内容。

var canvas = document.getElementById('tutorial'); //获得 2d 上下文对象 
var ctx = canvas.getContext('2d'); 

1.3 检验支持性

var canvas = document.getElementById('tutorial');
if (canvas.getContext){
  var ctx = canvas.getContext('2d');
  // drawing code here
} else {
  // canvas-unsupported code here
}

1.4 代码模板

<html>
<head>
    <title>Canvas tutorial</title>
    <style type="text/css">
        canvas {
            border: 1px solid black;
        }
    </style>
</head>
<canvas id="tutorial" width="300" height="300"></canvas>
</body>
<script type="text/javascript">
    function draw(){
        var canvas = document.getElementById('tutorial');
        if(!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        //开始代码
}
draw();
</script>
</html>

二、绘制形状

2.1 栅格(grid)和坐标空间

如下图所示,canvas元素默认被网格所覆盖。通常来说网格中的一个单元相当于canvas元素中的一像素。栅格的起点为左上角(坐标为(0,0))。所有元素的位置都相对于原点来定位。所以图中蓝色方形左上角的坐标为距离左边(X轴)x像素,距离上边(Y轴)y像素(坐标为(x,y))。

2.2 绘制矩形

canvast 提供了三种方法绘制矩形:

(1)fillRect(x, y, width, height)

      绘制一个填充的矩形

(2)strokeRect(x, y, width, height)

      绘制一个矩形的边框

(3)clearRect(x, y, widh, height)

      清除指定的矩形区域,然后这块区域会变的完全透明。

说明:这3个方法具有相同的参数。

   x, y:指的是矩形的左上角的坐标。(相对于canvas的坐标原点)

   width, height:指的是绘制的矩形的宽和高。

-------------------------------------------------------------------------------例子1--------------------------------------------------------------------

三、绘制路径

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。

一个路径,甚至一个子路径,都是闭合的。

步骤:

1.创建路径起始点

2.调用绘制方法去绘制出路径

3.把路径封闭

4.一旦路径生成,通过描边或填充路径区域来渲染图形。

方法:

beginPath() //新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径

moveTo(x, y) //把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。

closePath() //闭合路径之后,图形绘制命令又重新指向到上下文中

stroke() //通过线条来绘制图形轮廓

fill() //通过填充路径的内容区域生成实心的图形

3.1 绘制线段

-------------------------------------------------------------------------------例子2--------------------------------------------------------------------

3.2 绘制三角形边框

-------------------------------------------------------------------------------例子3--------------------------------------------------------------------

3.3 填充三角形

-------------------------------------------------------------------------------例子4--------------------------------------------------------------------

3.4 绘制圆弧

有两个方法可以绘制圆弧:

  1. arc(x, y, r, startAngle, endAngle, anticlockwise):

以(x, y)为圆心,以r为半径,从 startAngle弧度开始到endAngle弧度结束。anticlosewise是布尔值,true表示逆时针,false表示顺时针。(默认是顺时针)

注:这里的度数都是弧度。0弧度是指的x轴正方形

radians=(Math.PI/180)*degrees   //角度转换成弧度
  1. arcTo(x1, y1, x2, y2, radius):
    参数1、2:控制点1坐标 参数3、4:控制点2坐标 参数4:圆弧半径

根据给定的控制点和半径画一段圆弧,最后再以直线连接两个控制点。

注:这个方法可以这样理解。绘制的弧形是由两条切线所决定。

    第 1 条切线:起始点和控制点1决定的直线。

第 2 条切线:控制点1 和控制点2决定的直线。

其实绘制的圆弧就是与这两条直线相切的圆弧。

-------------------------------------------------------------------------------例子5--------------------------------------------------------------------

-------------------------------------------------------------------------------例子6--------------------------------------------------------------------

四、添加样式和颜色

在前面的绘制矩形章节中,只用到了默认的线条和颜色。如果想要给图形上色,有两个重要的属性可以做到。

4.1 fillstyle

  1. fillStyle = color //设置图形的填充颜色

4.2 strokeStyle

  1. strokeStyle = color //设置图形轮廓的颜色

注:

  1. color 可以是表示 css 颜色值的字符串、渐变对象或者图案对象。
  2. 默认情况下,线条和填充颜色都是黑色。
  3. 一旦设置了 strokeStyle 或者 fillStyle 的值,那么这个新值就会成为新绘制的图形的默认值。如果你要给每个图形上不同的颜色,你需要重新设置 fillStyle 或 strokeStyle 的值。

-------------------------------------------------------------------------------例子7--------------------------------------------------------------------

-------------------------------------------------------------------------------例子8--------------------------------------------------------------------

4.3 linestyle

  1. lineWidth = value //线宽。只能是正值。默认是1.0。起始点和终点的连线为中心,上下各占线宽的一半

-------------------------------------------------------------------------------例子9--------------------------------------------------------------------

  1. lineCap = type //线条末端样式。
    共有3个值:
    butt:线段末端以方形结束
    round:线段末端以圆形结束
    square:线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域。

-------------------------------------------------------------------------------例子10------------------------------------------------------------------

  1. lineJoin = type //同一个path内,设定线条与线条间接合处的样式。
    共有3个值:
    round:通过填充一个额外的,圆心在相连部分末端的扇形,绘制拐角的形状。 圆角的半径是线段的宽度。
    bevel:在相连部分的末端填充一个额外的以三角形为底的区域, 每个部分都有各自独立的矩形拐角。
    miter(默认):通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。

-------------------------------------------------------------------------------例子11------------------------------------------------------------------

  1. 虚线
    用 setLineDash 方法和 lineDashOffset 属性来制定虚线样式.
    setLineDash 方法接受一个数组,来指定线段与间隙的交替;
    lineDashOffset属性设置起始偏移量.

-------------------------------------------------------------------------------例子12------------------------------------------------------------------

五、绘制文本

5.1 绘制文本的两种方法

canvas 提供了两种方法来渲染文本:

fillText(text, x, y [, maxWidth])

在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的.

strokeText(text, x, y [, maxWidth])

在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的.

-------------------------------------------------------------------------------例子13------------------------------------------------------------------

5.2 给文本添加样式

  1. font = value

当前我们用来绘制文本的样式。这个字符串使用和 CSS font属性相同的语法. 默认的字体是 10px sans-serif。

  1. textAlign = value

文本对齐选项. 可选的值包括:start, end, left, right or center. 默认值是 start。

  1. textBaseline = value

基线对齐选项,可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。

  1. direction = value

文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。

六、绘制图片

6.1 开始创建图片

创建<img>元素(脚本执行后图片开始装载)

var img = new Image();   // 创建一个<img>元素

img.src = 'myImage.png'; // 设置图片源地址

绘制img

//参数1:要绘制的img  参数2、3:绘制的img在canvas中的坐标

ctx.drawImage(img,0,0); 

注:考虑到图片是从网络加载,如果 drawImage 的时候图片还没有完全加载完成,则什么都不做,个别浏览器会抛异常。所以我们应该保证在 img 绘制完成之后再 drawImage。

var img = new Image();   // 创建img元素
img.onload = function(){
  ctx.drawImage(img, 0, 0)
}
img.src = 'myImage.png'; // 设置图片源地址

6.2 绘制 img 标签元素中的图片

img 可以 new 也可以来源于我们页面的 <img>标签

-------------------------------------------------------------------------------例子14------------------------------------------------------------------

6.3 缩放图片

drawImage() 也可以再添加两个参数:

drawImage(image, x, y, width, height)

这个方法多了2个参数:width 和 height,这两个参数用来控制 当像canvas画入时应该缩放的大小。

ctx.drawImage(img, 0, 0, 400, 200)

-------------------------------------------------------------------------------例子14------------------------------------------------------------------

6.4 图片切片(slice)

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。

其他8个参数:

前4个是定义图像源的切片位置和大小,

后4个则是定义切片的目标显示位置和大小。

-------------------------------------------------------------------------------例子14------------------------------------------------------------------

七、状态的保存和恢复

Saving and restoring state是绘制复杂图形时必不可少的操作。

  1. save()和restore()

    save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。

    Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

  2. 关于 save()

    Canvas状态存储在栈中,每当save()方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:
    
    当前应用的变形(即移动,旋转和缩放)
    
    strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX,          shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 的值
    
    当前的裁切路径(clipping path)
    

可以调用任意多次 save方法。(类似数组的push())

  1. 关于restore()

    每一次调用 restore 方法,上一个保存的状态就从栈中弹出,所有设定都恢复。(类似数组的pop())

-------------------------------------------------------------------------------例子15------------------------------------------------------------------

八、变形

8.1 translate

translate(x, y) //用来移动 canvas 的原点到指定的位置

translate方法接受两个参数。x 是左右偏移量,y 是上下偏移量。

在做变形之前先保存状态是一个良好的习惯。大多数情况下,调用 restore 方法比手动恢复原先的状态要简单得多。又如果你是在一个循环中做位移但没有保存和恢复canvas 的状态,很可能到最后会发现怎么有些东西不见了,那是因为它很可能已经超出 canvas 范围以外了。

注:translate移动的是canvas的坐标原点。(坐标变换)

-------------------------------------------------------------------------------例子16------------------------------------------------------------------

8.2 rotate

rotate(angle) //旋转坐标轴。

这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。

旋转的中心是坐标原点。

-------------------------------------------------------------------------------例子17------------------------------------------------------------------

8.3 scale

scale(x, y)

我们用它来增减图形在 canvas 中的像素数目,对形状,位图进行缩小或者放大。

scale方法接受两个参数。x,y分别是横轴和纵轴的缩放因子,它们都必须是正值。值比 1.0 小表示缩 小,比 1.0 大则表示放大,值为 1.0 时什么效果都没有。

默认情况下,canvas 的 1 单位就是 1 个像素。举例说,如果我们设置缩放因子是 0.5,1 个单位就变成对应 0.5 个像素,这样绘制出来的形状就会是原先的一半。同理,设置为 2.0 时,1 个单位就对应变成了 2 像素,绘制的结果就是图形放大了 2 倍。

8.4 transform(变形矩阵)

transform(a, b, c, d, e, f)

a (m11)Horizontal scaling.

b (m12)Horizontal skewing.

c (m21)Vertical skewing.

d (m22)Vertical scaling.

e (dx)Horizontal moving.

f (dy)Vertical moving.

-------------------------------------------------------------------------------例子18------------------------------------------------------------------

九、合成

在前面的所有例子中、,我们总是将一个图形画在另一个之上,对于其他更多的情况,仅仅这样是远远不够的。比如,对合成的图形来说,绘制顺序会有限制。不过,我们可以利用 globalCompositeOperation 属性来改变这种状况。

globalCompositeOperation = type

type 是下面 13 种字符串值之一:

  1. source-over(default) //这是默认设置,新图像会覆盖在原有图像。

  2. source-in //仅仅会出现新图像与原来图像重叠的部分,其他区域都变成透明的。(包括其他的老图像区域也会透明)

  3. source-out //仅仅显示新图像与老图像没有重叠的部分,其余部分全部透明。(老图像也不显示)

  4. source-atop //新图像仅仅显示与老图像重叠区域。老图像仍然可以显示。

  5. destination-over //新图像会在老图像的下面。

  6. destination-in //仅仅新老图像重叠部分的老图像被显示,其他区域全部透明。

  7. destination-out //仅仅老图像与新图像没有重叠的部分。 注意显示的是老图像的部分区域。

  8. destination-atop //老图像仅仅仅仅显示重叠部分,新图像会显示在老图像的下面。

  9. lighter //新老图像都显示,但是重叠区域的颜色做加处理

  10. darken //保留重叠部分最黑的像素。(每个颜色位进行比较,得到最小的)

    blue: #0000ff

    red: #ff0000

    所以重叠部分的颜色:#000000

  11. lighten //保证重叠部分最量的像素。(每个颜色位进行比较,得到最大的)

    blue: #0000ff

    red: #ff0000

    所以重叠部分的颜色:#ff00ff

  12. xor //重叠部分会变成透明

  13. copy //只有新图像会被保留,其余的全部被清除(边透明)

-------------------------------------------------------------------------------例子19------------------------------------------------------------------

十、裁剪路径

clip() //把已经创建的路径转换成裁剪路径。

裁剪路径的作用是遮罩。只显示裁剪路径内的区域,裁剪路径外的区域会被隐藏。

注:clip()只能遮罩在这个方法调用之后绘制的图像,如果是clip()方法调用之前绘制的图像,则无法实现遮罩。

-------------------------------------------------------------------------------例子20------------------------------------------------------------------

十一、动画

11.1 动画的基本步骤

  1. 清空canvas

再绘制每一帧动画之前,需要清空所有。清空所有最简单的做法就是clearRect()方法

  1. 保存canvas状态

如果在绘制的过程中会更改canvas的状态(颜色、移动了坐标原点等),又在绘制每一帧时都是原始状态的话,则最好保存下canvas的状态

  1. 绘制动画图形

这一步才是真正的绘制动画帧

  1. 恢复canvas状态

如果你前面保存了canvas状态,则应该在绘制完成一帧之后恢复canvas状态。

11.2控制动画

我们可用通过canvas的方法或者自定义的方法把图像会知道到canvas上。正常情况,我们能看到绘制的结果是在脚本执行结束之后。例如,我们不可能在一个 for 循环内部完成动画。

也就是,为了执行动画,我们需要一些可以定时执行重绘的方法。

一般用到下面三个方法:

setInterval()

setTimeout()

requestAnimationFrame()

-------------------------------------------------------------------------------例子21------------------------------------------------------------------

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容

  • canvas元素的基础知识 在页面上放置一个canvas元素,就相当于在页面上放置了一块画布,可以在其中进行图形的...
    oWSQo阅读 10,279评论 0 19
  •   HTML5 添加的最受欢迎的功能就是 元素。这个元素负责在页面中设定一个区域,然后就可以通过 JavaScri...
    霜天晓阅读 3,006评论 0 2
  • 本文首发于我的个人博客:http://cherryblog.site/github项目地址:https://git...
    sunshine小小倩阅读 1,977评论 1 8
  • 什么是 canvas canvas 是 HTML5 新定义的标签,通过使用脚本(通常是 JavaScript)绘制...
    烟森儿阅读 508评论 0 0
  • 从结婚那天开始,我就和公婆住在一起。 他们视我为己出,特别是我亲爱的婆婆。 无法用语言表达,只好深深地深深地说: ...
    安闫阅读 267评论 0 4