0

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

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

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

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

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

问候,詹姆斯

4

1 回答 1

1

Path2D 构造函数接受一个 SVG 路径数据参数,它将被解析为SVG元素的d属性。<path>

然后,您可以将此 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);
<canvas width="792" height="612"></canvas>

如果您需要转换此路径数据(例如缩放或旋转),则可以创建第二个 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);
<canvas width="396" height="306"></canvas>

于 2021-10-13T03:29:04.707 回答