Canvas 常用 API

8 阅读3分钟

Canvas 常用 API

基础设置

const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");

基础图形绘制

矩形绘制

// 绘制填充矩形
ctx.fillRect(x, y, width, height);

// 绘制描边矩形
ctx.strokeRect(x, y, width, height);

// 清除矩形区域
ctx.clearRect(x, y, width, height);

路径绘制

// 开始新路径
ctx.beginPath();

// 移动画笔到指定位置
ctx.moveTo(x, y);

// 绘制直线到指定位置
ctx.lineTo(x, y);

// 绘制矩形路径
ctx.rect(x, y, width, height);

// 绘制圆弧
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);

// 绘制椭圆
ctx.ellipse(
  x,
  y,
  radiusX,
  radiusY,
  rotation,
  startAngle,
  endAngle,
  anticlockwise
);

// 绘制二次贝塞尔曲线
ctx.quadraticCurveTo(cpx, cpy, x, y);

// 绘制三次贝塞尔曲线
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);

// 关闭路径
ctx.closePath();

// 填充路径
ctx.fill();

// 描边路径
ctx.stroke();

样式与颜色

颜色设置

// 设置填充颜色
ctx.fillStyle = "red";
ctx.fillStyle = "#ff0000";
ctx.fillStyle = "rgb(255, 0, 0)";
ctx.fillStyle = "rgba(255, 0, 0, 0.5)";

// 设置描边颜色
ctx.strokeStyle = "blue";
ctx.strokeStyle = "#0000ff";
ctx.strokeStyle = "rgb(0, 0, 255)";
ctx.strokeStyle = "rgba(0, 0, 255, 0.5)";

线条样式

// 设置线条宽度
ctx.lineWidth = 5;

// 设置线条末端样式
ctx.lineCap = "butt"; // 默认
ctx.lineCap = "round"; // 圆形
ctx.lineCap = "square"; // 方形

// 设置线条连接处样式
ctx.lineJoin = "miter"; // 默认,尖角
ctx.lineJoin = "round"; // 圆角
ctx.lineJoin = "bevel"; // 斜角

// 设置虚线
ctx.setLineDash([10, 5]); // 实线10px,间隔5px
ctx.setLineDash([]); // 重置为实线

渐变

// 线性渐变
const linearGradient = ctx.createLinearGradient(x0, y0, x1, y1);
linearGradient.addColorStop(0, "red");
linearGradient.addColorStop(0.5, "yellow");
linearGradient.addColorStop(1, "blue");
ctx.fillStyle = linearGradient;

// 径向渐变
const radialGradient = ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
radialGradient.addColorStop(0, "white");
radialGradient.addColorStop(1, "black");
ctx.fillStyle = radialGradient;

阴影

// 设置阴影颜色
ctx.shadowColor = "rgba(0, 0, 0, 0.5)";

// 设置阴影模糊度
ctx.shadowBlur = 10;

// 设置阴影偏移
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;

文本绘制

文本属性

// 设置字体
ctx.font = "48px sans-serif";
ctx.font = "bold 32px Arial";
ctx.font = "italic 24px Georgia";

// 设置文本对齐方式
ctx.textAlign = "start"; // 默认
ctx.textAlign = "end";
ctx.textAlign = "left";
ctx.textAlign = "right";
ctx.textAlign = "center";

// 设置文本基线
ctx.textBaseline = "top";
ctx.textBaseline = "hanging";
ctx.textBaseline = "middle";
ctx.textBaseline = "alphabetic"; // 默认
ctx.textBaseline = "ideographic";
ctx.textBaseline = "bottom";

文本绘制方法

// 绘制填充文本
ctx.fillText(text, x, y, maxWidth);

// 绘制描边文本
ctx.strokeText(text, x, y, maxWidth);

// 测量文本宽度
const metrics = ctx.measureText(text);
const width = metrics.width;

图像处理

绘制图像

const img = new Image();
img.src = "image.jpg";
img.onload = () => {
  // 绘制完整图像
  ctx.drawImage(img, x, y);

  // 绘制缩放图像
  ctx.drawImage(img, x, y, width, height);

  // 裁剪并绘制图像
  ctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
};

图像数据操作

// 获取图像数据
const imageData = ctx.getImageData(x, y, width, height);
const data = imageData.data;

