这是我正在try 构建的一个简单的Web应用程序:一个随机 Select 的形状(从一组例如100个可能的形状中)将被放置在一个随机 Select 的较大的"容器"(从一组例如100个可能的容器中)的顶部.
有些容器是不透明的形状,完全填满了,但有些是轮廓(想象一个1px的笔划圆圈).
因此,在组合形状时,我需要进行XOR运算,本质上是:
- 如果容器是轮廓:同时渲染形状和容器
- 如果容器已装满:将形状从容器中剪切出来
这张图片有望传达出想要的结果:
我有一个代码引用,它可以正常工作,但它是在Reaction Native中(遗憾的是不能在这里共享它),使用的是Shopify的React Native Skia library,因为该库有一个blendMode="xor"
选项,而SVG本身似乎没有这个选项.
我找到了<feComposite operation="xor">
个,但这似乎适用于像素,而不是矢量空间.老实说,这应该很好,但我也不太能让它工作.
下面是一个样例形状和两种容器各自的样例:
- 形状:
<path d="M8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8C0 12.4183 3.58172 16 8 16ZM8 13C10.7614 13 13 10.7614 13 8C13 5.23858 10.7614 3 8 3C5.23858 3 3 5.23858 3 8C3 10.7614 5.23858 13 8 13Z" fillType="evenOdd"></path>
- 容器1(已填满):
<path d="M0 8C0 3.58172 3.58172 0 8 0H28C32.4183 0 36 3.58172 36 8V28C36 32.4183 32.4183 36 28 36H8C3.58172 36 0 32.4183 0 28V8Z"></path>
- 容器2(轮廓):
<path d="M18 2.76923C14.1765 2.76923 11.0769 5.8688 11.0769 9.69231V11.0769H9.69231C5.8688 11.0769 2.76923 14.1765 2.76923 18C2.76923 21.8235 5.8688 24.9231 9.69231 24.9231H11.0769V26.3077C11.0769 30.1312 14.1765 33.2308 18 33.2308C21.8235 33.2308 24.9231 30.1312 24.9231 26.3077V24.9231H26.3077C30.1312 24.9231 33.2308 21.8235 33.2308 18C33.2308 14.1765 30.1312 11.0769 26.3077 11.0769H24.9231V9.69231C24.9231 5.8688 21.8235 2.76923 18 2.76923ZM8.39391 8.39391C9.02837 3.65493 13.0874 0 18 0C22.9126 0 26.9716 3.65493 27.6061 8.39391C32.3451 9.02837 36 13.0874 36 18C36 22.9126 32.3451 26.9716 27.6061 27.6061C26.9716 32.3451 22.9126 36 18 36C13.0874 36 9.02837 32.3451 8.39391 27.6061C3.65493 26.9716 0 22.9126 0 18C0 13.0874 3.65493 9.02837 8.39391 8.39391Z" fillType="evenOdd"></path>
下面是CodePen段以下代码:
const shape = (
<path
d="M8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8C0 12.4183 3.58172 16 8 16ZM8 13C10.7614 13 13 10.7614 13 8C13 5.23858 10.7614 3 8 3C5.23858 3 3 5.23858 3 8C3 10.7614 5.23858 13 8 13Z"
fill-type="evenOdd"
></path>
);
const containerOutline = (
<path
d="M18 2.76923C14.1765 2.76923 11.0769 5.8688 11.0769 9.69231V11.0769H9.69231C5.8688 11.0769 2.76923 14.1765 2.76923 18C2.76923 21.8235 5.8688 24.9231 9.69231 24.9231H11.0769V26.3077C11.0769 30.1312 14.1765 33.2308 18 33.2308C21.8235 33.2308 24.9231 30.1312 24.9231 26.3077V24.9231H26.3077C30.1312 24.9231 33.2308 21.8235 33.2308 18C33.2308 14.1765 30.1312 11.0769 26.3077 11.0769H24.9231V9.69231C24.9231 5.8688 21.8235 2.76923 18 2.76923ZM8.39391 8.39391C9.02837 3.65493 13.0874 0 18 0C22.9126 0 26.9716 3.65493 27.6061 8.39391C32.3451 9.02837 36 13.0874 36 18C36 22.9126 32.3451 26.9716 27.6061 27.6061C26.9716 32.3451 22.9126 36 18 36C13.0874 36 9.02837 32.3451 8.39391 27.6061C3.65493 26.9716 0 22.9126 0 18C0 13.0874 3.65493 9.02837 8.39391 8.39391Z"
fill-type="evenOdd"
></path>
);
const containerFilled = (
<path d="M0 8C0 3.58172 3.58172 0 8 0H28C32.4183 0 36 3.58172 36 8V28C36 32.4183 32.4183 36 28 36H8C3.58172 36 0 32.4183 0 28V8Z"></path>
);
const OutputSVG = ({ shape, container }) => {
return (
<svg>
<defs>
<filter id="output">
<g id="shape" transform="translate(10,10)">
{shape}
</g>
<feComposite operator="xor" in="shape" />
</filter>
</defs>
<g
id="container"
filter="url(#output)"
>
{container}
</g>
</svg>
);
};
const App = () => {
return (
<div>
<p>Outline</p>
<OutputSVG shape={shape} container={containerFilled} />
<p>Filled</p>
<OutputSVG shape={shape} container={containerOutline} />
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
我正在try 让OutputSVG
组件对形状和容器执行XOR操作.(实际上,一旦我弄清楚这一步,整个输出形状很可能是一个蒙版,因为我希望结果形状的"填充"是复杂的渐变,而不仅仅是黑色填充.)
我不太擅长SVG,所以我可能做了一些完全错误的事情,但我发现很难找到好的示例代码来做我想要的事情.
如果有一位SVG之神能帮我解决这个问题,我将永远感激不尽.谢谢!