多个重叠的 svg 路径会产生不需要的效果

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

我创建了一个树状结构的卡片,父母和孩子之间有线条。这些线是 svg 路径,如下所示:

const newpath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
        newpath.setAttributeNS(
            null,
            'd',
            `M${parentX} ${parentY} h10 a${arcRadius},${arcRadius} 0 0 1 ${arcRadius},${arcRadius} v ${
                childY - arcRadius * 2
            } a${arcRadius},${arcRadius} 0 0 0 ${arcRadius},${arcRadius} h12`
        );
        newpath.setAttributeNS(null, 'stroke', 'black');
        newpath.setAttributeNS(null, 'stroke-width', '1');
        newpath.setAttributeNS(null, 'opacity', '1');
        newpath.setAttributeNS(null, 'fill', 'none');

现在这意味着对于 1 个父级和 3 个子级,将创建 3 条路径。所有 3 条路径都与第一个子项重叠,2 条路径与第二个子项重叠,最后有 1 条路径与第三个子项重叠。通过调整transform:scale()属性,整个树是可缩放的。现在,当我缩小时,重叠的线条会变暗。除了只在孩子之间画线之外,还有什么方法可以摆脱这种行为吗?

这里之前已经问过类似的问题:为什么彼此之上的 SVG 线条/路径会创建不同的笔划?但接受的解决方案对我不起作用。

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

不幸的是,没有完美的解决方案。

在清晰度和平滑边缘之间提供适当平衡的解决方法可能是应用 svg

feComponentTransfer
滤镜 来增强 Alpha 通道的对比度。

svg{
  border: 1px solid #ccc;
  width: 70px;
}

path{
  stroke-width:1px;
  fill:none;
}

.crisp path{
  shape-rendering: crispEdges
}

.contrast
path{
   filter:url(#enhanceContrast);
}
<h3>Unedited</h3>

<svg  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" >
<path  stroke="#000"  d="M46.694,63.025c-6.627,0-12-5.373-12-12V16.248"/>
<path  stroke="#000"  d="M46.694,76.536c-6.627,0-12-5.373-12-12V29.758"/>
<path  stroke="#000"  d="M46.694,89.753c-6.627,0-12-5.373-12-12V42.975"/>
</svg>

<h3>shape-rendering: crispedges</h3>

<svg class="crisp" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" >
<path  stroke="#000"  d="M46.694,63.025c-6.627,0-12-5.373-12-12V16.248"/>
<path  stroke="#000"  d="M46.694,76.536c-6.627,0-12-5.373-12-12V29.758"/>
<path  stroke="#000"  d="M46.694,89.753c-6.627,0-12-5.373-12-12V42.975"/>
</svg>

<h3>Integer coordinates</h3>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path  stroke="#000" d="M 47 63
c -7 0 -12 -5 -12 -12
v -35"/>
<path  stroke="#000" d="M 47 77
c -7 0 -12 -5 -12 -12
v -35"/>
<path  stroke="#000" d="M 47 90
c -7 0 -12 -5 -12 -12
v -35"/>
</svg>

<h3>Duplicate strokes</h3>

<svg  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<path  stroke="#000" d="M 47 63
c -7 0 -12 -5 -12 -12
v -35"/>
<path  stroke="#000" d="M 47 77
c -7 0 -12 -5 -12 -12
v -35"/>
<path  stroke="#000" d="M 47 90
c -7 0 -12 -5 -12 -12
v -35"/>
<path  stroke="#000" d="M 47 63
c -7 0 -12 -5 -12 -12
v -35"/>
<path  stroke="#000" d="M 47 77
c -7 0 -12 -5 -12 -12
v -35"/>
<path  stroke="#000" d="M 47 90
c -7 0 -12 -5 -12 -12
v -35"/>
    
</svg>

<h3>Enhance contrast (svg filter)</h3>

<svg class="contrast" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" >
<path  stroke="#000"  d="M46.694,63.025c-6.627,0-12-5.373-12-12V16.248"/>
<path  stroke="#000"  d="M46.694,76.536c-6.627,0-12-5.373-12-12V29.758"/>
<path  stroke="#000"  d="M46.694,89.753c-6.627,0-12-5.373-12-12V42.975"/>
</svg>



<svg xmlns="http://www.w3.org/2000/svg" style="position: fixed; width:0; height:0; overflow:hidden;">
    <filter id="enhanceContrast" x="0" y="0" width="100%" height="100%">
      <feComponentTransfer>
        <feFuncA type="gamma" amplitude="1" exponent="1" offset="0"></feFuncA>        
      </feComponentTransfer>
      </filter>
</svg>

上面的示例比较了不同的解决方法:

  • shape-rendering: crispEdges
    – 非常适合直线,但会在曲线上产生锯齿状边缘
  • 整数坐标:将路径命令值舍入为整数通常可以减轻不同笔画宽度的不良影响
  • 重复笔划:另一种方法是复制路径 - 这将防止“较亮”的渲染,但也会导致视觉上更粗的笔划宽度
  • 通过 svg
    feComponentTransfer
    滤镜增强 alpha 对比度:我们基本上减少了半透明像素的数量。
© www.soinside.com 2019 - 2024. All rights reserved.