// data 数组结构:[r, g, b, a, r, g, b, a, ...]
// 每个像素占 4 个位置(RGBA)

// 修改像素数据
for (let i = 0; i < data.length; i += 4) {
  const r = data[i];
  const g = data[i + 1];
  const b = data[i + 2];
  const a = data[i + 3];

  // 修改像素
  data[i] = 255; // R
  data[i + 1] = 0; // G
  data[i + 2] = 0; // B
  data[i + 3] = 255; // A
}

// 将修改后的数据放回画布
ctx.putImageData(imageData, x, y);

变换操作

状态管理

// 保存当前状态
ctx.save();

// 恢复之前保存的状态
ctx.restore();

变换方法

// 平移
ctx.translate(x, y);

// 旋转(弧度制)
ctx.rotate(angle);

// 缩放
ctx.scale(x, y);

// 自定义变换矩阵
ctx.transform(a, b, c, d, e, f);

// 重置变换矩阵
ctx.setTransform(a, b, c, d, e, f);

变换示例

// 绘制旋转的矩形
ctx.save();
ctx.translate(100, 100);
ctx.rotate(Math.PI / 4); // 旋转45度
ctx.fillRect(-50, -50, 100, 100);
ctx.restore();

// 绘制缩放的图形
ctx.save();
ctx.translate(200, 200);
ctx.scale(2, 0.5); // 水平放大2倍,垂直缩小一半
ctx.fillRect(-25, -25, 50, 50);
ctx.restore();

合成操作

全局透明度

ctx.globalAlpha = 0.5; // 设置全局透明度为50%

合成模式

// 设置合成模式
ctx.globalCompositeOperation = "source-over"; // 默认
ctx.globalCompositeOperation = "source-in";
ctx.globalCompositeOperation = "source-out";
ctx.globalCompositeOperation = "source-atop";
ctx.globalCompositeOperation = "destination-over";
ctx.globalCompositeOperation = "destination-in";
ctx.globalCompositeOperation = "destination-out";
ctx.globalCompositeOperation = "destination-atop";
ctx.globalCompositeOperation = "lighter";
ctx.globalCompositeOperation = "copy";
ctx.globalCompositeOperation = "xor";
ctx.globalCompositeOperation = "multiply";
ctx.globalCompositeOperation = "screen";
ctx.globalCompositeOperation = "overlay";
ctx.globalCompositeOperation = "darken";
ctx.globalCompositeOperation = "lighten";
ctx.globalCompositeOperation = "color-dodge";
ctx.globalCompositeOperation = "color-burn";
ctx.globalCompositeOperation = "hard-light";
ctx.globalCompositeOperation = "soft-light";
ctx.globalCompositeOperation = "difference";
ctx.globalCompositeOperation = "exclusion";
ctx.globalCompositeOperation = "hue";
ctx.globalCompositeOperation = "saturation";
ctx.globalCompositeOperation = "color";
ctx.globalCompositeOperation = "luminosity";

常用合成模式说明

  • source-over: 新图形覆盖在旧图形之上(默认)
  • destination-over: 新图形在旧图形之下
  • lighter: 颜色值相加
  • multiply: 颜色值相乘(变暗)
  • screen: 颜色值反转相乘再反转(变亮)
  • overlay: 结合 multiply 和 screen

像素级操作

ImageData 对象

// 创建空的 ImageData
const imageData = ctx.createImageData(width, height);

// 获取画布区域的 ImageData
const imageData = ctx.getImageData(x, y, width, height);

// ImageData 属性
imageData.width; // 宽度
imageData.height; // 高度
imageData.data; // Uint8ClampedArray 数组,包含 RGBA 数据

像素遍历

const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;

for (let y = 0; y < canvas.height; y++) {
  for (let x = 0; x < canvas.width; x++) {
    const index = (y * canvas.width + x) * 4;
    const r = data[index];
    const g = data[index + 1];
    const b = data[index + 2];
    const a = data[index + 3];

    // 处理像素
  }
}

ctx.putImageData(imageData, 0, 0);

作者:李伟_Li慢慢 链接:[canvas-基础篇 - 李伟_Li慢慢的专栏 - 掘金 (juejin.cn)] 来源:稀土掘金