Canvas 基础汇总

语法

getContext()   用来获得渲染上下文和它的绘画功能(只有一个参数)

检测浏览器是否支持Canvas

1 var canvas = document.getElementById('tutorial');
2 
3 if (canvas.getContext){
4   var ctx = canvas.getContext('2d');
5   // drawing code here
6 } else {
7   // canvas-unsupported code here
8 }

绘制矩形

  • fillRect(x, y, width, height) 绘制一个填充的矩形
  • strokeRect(x, y, width, height) 绘制一个矩形的边框
  • clearRect(x, y, width, height) 清除指定矩形区域,让清除部分完全透明。

绘制路径

  • beginPath() 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
  • closePath() 闭合路径之后图形绘制命令又重新指向到上下文中。
  • stroke() 通过线条来绘制图形轮廓。
  • fill() 通过填充路径的内容区域生成实心的图形。
  1. 生成路径的第一步叫做beginPath()。本质上,路径是由很多子路径构成,这些子路径都是在一个列表中,所有的子路径(线、弧形、等等)构成图形。而每次这个方法调用之后,列表清空重置,然后我们就可以重新绘制新的图形。
  2. 第二步就是调用函数指定绘制路径
  3. 第三,就是闭合路径closePath(),不是必需的。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做。

注意:当前路径为空,即调用beginPath()之后,或者canvas刚建的时候,第一条路径构造命令通常被视为是moveTo(),无论实际上是什么。出于这个原因,你几乎总是要在设置路径之后专门指定你的起始位置。

注意:当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合

 

移动笔触

  • moveTo(xy)  将笔触移动到指定的坐标x以及y上。

当canvas初始化或者beginPath()调用后,通常会使用moveTo()函数设置起点。也能够使用moveTo()绘制一些不连续的路径。

线

 

  • lineTo(x, y)  绘制一条从当前位置到指定x以及y位置的直线。

圆弧

注意:arc()函数中表示角的单位是弧度,不是角度。角度与弧度的js表达式:

                              弧度 = (Math.PI / 180) * 角度。

 

二次贝塞尔曲线及三次贝塞尔曲线

  • quadraticCurveTo(cp1x, cp1y, x, y) 绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。
  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) 绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。

 

右边的图能够很好的描述两者的关系,二次贝塞尔曲线有一个开始点(蓝色)、一个结束点(蓝色)以及一个控制点(红色),而三次贝塞尔曲线有两个控制点。

参数x、y在这两个方法中都是结束点坐标。cp1x,cp1y为坐标中的第一个控制点,cp2x,cp2y为坐标中的第二个控制点。

 

矩形 

  • rect(xywidthheight) 绘制一个左上角坐标为(x,y),宽高为width以及height的矩形。

 

Path2D 对象

  作用:用来缓存或记录绘画命令,这样你将能快速地回顾路径。

  创建对象:

      Path2D()  Path2D()会返回一个新初始化的Path2D对象(可能将某一个路径作为变量——创建一个它的副本,或者将一个包含SVG path数据的字符串作为变量)。

1 new Path2D();     // 空的Path对象
2 new Path2D(path); // 克隆Path对象
3 new Path2D(d);    // 从SVG建立Path对象

  注意: 所有的路径方法比如 moveTorectarc quadraticCurveTo等,都可以在Path2D中使用。

  Path2D API 添加了 addPath作为将path结合起来的方法。当你想要从几个元素中来创建对象时,这将会很实用。

  比如:Path2D.addPath(path [, transform])
  添加了一条路径到当前路径(可能添加了一个变换矩阵)。

Path2D 示例

 1 function draw() {
 2   var canvas = document.getElementById('canvas');
 3   if (canvas.getContext){
 4     var ctx = canvas.getContext('2d');
 5 
 6     var rectangle = new Path2D();    // 创建实例
 7     rectangle.rect(10, 10, 50, 50);  // 创建矩形
 8 
 9     var circle = new Path2D();    // 创建实例
10     circle.moveTo(125, 35);       // 规定画笔起始点
11     circle.arc(100, 35, 25, 0, 2 * Math.PI);    // 创建圆
12 
13     ctx.stroke(rectangle);    // 生成边框图像
14     ctx.fill(circle);         // 生成实心图像
15   }
16 }

使用 SVG paths

这条路径将先移动到点 (M10 10) 然后再水平移动80个单位(h 80),然后下移80个单位 (v 80),接着左移80个单位 (h -80),再回到起点处 (z)。你可以在Path2D constructor 查看这个例子。

1 var p = new Path2D("M10 10 h 80 v 80 h -80 Z");

 

色彩 Colors

  注意:一旦设置了 strokeStyle 或者 fillStyle 的值,那么这个新值就会成为新绘制的图形的默认值。如果要给每个图形上不同的颜色,需要重新设置 fillStyle 或 strokeStyle 的值。

透明度 Transparency

  • globalAlpha = transparencyValue  这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。
  • 也可以用 strokeStyle  fillStyle 来设置 globalAlpha 的透明度
  • 1 // 指定透明颜色,用于描边和填充样式
    2 ctx.strokeStyle = "rgba(255,0,0,0.5)";
    3 ctx.fillStyle = "rgba(255,0,0,0.5)";

     

