如何使用 SVG 路径屏蔽 DIV

问题描述 投票:0回答:1

我尝试创建一个 HTML/CSS/JS 漏斗图,具有简单的前端结构,为此,我将漏斗段放置为弹性行:

document.addEventListener( 'DOMContentLoaded', function() {
    let funnels = document.getElementsByClassName( 'funnel' );
    
    for( let i = 0; i < funnels.length; i++ ) {
        let segments = funnels[i].children[1].children;
        
        for( let j = 0; j < segments.length; j++ ) {
            const from = parseFloat( segments[j].getAttribute( 'data-from' ) );
            const to = parseFloat( segments[j].getAttribute( 'data-to' ) );
            const difference = ( from - to ) / 2;
            
            const d = `M 0 ${50 - from * 50} Q 25 ${50 - from * 50} 50 ${50 - ( ( to + difference ) * 50 )} T 100 ${50 - to * 50} V 100 ${50 + to * 50} Q 75 ${50 + to * 50} 50 ${50 + ( ( to + difference ) * 50 )} T 0 ${50 + from * 50} V ${50 - from * 50} Z`;
            const svg = '<svg id="fcm-' + i + '-' + j + '" viewBox="0 0 100 100" preserveAspectRatio="none" style="width: 100%; height: 100%;"><path d="' + d + '" fill="black"></path></svg>';
            
            segments[j].style.setProperty( '--mask', ( 'url( #fcm-' + i + '-' + j + ' )' ) );
            segments[j].innerHTML = svg;
        }
    }
} );
.funnel > div:last-child {
    display: flex;
    flex-direction: row;
    height: 300px;
}

.funnel > div:last-child div {
    background: green;
    height: 100%;
    position: relative;
    width: 100%;
}

.funnel:not( .no-mask ) > div:last-child div {
    mask-image: var( --mask );
    mask-size: cover;
    mask-repeat: no-repeat;
}
<div class="funnel">
    <div>
        Funnel (Mask)
    </div>
    
    <div>
        <div data-from="1" data-to="0.66667"></div>
        <div data-from="0.66667" data-to="0.25"></div>
        <div data-from="0.25" data-to="0.1"></div>
    </div>
</div>


<div class="funnel no-mask">
    <div>
        Funnel (No Mask)
    </div>
    
    <div>
        <div data-from="1" data-to="0.66667"></div>
        <div data-from="0.66667" data-to="0.25"></div>
        <div data-from="0.25" data-to="0.1"></div>
    </div>
</div>

对于漏斗中的每个分段,脚本将绘制该分段的相关 SVG 路径,并将其(带有生成的 ID)添加到 DIV 中。新 ID 将作为 CSS 变量(类似

style="--mask: url( #fcm-0-0 );"
的属性)传递到 DIV。

我面临的问题是,当我尝试使用 SVG 的黑色区域来遮盖父 DIV 时,它似乎不起作用并且所有颜色都消失了。

我的目标是暂时用 SVG 形状遮盖 DIV 的绿色背景,以便稍后我可以用渐变替换背景。

我在我的代码片段中添加了 2 个示例:

  • 第一个,是我发布的代码。
  • 第二个是我的图形结果的示例(没有遮罩),因此您可以看到 SVG 漏斗段。

你能帮忙吗?

css svg css-mask
1个回答
0
投票

我会在 mask 变量中定义 SVG,而不是创建 SVG 元素然后引用它。

document.addEventListener('DOMContentLoaded', function() {
  let funnels = document.getElementsByClassName('funnel');

  for (let i = 0; i < funnels.length; i++) {
    let segments = funnels[i].children[1].children;

    for (let j = 0; j < segments.length; j++) {
      const from = parseFloat(segments[j].getAttribute('data-from'));
      const to = parseFloat(segments[j].getAttribute('data-to'));
      const difference = (from - to) / 2;

      const d = `M 0 ${50 - from * 50} Q 25 ${50 - from * 50} 50 ${50 - ( ( to + difference ) * 50 )} T 100 ${50 - to * 50} V 100 ${50 + to * 50} Q 75 ${50 + to * 50} 50 ${50 + ( ( to + difference ) * 50 )} T 0 ${50 + from * 50} V ${50 - from * 50} Z`;
      segments[j].style.setProperty('--mask', 'url(\'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" preserveAspectRatio="none" style="width: 100%; height: 100%;"><path d="' + d + '" fill="black"></path></svg>\')');
    }
  }
});
.funnel>div:last-child {
  display: flex;
  height: 300px;
}

.funnel>div:last-child div {
  background: green;
  flex: 1;
}

.funnel:not( .no-mask)>div:last-child div {
  mask-image: var( --mask);
}
<div class="funnel">
  <div>
    Funnel (Mask)
  </div>

  <div>
    <div data-from="1" data-to="0.66667"></div>
    <div data-from="0.66667" data-to="0.25"></div>
    <div data-from="0.25" data-to="0.1"></div>
  </div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.