【问题标题】:SVG: Highlight multiple parts of an image (compositing)SVG:突出显示图像的多个部分(合成)
【发布时间】:2014-03-26 21:37:49
【问题描述】:

我想展示一张图片并在其上应用一个遮罩,这会使整个图像变暗,但一些区域会保留图像的原始内容。 就像使用带孔的面具一样。

我尝试了很多选择,但都无法奏效。 这是我得到的最接近的:

<image id="image1" xlink:href="image.png" height="100%" width="100%" />
<g if="image1mask" >
    <circle id="image1maskhole" cx="160" cy="120" r="80" fill="black" fill-opacity="100%" />
    <rect id="image1maskbase" x="0" y="0" width="100%" height="100%" fill="rgb(100, 100, 100)" fill-opacity="30%" comp-op="dst-out"/>
</g>

但是,蒙版中的圆圈已填充(黑色)。我希望它完全透明。 我尝试使用白色代替,但结果也是错误的。 我也尝试使用填充不透明度值,但我也无法使其工作。

我正在 chrome 上进行测试,但我将在不能很好地处理掩码的嵌入式浏览器中运行它。这就是为什么我要避免这种可能的解决方案(在 chrome 上完美运行):

<defs>
  <mask id="image1mask" >
      <rect x="0" y="0" width="100%" height="100%" fill="white" fill-opacity="30%" />
  <polygon points="30,30, 80,30, 50,120, 80,210, 30,210" fill="white" />
      <circle cx="160" cy="120" r="80" fill="white" />
  <rect x="250" y="30" width="50" height="180" fill="white" />
  </mask>
</defs>
<image id="image1" xlink:href="image.png" height="100%" width="100%" mask="url(#image1mask)" />

有人可以帮忙吗?

非常感谢。

---- 可能的解决方案:

我找到了一种方法。这实际上是一种解决方法,我有点担心性能。 我将它嵌入到 JavaFX2 应用程序中。不幸的是,它不能很好地工作。 掩码实际上将被解释为一个矩形,其中包含 mask1 的所有项目。 所以回到开头。

    <svg class="svg-graphic" width="320" height="240" >
    <defs>
        <clipPath id="mask1">
            <polygon points="30,30, 80,30, 50,120, 80,210, 30,210" fill="white" />
            <circle cx="160" cy="120" r="80" fill="white" />
            <rect x="250" y="30" width="50" height="180" fill="white" />
        </clipPath>
    </defs>

    <image id="backimage" xlink:href="image.png" height="100%" width="100%" style="opacity:0.3" />
    <image id="imagemask" xlink:href="image.png" height="100%" width="100%" clip-path="url(#mask1)"/>
</svg>

-- 另一种可能的解决方案:这个适用于嵌入式浏览器。

唯一的缺点是它使用了很多“假”图像。一个用于背景(阴影),一个用于遮罩中的每个孔(非阴影部分)。再一次,性能可能会受到影响。

    <svg class="svg-graphic" width="320" height="240" >
    <image id="image1back" xlink:href="image.png" height="100%" width="100%" style="opacity:0.3" />
    <g id="mask4" visibility="visible">
        <defs>
            <clipPath id="mask4def-1"><polygon points="30,30, 80,30, 50,120, 80,210, 30,210" /></clipPath>
            <clipPath id="mask4def-2"><circle cx="160" cy="120" r="50" /></clipPath>
            <clipPath id="mask4def-3"><rect x="250" y="30" width="50" height="180" /></clipPath>
        </defs>
        <image xlink:href="image.png" height="100%" width="100%" clip-path="url(#mask4def-1)"/>
        <image xlink:href="image.png" height="100%" width="100%" clip-path="url(#mask4def-2)"/>
        <image xlink:href="image.png" height="100%" width="100%" clip-path="url(#mask4def-3)"/>
    </g>
</svg>

它将产生与我在上面给出的掩蔽方法相同的结果(在我的嵌入式浏览器中不起作用)。 有谁知道这是否是一个有问题的方法? 谁有更好的想法?

【问题讨论】:

  • 我假设您的嵌入式浏览器不支持 SVG 过滤器?
  • 当你说 JavaFX WebView“不能很好地处理掩码”时,你是什么意思?

标签: svg


【解决方案1】:

试试这样的:

