CSS 中的分层蒙版

Layering masks in CSS

我想知道是否可以在 CSS 中使用图层蒙版。基本上我有一个 SVG 表示某种舞台。这使用 mask-image 显示为遮罩,并具有黑色背景色。大致如下:

mask-image: url(image.svg);
background-color: #000;
...

根据某些相关状态,我需要通过在其上叠加另一个 svg(例如感叹号)来引起对蒙版 svg 的注意。这会有另一种颜色,例如红色,但可能会根据情况而改变。

下面显示了一个粗略的示例,其中我有一个带有一些文本的按钮。正方形是一个 svg,它仅在某些状态(状态 A)存在时出现,在这种情况下,class 被添加到 div。正方形内的圆圈是相关状态,仅在正方形为状态 A 为真时出现,再加上一些附加状态。所以在 Less/BEM 结构中,这个额外的状态将作为修饰符实现:

&__state {
  mask-image: url(state.svg);
  background-color: #000;
  ...

  &--inner-state {
    mask-image: url(inner-state.svg);
    background-color: red;
    ...
  }
}

按钮对 svg 一无所知,因为我正在根据状态动态添加 divs 和以上 CSS。

这在 CSS 中容易实现吗?如前所述,我将 Less 与 BEM 结构一起使用,但我不一定需要与这些相关的答案。我对这个概念更感兴趣。

如有需要,请随时询问更多信息,如有任何帮助,我将不胜感激!

如果我没有正确理解你的问题......你可以简单地将额外的叠加 svg 放置为 <img> 或内联 <svg> 像这样:

.masked{
  width: 100px;
  position: relative;
}
.masked img{
  width: 100%;
  -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><circle cx='50' cy='50' r='50' fill='#fff'></circle></svg>") top left / cover;
  mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><circle cx='50' cy='50' r='50' fill='#fff'></circle></svg>") top left / cover;
}

.masked svg{
  width: 100%;
  position: absolute;
  top: 0;
  opacity: 0;
}

.masked:hover svg{
  opacity: 1;
}
<div class="masked">
  <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/Harry-Potter-1-.jpg" />
  <svg viewBox="0 0 100 100">
    <rect x="25" y="25" width="50" height="50" fill="red"></rect>
  </svg>
</div>

(发布另一个答案,因为这是非常不同的)

演示:

(理想情况下,您应该先阅读说明,但如果您想先查看最终结果...)

前端:https://codepen.io/devanshj/pen/OomRer

后端:https://glitch.com/edit/#!/mature-teller?path=server.js:8:0

解释:

在我看到这篇文章之前,我无法理解你试图用这些蒙版和背景(而不是直接 svgs)实现什么:Coloring SVGs in CSS Background Images...

本文中的解决方案对您不起作用的原因是您需要多个彩色 svg(而本文中的解决方案仅适用于单个 svg)

结合本文解决的问题,以及您想要的最终目标,我会像这样重构问题:

  1. 我想在一个元素上有多个 svg 背景
  2. 我也想控制每个svg的颜色
  3. 只有css解决方案。您不能更改 html.

这是不可能的。 "pretty"我说了,所以有可能(用超级超凡的解决方案)。

最不可能的部分是给 svg 着色。只有 css 的多个 svg 背景很简单。

但是,如果我做一些从 url 本身给 svg 着色的事情,比如 url(my-icon.svg?fill=#f00) 如果我能做到这一点,你的问题就解决了,我们可以做类似的事情:

.icon-a{
    background-image: url("a.svg?fill=%23000"); // # encoded to %23 so that server doesn't think #000 is the hash part of the request

    &.icon-b{
        background-image: url("a.svg?fill=%23000"), url("b.svg?fill=%23fff");

        &:hover{
            background-image: url("a.svg?fill=%23000"), url("b.svg?fill=%23f00");
        }
    }
}

这可以通过一些服务器代码来完成(这里使用 express 和 nodejs,也可以为其他 languages/frameworks 编写类似的代码):

app.get("/icons/*.svg", async (req, res) => {
    let svgCode = await readFileAsync(path.join(__dirname, req.path), {encoding: "utf8"});
    svgCode = svgCode.replace(/{{queryFill}}/g, req.query.fill);
    res.set("Content-Type", "image/svg+xml");
    res.send(svgCode);
});

和 svg:

<svg xmlns="http://www.w3.org/2000/svg">
    <style>
        .query-fill{
            fill: {{queryFill}};
        }
    </style>
    <rect x="0" y="0" width="100" height="100" class="query-fill"></rect>
</svg>

选择:

如果您允许我更改 html,使用内联 svg 和 <use> 解决方案将非常简单...但我猜您想要仅 css 的解决方案...

PS: 如果您想知道是否有没有任何服务器代码的解决方案?号

PPS :如果重构的问题不是您想要的,那么仅 css.

就无法实现您正在寻找的东西(分层蒙版)