gpt4 book ai didi

SVG 过滤器相对于可能为零长度边的边界框,calc() 替代方案?

转载 作者:行者123 更新时间:2023-12-02 03:47:57 25 4
gpt4 key购买 nike

这在某种程度上是 Humongous height value for <filter> not preventing cutoff 的延续。 :我仍在尝试申请 <filter><path>上但我在剪辑时遇到问题。

通过使用x移动过滤器 Canvas 的中心,在另一个线程中解决了该问题。/y <filter> 上的属性,仍然一切都是百分比,因此相对于您尝试应用效果的物体的大小,但问题是边长可以是 0即使在您看到某些东西的情况下,请参阅例如以下示例中的顶行:

.pathWrapper path {
stroke: grey;
fill: none;
stroke-width: 1.5;
marker-start: url(#circle);
marker-end: url(#arrow);
}

.pathWrapper:hover {
filter: url(#colorFilter);
}
<svg style="height:400px;width:100%;background-color:LightCyan">

<defs>
<filter id="colorFilter" x="-300%" y="-300%" width="600%" height="600%">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur"></feGaussianBlur>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 3 0" result="lightenedBlur"></feColorMatrix>
<feMerge>
<feMergeNode in="lightenedBlur"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<marker id="arrow" viewBox="0 -5 10 10" refX="0" refY="0" markerWidth="8" markerHeight="8" orient="auto" style="fill: grey;">
<path d="M0,-5L10,0L0,5"></path>
</marker>
<marker id="circle" viewBox="0 -4 8 8" refX="0" refY="0" markerWidth="8" markerHeight="8" orient="auto-start-reverse" style="fill: grey;"><circle r="4" cx="4"></circle></marker>
</defs>

<g transform="scale(2)">

<g class="pathWrapper" transform="translate(70,20)">
<path d="M52,10L45,10L-30,10L-37,10"></path>
</g>

<g class="pathWrapper" transform="translate(70,50)">
<path d="M42,20L35,20L30,10L-30,10L-37,10"></path>
</g>

<g class="pathWrapper" transform="translate(200,20)">
<path d="M42,140L35,140L-30,70L-30,10L-30,10L-37,10"></path>
</g>

</g>

</svg>

将鼠标悬停在线条上可查看此处应用的滤镜效果。 您将看到悬停时顶线变得不可见。这是因为边界框高度为 0 、笔画宽度和标记小玩意不计算在内:

height zero demo

我可以使用绝对单位,例如就像下面的例子一样:

.pathWrapper path {
stroke: grey;
fill: none;
stroke-width: 1.5;
marker-start: url(#circle);
marker-end: url(#arrow);
}

.pathWrapper:hover {
filter: url(#colorFilter);
}
<svg style="height:400px;width:100%;background-color:LightCyan">

<defs>
<filter id="colorFilter" filterUnits="userSpaceOnUse" x="-125" y="-125" width="250" height="250">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur"></feGaussianBlur>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 3 0" result="lightenedBlur"></feColorMatrix>
<feMerge>
<feMergeNode in="lightenedBlur"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<marker id="arrow" viewBox="0 -5 10 10" refX="0" refY="0" markerWidth="8" markerHeight="8" orient="auto" style="fill: grey;">
<path d="M0,-5L10,0L0,5"></path>
</marker>
<marker id="circle" viewBox="0 -4 8 8" refX="0" refY="0" markerWidth="8" markerHeight="8" orient="auto-start-reverse" style="fill: grey;"><circle r="4" cx="4"></circle></marker>
</defs>

<g transform="scale(2)">

<g class="pathWrapper" transform="translate(70,20)">
<path d="M52,10L45,10L-30,10L-37,10"></path>
</g>

<g class="pathWrapper" transform="translate(70,50)">
<path d="M42,20L35,20L30,10L-30,10L-37,10"></path>
</g>

<g class="pathWrapper" transform="translate(200,20)">
<path d="M42,140L35,140L-30,70L-30,10L-30,10L-37,10"></path>
</g>

</g>

</svg>

问题是,在我的用例中,应用了效果的元素的大小可能变化很大,所以我必须在其中放置一个巨大的值,否则总是会发生变化足够大(如跨越最大高度的线的示例所示)。

我发现使用 CSS calc() 会吗?可能是一个解决方案:

#colorFilter {
width: calc(100% + 100);
height: calc(100% + 100);
x: calc(-50% - 50);
y: calc(-50% - 50);
}

.pathWrapper path {
stroke: grey;
fill: none;
stroke-width: 1.5;
marker-start: url(#circle);
marker-end: url(#arrow);
}

.pathWrapper:hover {
filter: url(#colorFilter);
}
<svg style="height:400px;width:100%;background-color:LightCyan">

<defs>
<filter id="colorFilter" filterUnits="userSpaceOnUse">
<feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur"></feGaussianBlur>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 255 0 0 0 0 0 0 0 0 3 0" result="lightenedBlur"></feColorMatrix>
<feMerge>
<feMergeNode in="lightenedBlur"></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<marker id="arrow" viewBox="0 -5 10 10" refX="0" refY="0" markerWidth="8" markerHeight="8" orient="auto" style="fill: grey;">
<path d="M0,-5L10,0L0,5"></path>
</marker>
<marker id="circle" viewBox="0 -4 8 8" refX="0" refY="0" markerWidth="8" markerHeight="8" orient="auto-start-reverse" style="fill: grey;"><circle r="4" cx="4"></circle></marker>
</defs>

<g transform="scale(2)">

<g class="pathWrapper" transform="translate(70,20)">
<path d="M52,10L45,10L-30,10L-37,10"></path>
</g>

<g class="pathWrapper" transform="translate(70,50)">
<path d="M42,20L35,20L30,10L-30,10L-37,10"></path>
</g>

<g class="pathWrapper" transform="translate(200,20)">
<path d="M42,140L35,140L-30,70L-30,10L-30,10L-37,10"></path>
</g>

</g>

</svg>

这适用于当前版本的 Google Chrome 和 Mozilla Firefox,但似乎不适用于 Micosoft Edge 或 IE11(通过一些搜索,似乎 calc() 即使对于 HTML 内容支持也已经相当敏感,请参阅https://caniuse.com/#search=calc 处的已知问题部分)。

calc() 的更好替代方案也是如此方法存在吗?

(也许值得注意的是,我正在使用动态 d3.js 生成的内容。)

最佳答案

当您在 d3 中处理生成的内容时,最好的方法是将一个不可见的矩形插入到覆盖所需过滤区域的 g.pathWrapper 中。

我在这里即兴发挥,您可能需要根据您的逻辑进行调整(并且可能将 ES6 结构替换为其 ES5 等效结构)。假设您有一个要从中生成路径数据的点列表:

var points = [[52,10], [45,10], [-30,10], [-37,10]];

// get the min/max values
var x1 = d3.min(points,(p) => p[0]),
x2 = d3.max(points,(p) => p[0]),
y1 = d3.min(points,(p) => p[1]),
y2 = d3.max(points,(p) => p[1]);

// construct the path
var path = d3.path();
path.moveto(...points[0]);
for (var point of points.slice(1)) {
path.lineto(...point);
}

// wrapper
var wrapper = d3.select('svg > g').append('g')
.classed('pathWrapper');

// invisible rect with +5px in each direction as filter region
wrapper.append('rect')
.attr('fill', 'none')
.attr('x', x1 - 5)
.attr('y', y1 - 5)
.attr('width', x2 - x1 + 10)
.attr('height', y2 - y1 + 10);

// and the path itself
wrapper.append('path')
.attr('d', path);

之后,滤镜效果区域的默认值应该按原样工作。

关于SVG 过滤器相对于可能为零长度边的边界框,calc() 替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46201654/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com