<defs>
  <mask id="image1mask" >
    <g>
      <rect id="image1maskbase" x="0" y="0" width="100%" height="100%" fill="rgb(100, 100, 100)" fill-opacity="30%" />
      <circle id="image1maskhole" cx="160" cy="120" r="80" fill="black" />
    </g>
  </mask>
</defs>

<image id="image1" xlink:href="image.png" height="100%" width="100%" mask="url(#imagemask)" />

【讨论】:

  • 感谢您的回答。请按照您的方法检查我刚刚为工作解决方案所做的编辑。它适用于 chrome,但在我正在使用的嵌入式浏览器中效果不佳。我必须在不使用面具的情况下找到另一种解决方案。
  • 我找到了一种创建蒙版的方法,就像在我的示例中提供的那样,除了它在阴影处是透明的,在透明处是阴影处。我需要对面。我使用了带有填充不透明度集的几何形状。但是我不能使用合成技术来得到我想要的。
【解决方案2】:

我现在有点不清楚您想要阴影哪些位以及您想要清除哪些位:/

我假设您希望“KOI”形状清晰而其余部分变暗。这是一个不使用面具的解决方案。

<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="320" height="240" >
    <defs>
        <clipPath id="mask1">
            <polygon points="30,30, 80,30, 50,120, 80,210, 30,210"/>
            <circle cx="160" cy="120" r="80" />
            <rect x="250" y="30" width="50" height="180" />
        </clipPath>
    </defs>

    <image xlink:href="http://placepuppy.it/320/240" height="100%" width="100%" />
    <rect height="100%" width="100%" fill="black" opacity="0.6" />
    <image xlink:href="http://placepuppy.it/320/240" height="100%" width="100%" clip-path="url(#mask1)"/>
</svg>

Demo here

还有一种解决方案只需要一个&lt;image&gt; 元素,但为此您需要将“KOI”形状组合成一个&lt;path&gt; 元素。

【讨论】:

  • 这正是我想做的。我实际上设法做到的方式与您几乎相同,但它在我必须使用的嵌入式浏览器中不起作用。所以我不能这样做。我可以使它工作的唯一方法是我在第一篇文章(已编辑)中描述的第二种可能的解决方案。非常感谢您的回答。这给了我解决问题的基本思路。
【解决方案3】:

BigBadaboom 提供的两种解决方案都在 Chrome 中运行良好。 但是,我必须使用 JavaFX2 嵌入式浏览器,而这些解决方案不能很好地工作。据我了解,它不能很好地管理口罩。 另一个限制与剪辑路径中的多个项目有关。浏览器实际上会将它们理解为一个大到足以容纳所有项目的单个矩形。

我可以让它在嵌入式浏览器中工作的唯一方法是叠加图像。 我从完全着色的基本图像开始。然后我添加一个图像,为我想要的每个突出显示的部分添加一个剪辑路径。

到目前为止,性能是可以接受的。但是,我不建议任何人在使用普通浏览器时遵循这种方法。如果你在一个页面中多次使用它可能会更慢。

<svg class="svg-graphic" width="320" height="240">http://placepuppy.it/320/240
    <image id="image1back" xlink:href="http://placepuppy.it/320/240" height="100%" width="100%" />
    <rect height="100%" width="100%" fill="black" style="opacity:0.6" />
    <g id="mask4" visibility="visible">
        <defs>
            <clipPath id="mask4def-1">
                <polygon points="30,30, 80,30, 50,120, 80,210, 30,210" />
            </clipPath>
            <clipPath id="mask4def-2">
                <circle cx="160" cy="120" r="50" />
            </clipPath>
            <clipPath id="mask4def-3">
                <rect x="250" y="30" width="50" height="180" />
            </clipPath>
        </defs>
        <image xlink:href="http://placepuppy.it/320/240" height="100%" width="100%" clip-path="url(#mask4def-1)" />
        <image xlink:href="http://placepuppy.it/320/240" height="100%" width="100%" clip-path="url(#mask4def-2)" />
        <image xlink:href="http://placepuppy.it/320/240" height="100%" width="100%" clip-path="url(#mask4def-3)" />
    </g>
</svg>

Demo here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-26
    • 2012-06-26
    • 2010-11-16
    • 2020-08-28
    • 2019-09-24
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多