H5 CanvasHTML5 中的一个元素,它拥有丰富的 API,允许开发人员通过 JS 在网页上绘制图形、动画和复杂的视觉效果-比如笔者之前的文章引力粒子特效 - 归为尘埃。

本文,我们来讲讲 globalCompositeOperation 这个重要的属性。

globalCompositeOperaton 是什么

globalCompositeOperation 顾名思义,为合成操作,用于设置新绘制的图形如何和已有图形进行合成。 这个属性接受一个字符串值,该值决定了合成的方式。

context.globalCompositeOperation = "source-over" 是其默认值,表示新图形会覆盖在已有图形之上。

合成操作方式

合成的方式有以下,我们结合案例,逐一来体验。

假设我们有素材如下:

H5 Canvas 中 globalCompositeOperation 的理解和应用_背景图

该素材的尺寸为 548px * 452px,包含透明的地方和红色不透明的地方。该图片作为已有图片

H5 Canvas 中 globalCompositeOperation 的理解和应用_图层_02

笔者头像作为新图,尺寸为 90px * 90px

<canvas id="canvas" width="548" height="452"></canvas>
  • 1.
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const imgOrigin = new Image();
imgOrigin.src = "path/to/orignal-image.png";
imgOrigin.onload = () => {
  ctx.drawImage(imgOrigin, 0, 0, 548, 452);
  
  // 设置 globalCompositeOperation 为 source-over
  ctx.globalCompositeOperation = "source-over";

  const imgTarget = new Image();
  imgTarget.src = "path/to/target-image.png";
  imgTarget.onload = () => {
    ctx.drawImage(imgTarget, 0, 0);
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • source-over:默认值,新图形绘制在已有图形上。

如上代码,得到的结果如图:

H5 Canvas 中 globalCompositeOperation 的理解和应用_图层_03

  • source-in:新图形仅在与已有图形重叠的地方显示

我们更改下目标绘制的尺寸 ctx.drawImage(imgTarget, 0, 0, 300, 300);

注意:以下案例新图的绘制尺寸均为 300px * 300px

H5 Canvas 中 globalCompositeOperation 的理解和应用_前端_04

  • source-out:新图形仅在不与已有图形重叠的地方显示。

H5 Canvas 中 globalCompositeOperation 的理解和应用_JavaScript_05

  • source-atop:新图形仅在与已有图形重叠的地方显示,且在已有图形之上。

H5 Canvas 中 globalCompositeOperation 的理解和应用_前端_06

  • destination-over:新图形绘制在已有图形之下

H5 Canvas 中 globalCompositeOperation 的理解和应用_图层_07

  • destination-in:已有图形仅在与新图形重叠的地方显示。

H5 Canvas 中 globalCompositeOperation 的理解和应用_JavaScript_08

  • destination-out:已有图形仅在不与新图形重叠的地方显示

H5 Canvas 中 globalCompositeOperation 的理解和应用_前端_09

  • destination-atop:已有图形仅在与新图形重叠的地方显示,且在新图形之上

H5 Canvas 中 globalCompositeOperation 的理解和应用_JavaScript_10

  • lighter:新图形和已经有的图形颜色值相加

H5 Canvas 中 globalCompositeOperation 的理解和应用_前端_11

  • copy:新图形完成替换已有图形

H5 Canvas 中 globalCompositeOperation 的理解和应用_前端_12

  • xor:新图形和已有图形进行抑或操作
body {
  // 方便比较,这里更改下背景颜色
  background-color: blue;
}
  • 1.
  • 2.
  • 3.
  • 4.

H5 Canvas 中 globalCompositeOperation 的理解和应用_背景图_13

案例

我们在合成图像的时候,针对不同形状的图层,比如开题给出的图👇

H5 Canvas 中 globalCompositeOperation 的理解和应用_背景图

那么我们可以通过 source-atop 将需要的图绘制在红色的区间。

如果,我们需要将蒙层的边框和上面的蒙层进行叠加,获取到新的蒙层内容。我们可以使用 destination-out

// 创建图层背景图片-这里统一没有重叠的地方,以原图的为标准,保留其原图不重叠的部分
async function createModelLayerBgImage(params: Params, backgroundImage?: string): Promise<string> {
    const croppedFrame = await createCroppedCanvas(params);
    // 没有背景图则取相框
    if (!backgroundImage) {
        return croppedFrame || whiteBgBase64;
    }

    const modelLayerWidth: number = params.modelLayerInfo.size.width;
    const modelLayerHeight: number = params.modelLayerInfo.size.height;
    const generateCanvas: HTMLCanvasElement | null = document.createElement("canvas");
    generateCanvas.width = modelLayerWidth;
    generateCanvas.height = modelLayerHeight;

    const generateCtx = generateCanvas.getContext("2d");
    if (!generateCtx) {
        console.error("Failed to get 2D context from generate canvas");
        return backgroundImage;

    }

    const bgImage = await loadImage(backgroundImage);
    generateCtx.drawImage(bgImage, 0, 0, modelLayerWidth, modelLayerHeight);

    // 先变成白色背景
    generateCtx.globalCompositeOperation = "source-in";
    generateCtx.fillStyle = "#FFFFFF";
    generateCtx.fillRect(0, 0, modelLayerWidth, modelLayerHeight);

  
    generateCtx.globalCompositeOperation = "destination-out";
    // 加载剪切的图层的边框背景图
    const croppedFrameImage = await loadImage(croppedFrame);
    generateCtx.drawImage(croppedFrameImage, 0, 0, modelLayerWidth, modelLayerHeight);

    // 返回base64编码的图片 - 变成白色背景图
    const base64Image = generateCanvas.toDataURL("image/png");

    return base64Image;

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.

参考

  • Canvas 教程
  • 引力粒子特效 - 归为尘埃
  • 组合 Compositing