【问题标题】:html canvas clip but with an imagehtml 画布剪辑,但带有图像
【发布时间】:2021-11-27 04:54:06
【问题描述】:

我一直在使用 html 画布合成尝试使用蒙版剪辑图案。

我遇到的主要问题是我的面具来自一个 svg,最外面的边框内有透明胶片。我希望从最外边界开始的整个内部都被图案填充。

Take this SVG for example 你可以看到有一个像素边框,然后是一些透明度,然后是一个不透明的红色内部斑点。我所做的合成工作按照文档所说的那样工作,单像素边框和红色内部部分拾取了我想要掩盖成这种形状的图案。问题是我想从单个像素边框开始屏蔽整个内部。

这是我认为剪辑可能会有所帮助的地方。但似乎剪辑只适用于手动绘制的路径,而不是来自 svg 的路径(至少我知道)。

有没有办法完成我想做的事情?

问候, 詹姆斯

【问题讨论】:

  • 所有 Canvas2D 命令直接对应 SVG 路径命令。因此,将 SVG 路径转换为画布方法调用应该很容易。
  • 前面的评论不正确,ellipse、arc和arcTo对椭圆没有使用相同的参数化,转换远非微不足道。

标签: svg html5-canvas mask clipping compositing


【解决方案1】:

Path2D constructor 接受 SVG 路径数据参数,它将解析为 SVG <path> 元素的 d 属性。

然后您可以将此 Path2D 对象与 clip() 方法一起使用:

(async () => {
// fetch the svg's path-data
const markup = await fetch("https://upload.wikimedia.org/wikipedia/commons/7/76/Autism_spectrum_infinity_awareness_symbol.svg").then(resp => resp.ok && resp.text());
const doc = new DOMParser().parseFromString(markup, "image/svg+xml");
const pathData = doc.querySelector("[d]").getAttribute("d");
// build our Path2D object and use it
const path = new Path2D(pathData);
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.clip(path);
// draw something that will get clipped
const rad = 30;
for(let y = 0; y < canvas.height; y += rad * 2 ) {
  for(let x = 0; x < canvas.width; x += rad * 2 ) {
    ctx.moveTo(x+rad, y);
    ctx.arc(x, y, rad, 0, Math.PI*2);
  }
}
ctx.fillStyle = "red";
ctx.fill();

})().catch(console.error);
&lt;canvas width="792" height="612"&gt;&lt;/canvas&gt;

如果您需要转换此路径数据(例如缩放或旋转),则可以创建第二个 Path2D 对象,并使用其.addPath(path, matrix) 方法来执行此操作:

// same as above, but smaller
(async () => {
const markup = await fetch("https://upload.wikimedia.org/wikipedia/commons/7/76/Autism_spectrum_infinity_awareness_symbol.svg").then(resp => resp.ok && resp.text());
const doc = new DOMParser().parseFromString(markup, "image/svg+xml");
const pathData = doc.querySelector("[d]").getAttribute("d");

const originalPath = new Path2D(pathData);
const path = new Path2D();
// scale by 0.5
path.addPath(originalPath, { a: 0.5, d: 0.5 });
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.clip(path);
// draw something that will get clipped
const rad = 15;
for(let y = 0; y < canvas.height; y += rad * 2 ) {
  for(let x = 0; x < canvas.width; x += rad * 2 ) {
    ctx.moveTo(x+rad, y);
    ctx.arc(x, y, rad, 0, Math.PI*2);
  }
}
ctx.fillStyle = "red";
ctx.fill();

})().catch(console.error);
&lt;canvas width="396" height="306"&gt;&lt;/canvas&gt;

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 2011-11-10
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 2014-02-05
    相关资源
    最近更新 更多