SkyBlog

canvas

这篇文章发布于 2024年11月21日,星期四,01:37阅读 ? 次,0 条评论

不同于 svg,canvas 只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)。所有其他类型的图形都是通过一条或者多条路径组合而成的。

绘制图形

矩形

不同于路径函数,以下的三个函数绘制之后会马上显现在 canvas 上,即时生效。

  • 绘制一个填充的矩形

    fillRect(x, y, width, height)

  • 绘制一个矩形的边框

    strokeRect(x, y, width, height)

  • 清除指定矩形区域,让清除部分完全透明

    clearRect(x, y, width, height)

路径

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径,甚至一个子路径,都是闭合的。使用路径绘制图形需要一些额外的步骤。

首先,需要创建路径起始点;然后使用画图命令去画出路径;把路径封闭;一旦路径生成,就能通过描边或填充路径区域来渲染图形。

  • 新建一条路径,生成之后,图形绘制命令被指向到路径上生成路径

    beginPath()

  • 闭合路径之后图形绘制命令又重新指向到上下文中

    closePath()

  • 通过线条来绘制图形轮廓

    stroke()

  • 通过填充路径的内容区域生成实心的图形。可以选择填充规则 nonzero 或 evenodd,默认值:nonzero

    fill()

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

    clip()

路径绘制

  • 移动笔触

    moveTo(x, y)

  • 绘制直线

    lineTo(x, y)

  • 圆弧

    • 画一个以 (x,y) 为圆心的以 radius 为半径的圆弧(圆),从 startAngle 开始到 endAngle 结束,按照 anticlockwise 给定的方向(默认为 false 顺时针)来生成

      arc(x, y, radius, startAngle, endAngle [, anticlockwise])

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

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

  • 贝塞尔曲线

    • 绘制二次贝塞尔曲线,cp1x,cp1y 为一个控制点,x,y 为结束点

      quadraticCurveTo(cp1x, cp1y, x, y)

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

      bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

  • 矩形

    绘制一个左上角坐标为 x,y,宽为 width 高为 height 的矩形

    rect(x, y, width, height)

Path2D 对象

为了简化代码和提高性能,Path2D 对象已可以在较新版本的浏览器中使用,用来缓存或记录绘画命令,这样你将能快速地回顾路径。

可以将某一个路径作为变量创建它的副本,或者将一个包含 SVG path 数据的字符串作为变量。所有的路径方法都可以在 Path2D 中使用。

const circle = new Path2D()
circle.arc(100, 35, 25, 0, 2 * Math.PI)
 
const p = new Path2D('M10 10 h 80 v 80 h -80 Z')

样式

色彩

color 可以是表示 CSS 颜色值的字符串,渐变对象或者图案对象。

  • 设置图形的填充颜色

    fillStyle = color

  • 设置图形轮廓的颜色

    strokeStyle = color

渐变

可以用线性或者径向的渐变来填充或描边

  • 线性。接受 4 个参数,表示渐变的起点 (x1,y1) 与终点 (x2,y2)

    createLinearGradient(x1, y1, x2, y2)

  • 径向。接受 6 个参数,前三个定义一个以 (x1,y1) 为原点,半径为 r1 的圆,后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆

    createRadialGradient(x1, y1, r1, x2, y2, r2)

创建出 canvasGradient 对象后,我们就可以用 gradient.addColorStop(position, color) 方法给它上色了。position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置,color 参数必须是一个有效的 CSS 颜色值

const lineargradient = ctx.createLinearGradient(0, 0, 150, 150)
lineargradient.addColorStop(0, 'white')
lineargradient.addColorStop(1, 'black')
 
ctx.fillStyle = lineargradient
ctx.fillRect(0, 0, 150, 150)

透明度

除了可以绘制实色图形,我们还可以用 canvas 来绘制半透明的图形。通过设置 globalAlpha 属性或者使用一个半透明颜色作为轮廓或填充的样式。

globalAlpha = transparencyValue

线型

通过一系列属性来设置线的样式。

  • 设置线条宽度。属性值必须为正数。默认值是 1.0

    lineWidth = value

  • 设置线条末端样式。它可以是这三种之一:butt,round 和 square。默认是 butt

    lineCap = type

  • 设定线条与线条间接合处的样式。它可以是这三种之一:round、bevel 和 miter。默认是 miter

    lineJoin = type

  • 限制当两条线相交时交接处最大长度;所谓交接处长度(斜接长度)是指线条交接处内角顶点到外角顶点的长度

    miterLimit = value

  • 设置当前虚线样式。接受一个数组,来指定线段与间隙的交替

    setLineDash(segments)

  • 设置虚线样式的起始偏移量

    lineDashOffset = value

  • 返回一个包含当前虚线样式,长度为非负偶数的数组

    getLineDash()

绘制文本

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

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

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

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

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

文本的样式

  • 文本的样式。这个字符串使用和 CSS font 属性相同的语法,默认的字体是 "10px sans-serif"

    font = value

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

    textAlign = value

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

    textBaseline = value

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

    direction = value

measureText(text) 方法可以返回文本的属性

绘制图片

可以使用 HTMLImageElement、HTMLVideoElement、HTMLCanvasElement、ImageBitmap 中的一种作为图片的源

drawImage(image, x, y)

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

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

变形

状态的保存 save() 和恢复 restore()

  • 移动

    translate(x, y)

  • 旋转

    rotate(angle)

  • 缩放

    scale(x, y)

  • 综合变换

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

      和 css transform: matrix(a, b, c, d, e, f) 效果一样。二维齐次坐标变换的矩阵表达式如下

      描述
      a水平方向的缩放
      b竖直方向的倾斜偏移
      c水平方向的倾斜偏移
      d竖直方向的缩放
      e水平方向的移动
      f竖直方向的移动

      旋转角度 需要 满足如下条件:

      1. 逆时针

      2. 顺时针

    • setTransform(a, b, c, d, e, f)

      先重置变形,再应用变形

    • resetTransform()

      重置变形,它和调用 ctx.setTransform(1, 0, 0, 1, 0, 0) 效果一样