Canvas基础API使用教程

背景

canvas 应用非常广泛,可以做游戏引擎、表格文档、编辑器、图表、画板等。从基础 canvas API 入手,结合一定的算法、函数,可以绘制出任何你想要的效果,构建出更炫酷的应用。

绘制矩形

基础 API

  • fillStyle
  • fillRect
  • strokeStyle
  • strokeRect
  • lineWidth
  • lineCap
  • lineJoin
  • clearRect
  • toDataURL

代码

以下展示绘制两个矩形核心代码

const canvas = document.getElementById("canvas");

// 确认浏览器智慧城canvas元素
if (canvas.getContext) {
    // 获取到canvas上下文
    const context = canvas.getContext("2d");

    // 设置填充为红色
    // 可以使用css任何颜色值:颜色名、十六进制码、rgb、rgba、hsl、hsla
    context.fillStyle = "#ff0000";

    // 绘制正方形,用上一步设置的红色填充
    // x坐标10,y坐标10,宽度80,高度80
    context.fillRect(10, 10, 80, 80);

    // 设置描边为绿色
    // 可以使用css任何颜色值:颜色名、十六进制码、rgb、rgba、hsl、hsla
    context.strokeStyle = "green";

    // 设置描边宽度,任意的整数
    context.lineWidth = 10;

    // 绘制正方形,用上一步设置的绿色描边
    // x坐标10,y坐标10,宽度80,高度80
    context.strokeRect(10, 10, 80, 80);

    // 设置填充为蓝色半透明
    context.fillStyle = "rgba(0,0,255,0.5)";

    // 绘制矩形,用上一步设置的蓝色半透明填充
    context.fillRect(50, 50, 80, 100);

    // 设置线条末端样式
    /**
     * 平头:butt
     * 圆头:round
     * 方头:square
     * */
    context.lineCap = "square";

    // 设置线条相交的方式,默认是斜接
    /**
     * 圆交:round
     * 斜交:bevel
     * 斜接:miter
     * */
    context.lineJoin = "round";

    // 设置描边为蓝色
    context.strokeStyle = "blue";

    // 绘制矩形,用上一步设置的蓝色描边
    context.strokeRect(50, 50, 80, 100);

    // 清除画布上的矩形区域
    // x坐标100,y坐标100,宽度20,高度20
    context.clearRect(100, 100, 20, 20);

    // toDataURL 将 canvas 转化为base64字符串格式的图片地址
    const imgURI = canvas.toDataURL("image/png");
    const image = document.createElement("img");
    image.src = imgURI;
    document.body.appendChild(image);
}

Demo

详细的执行请查看下方demo

绘制路径

基础 API

  • arc(x,y,radius,startAngle,endAngle,counterclockwise)

    以(x,y)为圆心绘制一条弧线,弧线半径为 radius,起始和结束角度(以弧度表示)分别为startAngle和endAngle。最后一个参数表示startAngle 和 endAngle 是否按照逆时针方向计算,值为 false 表示按顺时针方向计算。

  • arcTo(x1,y1,x2,y2,radius)

    从上一点开始绘制一条弧线,到(x2,y2)为止,并且以给定半径radius穿过(x1,y1)

  • bezierCurveTo(c1x,c1y,c2x,c2y,x,y)

    从上一点开始绘制一条曲线,到(x,y)为止,并且以(c1x,c1y)和(c2x,c2y)为控制点

  • lineTo(x,y)

    从上一点开始绘制一条直线,到(x,y)为止

  • moveTo(x,y)

    将绘图游标移动到(x,y),不画线

  • quadraticCurveTo(cx,cy,x,y)

    从上一点开始绘制一条二次曲线,到(x,y)为止,并且以(cx,cy)作为控制点

  • rect(x,y,width,height)

    从点(x,y)开始绘制一个矩形,宽度和高度分别由width 和 height 指定

  • isPointInPath(x,y)

    接受x和y坐标作为参数,用于在路径被关闭之前确定画布上的某一点是否位于路径上

代码

以下展示绘制一个不带数字的时钟表盘

const drawing = document.getElementById('canvas');

if (drawing.getContext) {
    const context = drawing.getContext('2d');
    // 开始路径
    context.beginPath();

    // 绘制外圆
    context.arc(100, 100, 99, 0, 2 * Math.PI, false);

    // 绘制内圆
    context.moveTo(194, 100);
    context.arc(100, 100, 94, 0, 2 * Math.PI, false);

    // 绘制分针
    context.moveTo(100, 100);
    context.lineTo(100, 15);

    // 绘制时针
    context.moveTo(100, 100);
    context.lineTo(35, 100);

    // 描边路径
    context.stroke();
}

Demo

详细的执行请查看下方demo

绘制文本

