这是我正在try 构建的一个简单的Web应用程序:一个随机 Select 的形状(从一组例如100个可能的形状中)将被放置在一个随机 Select 的较大的"容器"(从一组例如100个可能的容器中)的顶部.

有些容器是不透明的形状,完全填满了,但有些是轮廓(想象一个1px的笔划圆圈).

因此,在组合形状时,我需要进行XOR运算,本质上是:

  • 如果容器是轮廓:同时渲染形状和容器
  • 如果容器已装满:将形状从容器中剪切出来

这张图片有望传达出想要的结果:

my code desired output
enter image description here enter image description here

我有一个代码引用,它可以正常工作,但它是在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之神能帮我解决这个问题,我将永远感激不尽.谢谢!

推荐答案

下面是如何使用SVG滤镜进行XOR合成.您必须将形状放入Defs部分,并使用feImage将其导入滤镜,然后才能使用它.(这在Firefox上不起作用,因为Firefox不支持在feImage中使用片段标识符,所以您必须使用带data:URI的feImage来跨浏览器.)

不管怎样,这是普通的SVG Chrome/Safari版本.FeImage渲染/定位有错误,它不能正确调整非默认滤镜区域,因此您必须使用变换/平移将您的形状从滤镜区域的边缘移开,以使其正确渲染.准备好调整视框、滤镜区域和FeImage位置的尺寸,以获得正确的形状定位.

svg {
background: rgb(0,50, 50);
}
<svg width="800px" height="600px" viewBox="0 0 100 100">

<defs>

  <path transform="translate (2 5)" id="shapeOne"fill="blue" stroke="red" stroke-width="2" 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" />
    
<filter id="XORme">
  <feImage xlink:href="#shapeOne"/>
  <feComposite operator="xor" in="SourceGraphic"/>
</filter>

</defs>

<g filter="url(#XORme)">
  <path fill="green" stroke="gray" 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" />
  </g>
  
  
</svg>

Reactjs相关问答推荐

如何将google地址lat收件箱设置为输入值?

无法从正在使用Reaction的Electron 商务store 项目中的购物车中删除项目

在url中使用MongoDB对象ID被认为是不好的做法?

无法使用Reaction日期选取器和Next.js设置初始日期

无法找出状态正在被更改的位置

useState导致对函数的无休止调用

取消 Select 较高组件中的所有行

我如何使用 React toastify (Promise) toast 和邮箱 js

React useContext 的未定义返回值

在 React-Select 中显示多值的倒序

Suspense/Await - 解析数据加载/保存到状态后无限循环

导入样式化组件时未导入组件内容

意外的标记.您可能需要一个合适的加载器来处理这种文件类型.书?.img? /*#__PURE__*/React.createElement("img",

如何在 React 中单击鼠标的位置动态添加 div?

getAttribute 函数并不总是检索属性值

NextJs - 如何从站点 map 生成器中删除重复的 URL?

单击三个按钮之一后如何显示特定按钮的内容?单击其中一个按钮后应隐藏所有按钮

Material UI 安装和 React v. 18.2 出现问题

点击提交后自动添加#

material uireact ,如何从表格中删除阴影?试图找到 api 但找不到正确的属性