【问题标题】:Layering masks in CSSCSS中的分层蒙版
【发布时间】:2019-02-07 03:29:04
【问题描述】:

我试图弄清楚 CSS 中是否有可能的图层蒙版。基本上我有一个表示某种阶段的 SVG。这使用 mask-image 显示为掩码,并且具有黑色背景色。大致如下:

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

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

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

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

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

按钮不知道任何关于 svgs 的信息,因为我根据状态动态添加 div 和上述 CSS。

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

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

【问题讨论】:

    标签: css svg less mask bem


    【解决方案1】:

    (发布另一个答案,因为这是超级不同)

    演示:

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

    前端: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。

    这几乎是不可能的。我说“漂亮”,因此有可能(使用超级非凡的解决方案)。

    几乎不可能的部分是为 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,也可以为其他语言/框架编写类似的代码):

    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 和 &lt;use&gt; 解决方案将非常简单...但我猜您想要纯 css 解决方案...

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

    PPS :如果重新构建的问题不是您想要的,那么您正在寻找的东西(分层蒙版)仅使用 css 是不可能的。

    【讨论】:

    • 我会接受这个作为答案,因为你已经证实了我的怀疑,这几乎是不可能轻易做到的。感谢您提供非常详细的答案!
    【解决方案2】:

    如果我正确理解了您的问题...您可以像这样简单地将额外的覆盖 svg 放置为 &lt;img&gt; 或内联 &lt;svg&gt;

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

    【讨论】:

    • 感谢您的回答。我希望封闭的 div 对 svgs/图像一无所知。我已经扩展了我的问题以反映这一点。如前所述,我根据状态动态添加 div 和类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 2014-09-13
    • 2012-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多