You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现两个重叠SVG图形的XOR运算?

问题:实现SVG图形与容器的XOR组合效果

我正在开发一个简易Web应用,核心逻辑是:从100种可选图形中随机选取一个,放置在从100种可选容器中随机选取的更大容器之上。容器分为两类:

  • 填充样式:完全填充的不透明图形
  • 轮廓样式:仅含轮廓的图形(例如1px描边的圆形)

组合规则如下:

  • 若容器是轮廓样式:同时渲染图形与容器
  • 若容器是填充样式:将图形从容器中挖去

效果对比

当前代码效果预期效果
当前效果预期效果

我曾在React Native中使用Shopify的React Native Skia库实现过类似效果,该库提供了SVG原生不具备的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>

填充样式容器

<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>

轮廓样式容器

<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>

测试代码

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"));

我需要让OutputSVG组件实现图形与容器的XOR组合逻辑,后续还要将生成的图形作为蒙版,用复杂渐变填充(而非纯黑色)。我对SVG不熟悉,找不到符合需求的示例代码,希望得到解决方案。

内容的提问来源于stack exchange,提问作者doteth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 00:15:38