基础 API

  • fillText(text, x, y,maxWidth)

    要绘制的文本字符串text,x坐标,y坐标,可选的最大像素宽度maxWidth

  • strokeText(text, x, y,maxWidth)

    要绘制的文本字符串text,x坐标,y坐标,可选的最大像素宽度maxWidth

  • measureText(text)

    要绘制的文本text,用于辅助确定文本的大小,返回一个TextMetrics对象,这个对象目前只有一个width属性

这三个API都以属性font、textAlign、textBaseline为基础

  • font:表示文本样式、大小及字体,用CSS中指定字体的格式来指定,例如"10px Arial"。
  • textAlign:表示文本对齐方式。可能的值有"start"、"end"、"left"、"right"和"center"。建议使用"start"和"end",不用使用"left"和"right",因为前两者的意思更稳妥,能同时适合从左到右和从右到左显示(阅读)的语言。
  • textBaseline:表示文本的基线。可能的值有"top"、"hanging"、"middle"、"alphabetic"、"ideographic"、"bottom"。

代码

以下展示绘制一个带数字的时钟表盘

const drawing = document.getElementById('canvas');

if (drawing.getContext) {
    
    // 省略 绘制表盘代码
    
    // 在表盘上显示一个数字12
    context.font = "bold 14px Arial";
    context.textAlign = "center";
    context.textBaseline = "middle";
    context.fillText("12",100,20);

    var text = context.measureText("foo"); // TextMetrics object
    console.log(text.width); // 21.765625;
}

Demo

详细的执行请查看下方demo

变换

基础 API

  • rotate(angle)

    围绕原点旋转图像angle弧度。

  • scale(scaleX,scaleY)

    缩放图像,在x方向乘以scaleX,在y方向乘以scaleY。scaleX的scaleY的默认值都是 1.0。

  • translate(x,y)

    将坐标原点移动到(x,y)。执行这个变换后,坐标(0,0)会变成之前由(x,y)表示的点。

  • transform(m1_1,m1_2,m2_1,m2_2,dx,dy)

    直接修改变换矩阵,方式是乘以如下矩阵

    m1_1  m1_2  dx
    m2_1  m2_2  dy
    0     0     1
    
  • setTransform(m1_1,m1_2,m2_1,m2_2,dx,dy)

    将变换矩阵重置为默认状态,然后再调用transform()。

代码

以下展示使用变换原点绘制一个时钟表盘

const drawing = document.getElementById('canvas');

if (drawing.getContext) {
    const context = drawing.getContext('2d');
    // 开始路径
    context.beginPath();

    // 绘制外圆
    context.arc(100, 100, 99, 0, 2 * Math.PI, false);

    // 绘制内圆
    context.moveTo(194, 100);
    context.arc(100, 100, 94, 0, 2 * Math.PI, false);

    // 变换原点,所有的数学计算都基于(0,0)而不是(100,100),使得绘制分针和时针的计算变得简单
    context.translate(100,100);

    // 旋转表针
    context.rotate(1)

    // 绘制分针
    context.moveTo(0, 0);
    context.lineTo(0, -85);

    // 绘制时针
    context.moveTo(0, 0);
    context.lineTo(-65, 0);

    // 描边路径
    context.stroke();
}

Demo

详细的执行请查看下方demo

上下文状态

基础 API

rotate、scale、translate、transform、fillStyle、strokeStyle等属性设置,会在当前上下文中一直有效,除非再对上下文进行什么修改,可以用save和restore来跟踪上下文的设置变化。

  • save()

    如果你知道将来还要返回某组属性与变换的组合,可以调用save()方法。调用这个方法后,当时所有设置都会进入一个栈结构,得以妥善保管。然后可以对上下文进行其他修改。

  • restore()

    如果想要回到之前保存的设置时,可以调用restore()方法,在保存设置的栈结构中向前返回一级,恢复之前的状态。连续调用save()可以把更多设置保存到栈结构中,之后再连续调用restore()则可以一级一级返回。

注意,save()方法保存的只是对绘图上下文的设置和变换,不会保存绘图上下文的内容。

代码

以下展示save和restore的作用

const drawing = document.getElementById('canvas');

if (drawing.getContext) {
    const context = drawing.getContext('2d');
    
    context.fillStyle = "#ff0000";
    context.save();

    context.fillStyle = "#00ff00";
    context.translate(100,100);
    context.save();

    // 从点(100,100)开始绘制蓝色矩形
    context.fillStyle = "#0000ff";
    context.fillRect(0,0,100,200);

    // 从点(110,110)开始绘制绿色矩形
    context.restore();
    context.fillRect(10,10,100,200);

    // 从点(0,0)开始绘制红色矩形
    context.restore();
    context.fillRect(0,0,100,200);
}

Demo

详细的执行请查看下方demo

总结

以上是在学习红宝书(JavaScript高级程序设计)关于Canvas画布的基础上做的一点学习笔记,还有更深入的canvas内容后续会分享。

参考

  • Canvas
  • JavaScript高级程序设计(第3版)

评论