速记canvas

279 阅读5分钟

基本操作

const canvas = document.querySelect('canvas');
let ctx = canvas.getContext('2d');

绘制矩形

  1. 实心矩形 ctx.fillRexct(x,y,width,height);
    ctx.fillStyle = "#ff0000";
    ctx.fillRect(10,10,50,50);
    ctx.fillStyle = "rgba(0,0,255,0.5)";
    ctx.fillRect(30,30,50,50);

两个实心矩形
2. 描边矩形 ctx.strokeRect(x,y,width,height)

    ctx.strokeStyle = "#ff0000";
    ctx.strokeRect(10,10,50,50);
    ctx.strokeStyle = "rgba(0,0,255,0.5)";
    ctx.strokeRect(30,30,50,50);

两个矩形框框
3. 清除一个矩形块

/*这里把1部分的代码放到前面就行了*/
ctx.clearRect(40,40,10,10);

中间掏空

绘制路径

基本介绍

  • beginPath() 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径。
  • closePath() 闭合路径之后图形绘制命令又重新指向到上下文中
  • fill() 通过填充路径的内容区域生成实心的图形。会自动闭合;
  • stroke() 通过线条来绘制图形轮廓

画圆 arc(x,y,radius,startAngle,endAngle,counterclockwise)

x坐标,y坐标,开始弧度,结束弧度,布尔值(true表示逆时针画,false表示顺时针画(默认))

    ctx.beginPath()
    ctx.arc(30, 30, 20, 0, 2*Math.PI, false);
    ctx.fillStyle = "rgba(0,0,255,0.5)";
    ctx.fill();
    ctx.beginPath();
    ctx.arc(70,60,30,0,2*Math.PI);
    ctx.stroke();

实心圆和圆框框

画弧 arcTo(x1,y1,x2,y2,radius)

    ctx.beginPath();
    ctx.arc(30,30,20,0,2*Math.PI);
    ctx.moveTo(150,20);
    ctx.arcTo(150,100,50,20,30);
    ctx.stroke();

画直线

moveTo(x,y),移动笔触到(x,y) lineTo(x,y),从上一点开始绘制一条直线

    ctx.beginPath();
    ctx.moveTo(100,100);
    ctx.lineTo(150,150);
    ctx.stroke();
    ctx.moveTo(200,100);
    ctx.lineTo(200,200);
    ctx.lineTo(300,200);
    ctx.fill(); // 这里会自动闭合,所以不用把终点移到起始点也行

直线和三角形
将前面几个综合一下

    ctx.beginPath();
    ctx.arc(75,75,50,0,Math.PI*2,true); // 绘制
    ctx.moveTo(110,75);
    ctx.arc(75,75,35,0,Math.PI,false);   // 口(顺时针)
    ctx.moveTo(65,65);
    ctx.arc(60,65,5,0,Math.PI*2,true);  // 左眼
    ctx.moveTo(95,65);
    ctx.arc(90,65,5,0,Math.PI*2,true);  // 右眼
    ctx.stroke();

没有感情的笑脸

画曲线

  • 二次贝塞尔曲线 quadraticCurveTo(cx,cy,x,y) 从上一点开始绘制一条二次曲线,到(x,y),以(cx,cy)为控制点
    ctx.beginPath();
    ctx.moveTo(100,100);
    ctx.quadraticCurveTo(100,50,202,200);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(300,100);
    ctx.quadraticCurveTo(300,50,202,200);
    ctx.fill();

二次贝塞尔曲线

  • 三次贝塞尔曲线 bezierCurveTo(c1x,c1y,c2x,c2y,x,y); 从上一点绘制曲线到(x,y),以(c1x,c1y)和(c2x,c2y)为控制点
 ctx.beginPath();
 ctx.moveTo(75,40);
 ctx.bezierCurveTo(75,37,70,25,50,25);
 ctx.bezierCurveTo(20,25,20,62.5,20,62.5);
 ctx.bezierCurveTo(20,80,40,102,75,120);
 ctx.bezierCurveTo(110,102,130,80,130,62.5);
 ctx.bezierCurveTo(130,62.5,130,25,100,25);
 ctx.bezierCurveTo(85,25,75,37,75,40);
 ctx.fill();

