I'm using an SVG filter that I want to use on paths.
Since my path could be straight lines, I'm using userSpaceOnUse
for the filter unit. To make sure that the path doesn't get clipped I make sure that my filter region is large enough.
<svg width="200px" height="200px" viewbox="0 0 200 200">
<defs>
<filter filterUnits="userSpaceOnUse" id="dark" x="0" y="0" width="200" height="200">
<feColorMatrix type="matrix" values="0.2 0 0 0 0, 0 .2 0 0 0, 0 0 0.2 0 0, 0 0 0 1 0" />
</filter>
</defs>
<path transform="translate(100,100)" d="M3.989422804014327,0A3.989422804014327,3.989422804014327,0,1,1,-3.989422804014327,0A3.989422804014327,3.989422804014327,0,1,1,3.989422804014327,0" transform="translate(0,12)" fill-opacity="0.4" fill="hsl(207,59%,56%)" stroke="hsl(207,59%,56%)" filter="url(#dark)" stroke-width="1" stroke-opacity="1" />
<path d="M 10 10 H 90 V 90 H 10 L 10 10" fill-opacity="0.4" stroke="hsl(207,59%,56%)" filter="url(#dark)" fill="hsl(207,59%,56%)" stroke-width="1" stroke-opacity="1"/>
<path d="M 10 10 H 90 V 90 H 10 L 10 10" transform="translate(100,100)" fill-opacity="0.4" stroke="hsl(207,59%,56%)" filter="url(#dark)" fill="hsl(207,59%,56%)" stroke-width="1" stroke-opacity="1"/>
</svg>
The filter is applied on the three paths: the two squares and the circle. However the circle gets clipped.
If I use objectBoundingBox
the circle is rendered entirely. However this is not an option because I also want to use the filter on straight lines that have no dimensions.
If I play around with x
and y
of the filter, like -10
for both for instance, it works fine as well.
Is there something wrong with my filter region? My understanding is that it covers the SVG entirely so anything that uses the filter should not be cropped.
Or this is a use case not supported by userSpaceOnUse
that I'm not aware ?
change the translate to (0,0) instead of (100,100) see how the shape is off the canvas.
<svg width="200px" height="200px" viewbox="0 0 200 200">
<defs>
<filter filterUnits="userSpaceOnUse" id="dark" x="0" y="0" width="200" height="200">
<feColorMatrix type="matrix" values="0.2 0 0 0 0, 0 .2 0 0 0, 0 0 0.2 0 0, 0 0 0 1 0" />
</filter>
</defs>
<path transform="translate(0,0)" d="M3.989422804014327,0A3.989422804014327,3.989422804014327,0,1,1,-3.989422804014327,0A3.989422804014327,3.989422804014327,0,1,1,3.989422804014327,0" transform="translate(0,12)" fill-opacity="0.4" fill="hsl(207,59%,56%)" stroke="hsl(207,59%,56%)" filter="url(#dark)" stroke-width="1" stroke-opacity="1" />
<path d="M 10 10 H 90 V 90 H 10 L 10 10" fill-opacity="0.4" stroke="hsl(207,59%,56%)" filter="url(#dark)" fill="hsl(207,59%,56%)" stroke-width="1" stroke-opacity="1"/>
<path d="M 10 10 H 90 V 90 H 10 L 10 10" transform="translate(100,100)" fill-opacity="0.4" stroke="hsl(207,59%,56%)" filter="url(#dark)" fill="hsl(207,59%,56%)" stroke-width="1" stroke-opacity="1"/>
</svg>
Translating it doesn't change that it's drawn above and left of the filter area originally. We could move the filter by changing its x and y values to fix that...
<svg width="200px" height="200px" viewbox="0 0 200 200">
<defs>
<filter filterUnits="userSpaceOnUse" id="dark" x="-10" y="-10" width="200" height="200">
<feColorMatrix type="matrix" values="0.2 0 0 0 0, 0 .2 0 0 0, 0 0 0.2 0 0, 0 0 0 1 0" />
</filter>
</defs>
<path transform="translate(100,100)" d="M3.989422804014327,0A3.989422804014327,3.989422804014327,0,1,1,-3.989422804014327,0A3.989422804014327,3.989422804014327,0,1,1,3.989422804014327,0" transform="translate(0,12)" fill-opacity="0.4" fill="hsl(207,59%,56%)" stroke="hsl(207,59%,56%)" filter="url(#dark)" stroke-width="1" stroke-opacity="1" />
<path d="M 10 10 H 90 V 90 H 10 L 10 10" fill-opacity="0.4" stroke="hsl(207,59%,56%)" filter="url(#dark)" fill="hsl(207,59%,56%)" stroke-width="1" stroke-opacity="1"/>
<path d="M 10 10 H 90 V 90 H 10 L 10 10" transform="translate(100,100)" fill-opacity="0.4" stroke="hsl(207,59%,56%)" filter="url(#dark)" fill="hsl(207,59%,56%)" stroke-width="1" stroke-opacity="1"/>
</svg>