线型 Line styles

  • miterLimit = value   限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度。
  • getLineDash()   返回一个包含当前虚线样式,长度为非负偶数的数组。

lineCap 属性的例子

  • 属性 lineCap 的值决定了线段端点显示的样子。它可以为下面的三种的其中之一:buttround 和 square。默认是 butt。

lineJoin 属性的例子

  • lineJoin 的属性值决定了图形中两线段连接处所显示的样子。它可以是这三种之一:roundbevel 和 miter。默认是 miter

使用虚线

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

渐变 Gradients

  • createLinearGradient(x1, y1, x2, y2)  createLinearGradient 方法接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)
  • createRadialGradient(x1, y1, r1, x2, y2, r2)  createRadialGradient 方法接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。
  • 1 var lineargradient = ctx.createLinearGradient(0,0,150,150);
    2 var radialgradient = ctx.createRadialGradient(75,75,0,75,75,100);

     

  • gradient.addColorStop(position, color)  addColorStop 方法接受 2 个参数,position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。color 参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。
  • 1 var lineargradient = ctx.createLinearGradient(0,0,150,150);
    2 lineargradient.addColorStop(0,'white');
    3 lineargradient.addColorStop(1,'black');

     

图案样式 Patterns

  • createPattern(image, type)  该方法接受两个参数。Image 可以是一个 Image 对象的引用,或者另一个 canvas 对象。Type 必须是下面的字符串值之一:repeatrepeat-xrepeat-y 和 no-repeat

  注意: 用 canvas 对象作为 Image 参数在 Firefox 1.5 (Gecko 1.8) 中是无效的

  图案的应用跟渐变很类似的,创建出一个 pattern 之后,赋给 fillStyle 或 strokeStyle 属性即可

1 var img = new Image();
2 img.src = 'someimage.png';
3 var ptrn = ctx.createPattern(img,'repeat');

  注意:与 drawImage 有点不同,你需要确认 image 对象已经装载完毕,否则图案可能效果不对的。

 

阴影 Shadows

  • shadowOffsetX = float   shadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0
  • shadowOffsetY = float   shadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0
  • shadowBlur = float   shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0
  • shadowColor = color   shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。

文字阴影的例子

 1 function draw() {
 2   var ctx = document.getElementById('canvas').getContext('2d');
 3 
 4   ctx.shadowOffsetX = 2;
 5   ctx.shadowOffsetY = 2;
 6   ctx.shadowBlur = 2;
 7   ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
 8  
 9   ctx.font = "20px Times New Roman";
10   ctx.fillStyle = "Black";
11   ctx.fillText("Sample String", 5, 30);
12 }

 

Canvas 填充规则

当我们用到 fill(或者 clipisPointinPath )你可以选择一个填充规则,该填充规则根据某处在路径的外面或者里面来决定该处是否被填充,这对于自己与自己路径相交或者路径被嵌套的时候是有用的。

两个可能的值:

绘制文本

有样式的文本

  • font = value  当前我们用来绘制文本的样式. 这个字符串使用和 CSS font 属性相同的语法. 默认的字体是 10px sans-serif
  • textAlign = value  文本对齐选项. 可选的值包括:startendleftright or center. 默认值是 start
  • textBaseline = value  基线对齐选项. 可选的值包括:tophangingmiddlealphabeticideographicbottom。默认值是 alphabetic。
  • direction = value  文本方向。可能的值包括:ltrrtlinherit。默认值是 inherit
  • 1 ctx.font = "48px serif";
    2 ctx.textBaseline = "hanging";
    3 ctx.strokeText("Hello world", 0, 100);

     

预测量文本宽度

  示例:

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  var text = ctx.measureText("foo"); // TextMetrics object
  text.width; // 16;
}

 

获得需要绘制的图片

  • HTMLImageElement  这些图片是由Image()函数构造出来的,或者任何的<img>元素
  • HTMLVideoElement  用一个HTML的 <video>元素作为你的图片源,可以从视频中抓取当前帧作为一个图像
  • HTMLCanvasElement  可以使用另一个 <canvas> 元素作为你的图片源。
  • ImageBitmap  这是一个高性能的位图,可以低延迟地绘制,它可以从上述的所有源以及其它几种源中生成。

 

绘制图片

  • drawImage(image, x, y)  其中 image 是 image 或者 canvas 对象,x 和 y 是其在目标 canvas 里的起始坐标。

缩放 Scaling

切片 Slicing

  相框例子

 1 function draw() {
 2   var canvas = document.getElementById('canvas');
 3   var ctx = canvas.getContext('2d');
 4 
 5   // Draw slice
 6   ctx.drawImage(document.getElementById('source'),
 7                 33,71,104,124,21,20,87,104);
 8 
 9   // Draw frame
10   ctx.drawImage(document.getElementById('frame'),0,0);
11 }

 

状态的保存和恢复 Saving and restoring state

  • save()  保存画布(canvas)的所有状态
  • restore()  save 和 restore 方法是用来保存和恢复 canvas 状态的,都没有参数。Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