三次贝塞尔曲线

绘制文本

  • fillText(text,x,y[, maxWidth]) 在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的.
  • strokeText(text,x,y[, maxWidth]) 在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的.
  • font = value 当前我们用来绘制文本的样式. 这个字符串使用和 CSS font 属性相同的语法. 默认的字体是 10px sans-serif。
  • textAlign = value 文本对齐选项. 可选的值包括:start, end, left, right or center. 默认值是 start
  • textBaseline = value 基线对齐选项. 可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。
  • direction = value 文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。
    ctx.font = "bold 20px Arial";
    ctx.textAlign = "center";
    ctx.textBaseLine = "middle";
    ctx.fillText("CANVAS", 100,100);
    ctx.font = "bold 20px Arial";
    ctx.textAlign = "start";
    ctx.textBaseLine = "middle";
    ctx.strokeText("CANVAS", 100,120);

文本图片

Path2D对象

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

let rectangle = new Path2D();
rectangle.rect(10,10,40,50);
let circle = new Path2D();
circle.arc(100,100,20,0,2*Math.PI);
ctx.fill(circle);
ctx.stroke(rectangle);

Path2D实例使用

变换

状态的保存恢复

  • save() 保存画布的所有状态,推入栈中
  • restore() 将状态推出栈
  • 状态:个人理解,就是ctx的一些属性,比如填充颜色,线条粗细等
    ctx.fillRect(0,0,150,150);
    ctx.save();
    ctx.fillStyle = "#09f"
    ctx.fillRect(15,15,120,120);
    ctx.save();
    ctx.fillStyle = "#fff";
    ctx.fillRect(30,30,90,90)
    ctx.restore();
    ctx.fillRect(45,45,60,60)
    ctx.restore();
    ctx.fillRect(60,60,30,30);
    ctx.font = "bold 20px Arial";
    ctx.fillText("我爱你", 200,200);
    ctx.save();
    ctx.font = "bold 12px Arial";
    ctx.fillText("我爱你", 200,250);
    ctx.restore();
    ctx.strokeText("我爱你",200,150)

sava与restore

移动,旋转

translate(xy) 将原点坐标移到(x,y)
rotate(angle) 围绕原点旋转图像angle弧度

  ctx.translate(75,75);

  for (var i=1;i<6;i++){ // Loop through rings (from inside to out)
    ctx.save();
    ctx.fillStyle = 'rgb('+(51*i)+','+(255-51*i)+',255)';
    for (var j=0;j<i*6;j++){ // draw individual dots
      ctx.rotate(Math.PI*2/(i*6));
      ctx.beginPath();
      ctx.arc(0,i*12.5,5,0,Math.PI*2,true);
      ctx.fill();
    }
    ctx.restore();
  }

旋转和平移的图片

缩放

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

    ctx.fillRect(20,20,40,20);
    ctx.scale(1,2);
    ctx.fillRect(20,40,40,20);

缩放
这样可以等到,我们日常数学里面的笛卡尔坐标系

translate(0,canvas.height);
scale(1,-1);

变形

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

m11:水平方向的缩放

m12:水平方向的倾斜偏移

m21:竖直方向的倾斜偏移

m22:竖直方向的缩放

dx:水平方向的移动

dy:竖直方向的移动

  • setTransform(m11, m12, m21, m22, dx, dy)
  • resetTransform() 重置当前变形为单位矩阵,它和调用以下语句是一样的:
ctx.setTransform(1, 0, 0, 1, 0, 0);
    var sin = Math.sin(Math.PI/6);
    var cos = Math.cos(Math.PI/6);
    ctx.translate(100, 100);
    var c = 0;
    for (var i=0; i <= 12; i++) {
      c = Math.floor(255 / 12 * i);
      ctx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
      ctx.fillRect(0, 0, 100, 10);
      ctx.transform(cos, sin, -sin, cos, 0, 0);
    }

    ctx.setTransform(-1, 0, 0, 1, 100, 100);
    ctx.fillStyle = "rgba(255, 128, 255, 0.5)";
    ctx.fillRect(0, 50, 100, 100);

示例

图像

阴影

渐变

合成