H5 Canvas 中 globalCompositeOperation 的理解和应用

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

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

globalCompositeOperaton 是什么

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

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

合成操作方式

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

假设我们有素材如下:

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

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

html 复制代码
<canvas id="canvas" width="548" height="452"></canvas>
javascript 复制代码
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);
  }
}
  • source-over:默认值,新图形绘制在已有图形上。

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

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

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

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

  • source-out:新图形仅在不与已有图形重叠的地方显示。
  • source-atop:新图形仅在与已有图形重叠的地方显示,且在已有图形之上。
  • destination-over:新图形绘制在已有图形之下
  • destination-in:已有图形仅在与新图形重叠的地方显示。
  • destination-out:已有图形仅在不与新图形重叠的地方显示
  • destination-atop:已有图形仅在与新图形重叠的地方显示,且在新图形之上
  • lighter:新图形和已经有的图形颜色值相加
  • copy:新图形完成替换已有图形
  • xor:新图形和已有图形进行抑或操作
CSS 复制代码
body {
  // 方便比较,这里更改下背景颜色
  background-color: blue;
}

案例

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

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

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

typescript 复制代码
// 创建图层背景图片-这里统一没有重叠的地方,以原图的为标准,保留其原图不重叠的部分
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;

}

参考

相关推荐
八了个戒8 分钟前
「数据可视化 D3系列」入门第六章:比例尺的使用
前端·javascript·信息可视化·数据可视化·canvas
少糖研究所15 分钟前
ACPA算法详解
前端
Mores27 分钟前
开源 | ImageMinify:轻量级智能图片压缩工具,为你的项目瘦身加速
前端
CHQIUU28 分钟前
PDF.js 生态中如何处理“添加注释\添加批注”以及 annotations.contents 属性
开发语言·javascript·pdf
执梦起航29 分钟前
webpack理解与使用
前端·webpack·node.js
ai大师29 分钟前
Cursor怎么使用,3分钟上手Cursor:比ChatGPT更懂需求,用聊天的方式写代码,GPT4、Claude 3.5等先进LLM辅助编程
前端
Json_32 分钟前
使用vue2技术写了一个纯前端的静态网站商城-鲜花销售商城
前端·vue.js·html
1024熙32 分钟前
【Qt】——理解信号与槽,学会使用connect
前端·数据库·c++·qt5
少糖研究所33 分钟前
ColorThief库是如何实现图片取色的?
前端
冴羽34 分钟前
SvelteKit 最新中文文档教程(22)—— 最佳实践之无障碍与 SEO
前端·javascript·svelte