Canvas状态存储在栈中,每当save()方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:

  • 当前应用的变形(即移动,旋转和缩放,见下)
  • strokeStylefillStyleglobalAlphalineWidthlineCaplineJoinmiterLimitshadowOffsetXshadowOffsetYshadowBlurshadowColorglobalCompositeOperation 的值
  • 当前的裁切路径(clipping path),会在下一节介绍

 

移动 Translating

  • translate(x, y)  translate 方法接受两个参数。是左右偏移量,y 是上下偏移量,如右图所示。

 

旋转 Rotating

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

  旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate 方法。

 

缩放 Scaling

  • scale(x, y) scale 方法可以缩放画布的水平和垂直的单位。两个参数都是实数,可以为负数,x 为水平缩放因子,y 为垂直缩放因子,如果比1小,会比缩放图形, 如果比1大会放大图形。默认值为1, 为实际大小。

  画布初始情况下, 是以左上角坐标为原点的第一象限。如果参数为负实数, 相当于以x 或 y轴作为对称轴镜像反转 (例如, 使用translate(0,canvas.height); scale(1,-1); 以y轴作为对称轴镜像反转, 就可得到著名的笛卡尔坐标系,左下角为原点)。 

注: 画图的方法的长度单位并不是1个像素点。

例如 fillRect(0,0,100,100),表示长为100 * canvas默认单位长度,宽为100 * canvas默认单位长度。(canvas默认单位长度为1px)。

 

 

变形 Transforms

  • transform(m11, m12, m21, m22, dx, dy)  这个方法是将当前的变形矩阵乘上一个基于自身参数的矩阵,在这里我们用下面的矩阵:
  • 1 m11 m21 dx
    2 m12 m22 dy
    3 0     0     1

    如果任意一个参数是无限大,变形矩阵也必须被标记为无限大,否则会抛出异常。

    这个函数的参数各自代表如下:

    m11:水平方向的缩放

    m12:水平方向的倾斜偏移

    m21:竖直方向的倾斜偏移

    m22:竖直方向的缩放

    dx:水平方向的移动

    dy:竖直方向的移动

  • resetTransform()  重置当前变形为单位矩阵,它和调用以下语句是一样的:
1 ctx.setTransform(1, 0, 0, 1, 0, 0);

 

globalCompositeOperation

我们不仅可以在已有图形后面再画新图形,还可以用来遮盖指定区域,清除画布中的某些部分(清除区域不仅限于矩形,像clearRect()方法做的那样)以及更多其他操作。

 

裁切路径

  • clip()  将当前正在构建的路径转换为当前的裁剪路径。

  我们使用 clip()方法来创建一个新的裁切路径。

  默认情况下,canvas 有一个与它自身一样大的裁切路径(也就是没有裁切效果)。

绘制星星示例

 1 function draw() {
 2   var ctx = document.getElementById('canvas').getContext('2d');
 3   ctx.fillRect(0,0,150,150);
 4   ctx.translate(75,75);
 5 
 6   // Create a circular clipping path
 7   ctx.beginPath();
 8   ctx.arc(0,0,60,0,Math.PI*2,true);
 9   ctx.clip();
10 
11   // draw background
12   var lingrad = ctx.createLinearGradient(0,-75,0,75);
13   lingrad.addColorStop(0, '#232256');
14   lingrad.addColorStop(1, '#143778');
15   
16   ctx.fillStyle = lingrad;
17   ctx.fillRect(-75,-75,150,150);
18 
19   // draw stars
20   for (var j=1;j<50;j++){
21     ctx.save();
22     ctx.fillStyle = '#fff';
23     ctx.translate(75-Math.floor(Math.random()*150),
24                   75-Math.floor(Math.random()*150));
25     drawStar(ctx,Math.floor(Math.random()*4)+2);
26     ctx.restore();
27   }
28   
29 }
30 function drawStar(ctx,r){
31   ctx.save();
32   ctx.beginPath()
33   ctx.moveTo(r,0);
34   for (var i=0;i<9;i++){
35     ctx.rotate(Math.PI/5);
36     if(i%2 == 0) {
37       ctx.lineTo((r/0.525731)*0.200811,0);
38     } else {
39       ctx.lineTo(r,0);
40     }
41   }
42   ctx.closePath();
43   ctx.fill();
44   ctx.restore();
45 }

首先,我画了一个与 canvas 一样大小的黑色方形作为背景,然后移动原点至中心点。然后用 clip 方法创建一个弧形的裁切路径。裁切路径也属于 canvas 状态的一部分,可以被保存起来。如果我们在创建新裁切路径时想保留原来的裁切路径,我们需要做的就是保存一下 canvas 的状态。

裁切路径创建之后所有出现在它里面的东西才会画出来。在画线性渐变时我们就会注意到这点。然后会绘制出50 颗随机位置分布(经过缩放)的星星,当然也只有在裁切路径里面的星星才会绘制出来。

 

posted @ 2020-03-10 18:26  林中有风  阅读(309)  评论(0编辑  收藏  举报