【问题标题】:Fill shape with no-repeat image pattern: unwanted contour line用不重复的图像图案填充形状:不需要的轮廓线
【发布时间】:2023-04-06 15:58:02
【问题描述】:

在我的 Angular 应用程序中,用户可以将图像插入 SVG 形状并以交互方式对图像应用变换。默认情况下,图像会填充形状。

它运作良好,除了一个非常烦人的问题发生在以下情况:

  • 形状没有描边
  • 图像的一侧比另一侧暗得多

当满足这些条件时,在图像较亮的形状一侧会出现一条非常细的线。例如,如果图像的底部比顶部暗得多,则细线将出现在形状的顶部。那条线来自图像的另一侧,就好像图案试图重复一样。我知道图像模式没有像no-repeat 属性这样的东西,所以我设置了以下模式属性以避免重复:

<pattern patternUnits="objectBoundingBox" x="0" y="0" width="1" height="1" ...>

它有效,但并不完美。细线在屏幕上并不总是可见,即使在缩放时也是如此,但大部分时间都是如此。它给我们带来了麻烦,因为这些 SVG 形状是书页的一部分,而细线通常最终会在最终打印中可见。

有没有完全避免模式重复的好方法?我尝试扩展图案以使其溢出形状,但额外的尺寸必须有点显着才能有效:

<pattern x="-0.01" y="-0.01" width="1.02" height="1.02" ...>

当我在 Chrome 浏览器中运行下面的代码 sn-p 时,不需要的蓝色细线在形状顶部可见。但是,该问题并非特定于 Chrome;我也在 Firefox 上看到它。

<div style="padding: 20px; width: 180px; height: 150px; background-color: yellow;">
  <svg height="100%" width="100%" x="0%" y="0%" viewBox="0 0 1600 1200">
    <defs>
      <pattern id="pattern1" patternUnits="objectBoundingBox" 
        preserveAspectRatio="xMidYMid slice" 
        width="1" height="1" x="0" y="0" viewBox="0 0 1600 1200">
        <image width="1600" height="1200" x="0" y="0" 
          xlink:href="https://i.ibb.co/vZ9spGH/1600x1200-1.png"></image>
      </pattern>
    </defs>
    <rect fill="url('#pattern1')" height="100%" width="100%" x="0%" y="0%"></rect>
    </svg>
</div>

【问题讨论】:

  • 但是一个模式只是为了重复它的内容,所以你为什么不直接使用纯图像,因为它不应该重复呢?
  • @philipp - 我可以在形状中包含普通图像吗?我在问题中展示了一个简单的案例,但形状可以是任何类型的路径,并且可以有笔划。
  • 如果整个点都将图像裁剪为一个形状,请使用&lt;clipPath&gt;,可能与clipPathUnits="objectBoundingBox" 一起使用,并将形状的大小标准化为1。
  • 关于你的问题,在rect上设置style="shape-rendering:geometricPrecision"有什么效果吗?
  • @ccprog - 我尝试设置 shape-rendering 样式/属性,但细重复线仍然存在。解释一下这个特性:每个 SVG 元素都是一个框架,用户可以在其中插入图片;一个特定的形状被设置为图像容器。用户可以交互:插入图片,更改形状的笔画粗细,移动,调整大小和旋转框架,移动,调整大小和旋转框架内的图片。这就是为什么让形状内部的图像对我来说很自然。 preserveAspectRatio 模式属性也便于缩放。

标签: svg shapes fill


【解决方案1】:

形状填充使用过滤器相当简单:

<div style="padding: 20px; width: 180px; height: 150px; background-color: yellow;">
  <svg height="100%" width="100%" x="0%" y="0%" viewBox="0 0 1600 1200">
    <defs>
      <filter id="simple-image-fill" primitiveUnits="userSpaceOnUse"> 
      
        <feImage width="1600" height="1200" x="0" y="0" preserveAspectRatio="xMidYMid slice"
          xlink:href="https://i.ibb.co/vZ9spGH/1600x1200-1.png" result="image-res"/>
          <feComposite operator="in" in2="SourceGraphic" in="image-res"/>
      </filter>
    </defs>
    <rect filter="url(#simple-image-fill)" height="100%" width="100%" x="0%" y="0%"/>
    </svg>
</div>

【讨论】:

  • 这看起来很有希望。谢谢!我现在不能完全测试它,但我会尽快。
  • 过滤器会在有笔画时覆盖笔画,不是吗?
  • 是的。您可以使用一种技术来保留笔触,但它有点复杂,需要针对每种笔触颜色使用特定的过滤器。
  • 那很不幸。我不明白的是,为什么 SVG 模式没有 no-repeat 选项。特别是因为使用模式是将图像包含在形状中的唯一方法(AFAIK)。不需要重复的用例不能太例外。
  • 您也可以尝试将图案的起始位置向上移动一点 - 这似乎可以消除错误:width="1" height="1.01" x="0" y="-0.01 " viewBox="0 0 1600 1200"
猜你喜欢
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
  • 2020-05-23
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
相关资源
最近更新 更多