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;

}

参考

相关推荐
超人不会飛26 分钟前
就着HTTP聊聊SSE的前世今生
前端·javascript·http
蓝胖子的多啦A梦29 分钟前
Vue+element 日期时间组件选择器精确到分钟,禁止选秒的配置
前端·javascript·vue.js·elementui·时间选选择器·样式修改
夏天想32 分钟前
vue2+elementui使用compressorjs压缩上传的图片
前端·javascript·elementui
The_cute_cat33 分钟前
JavaScript的初步学习
开发语言·javascript·学习
海天胜景36 分钟前
vue3 el-table 列增加 自定义排序逻辑
javascript·vue.js·elementui
今晚打老虎z40 分钟前
dotnet-env: .NET 开发者的环境变量加载工具
前端·chrome·.net
用户3802258598241 小时前
vue3源码解析:diff算法之patchChildren函数分析
前端·vue.js
烛阴1 小时前
XPath 进阶:掌握高级选择器与路径表达式
前端·javascript
小鱼小鱼干1 小时前
【JS/Vue3】关于Vue引用透传
前端
JavaDog程序狗1 小时前
【前端】HTML+JS 实现超燃小球分裂全过程
前端