2017-09-13 1 views
1

이것은 다소 계속 Humongous height value for <filter> not preventing cutoff입니다. 나는 <filter><path>에 적용하려고 시도하고 있지만 잘리는 데 문제가 있습니다.길이가 0 인 side, calc() 대신에 바운딩 박스를 기준으로 한 SVG 필터?

문제는 <filter>x/y 속성을 사용하여 필터 캔버스의 중심을 이동하여 다른 스레드에서 해결되었다, 여전히 모든 퍼센트에 있었고, 당신이 적용하고자하는 물건의 크기에 따라서 상대 효과가 있지만 문제는 측면 길이가 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>

마우스 오버가 적용된 필터의 효과를 볼 수있다. 호버링시 맨 위 줄이 보이지 않게됩니다.

height zero demo

는 I 대신에, 예를 절대 단위를 사용할 수있다 : 경계 박스의 높이 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>
구글 크롬과 모질라 파이어 폭스의 최신 버전에서 작동하지만 Micosoft 에지 나에서 작동하도록 나타나지 않습니다이

IE11 (그리고 심지어는 calc() 지원이 이미 HTML 콘텐츠에 대해서도 상당히 민감한 것처럼 보이기 때문에 알려진 문제 섹션 (https://caniuse.com/#search=calc) 참조).

calc() 접근 방법에 대한 더 나은 대안이 있습니까?

답변

3

당신은 D3에서 생성 콘텐츠로 작업하는 것처럼 (어쩌면 내가 동적으로 생성 d3.js 내용으로 일하고 있음을 지적. 가치 것은) 가장 좋은 방법은 g.pathWrapper에 보이지 않는 RECT를 삽입하는 것입니다 필요한 필터 영역을 덮습니다.

나는 여기에 날개 달기를하고있다. 당신의 논리에 맞춰야 할 것이다. (아마도 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); 

을, 필터 효과 지역의 기본값은 그대로 작동합니다.

+0

잘 작동합니다. 그 답변을 게시하기 전에 다른 필터를 사용하려고 생각하고 있었지만 방법이 훨씬 좋고 효과적입니다. – phk

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>

+0

호버는 데모 용 이었지만 드로잉 공간이 너무 크지 않은 경우 좋은 아이디어였습니다. 내 경우에는 보이는 공간이 내 드로잉 공간 (사용자가 이동/확대/축소 할 수 있음)의 일부만 표시하고 어떤 종류의 절두체를 동등한 (아직?) 구현하지 않았기 때문에 꽤 큽니다. – phk

관련 문제