这有点是Humongous height value for <filter> not preventing cutoff的延续:我仍在尝试在<filter>
上应用<path>
,但我遇到了被剪裁的问题。
通过使用x
上的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
,笔触宽度和标记小符号不计算在内:
我可以使用绝对单位,例如如下例所示:
.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生成的内容。)
答案 0 :(得分:3)
当您在d3中处理生成的内容时,最好的方法是在g.pathWrapper
中插入一个覆盖所需过滤区域的不可见矩形。
我在这里徘徊,你可能需要根据你的逻辑进行调整(并且可能会为他们的ES5等价物交换ES6结构)。假设您有一个从以下位置生成路径数据的点列表:
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);
之后,滤镜效果区域的默认值应按原样运行。
答案 1 :(得分:1)
仅仅因为您在过滤器中使用userSpaceOnUse
值,并不意味着您仍然无法使用百分比。只是百分比是相对于SVG的宽度和高度而不是元素的宽度和高度。
当然这意味着过滤器正在应用于很多的额外的,不必要的像素。过滤器应用于SVG大小的区域,而不是元素大小的区域。但是,由于您只是在悬停时过滤了一个元素,因此浏览器所做的额外工作导致的任何缓慢都不应该引人注意。
.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>