SVG with fill image - image

I have this SVG File - Where I want different paths to have different background images. I have tried these answers among others:
1. Fill SVG path element with a background image without tiling or scaling
2. Fill SVG path element with a background-image
But I can't seem to get it to work as I want. The images is not showing, or it is to small or to big. Trying to se height and width is not that helpful either.
How do I fill this path:
<g id="KK"><path class="cls-1" d="M303.83,1171.58c-3,1.39-5.62,1.93-8.54,1.2-2.44-.62-4.93-.87-7.34-1.85-4.58-1.87-8.13-5-11.42-8.48q-6-6.34-11.61-13.06a7.39,7.39,0,0,0-5.71-2.94c-3-.15-5.95-.57-8.93-.69a33.73,33.73,0,0,1-9.15-2c-4.12-1.34-8.29-2.5-12.39-3.89a25.65,25.65,0,0,0-7.91-1.35c-6.12-.1-12.25-.39-18.37-.25-3.38.08-5.22-1.83-6.91-4.14a6.89,6.89,0,0,1-.57-2.57c-.44-2.19-.81-4.39-1.33-6.56a19.24,19.24,0,0,0-3.38-6.75c-3.68-5.08-7.19-10.29-11.9-14.53a11.94,11.94,0,0,1-2.9-4.46c-3.22-7.71-6.36-15.46-8.17-23.66a14.34,14.34,0,0,0-2.64-5.62c-1.25-1.67-2.31-3.51-3.69-5.07-3.58-4.07-4.16-9-3.34-13.89a90.56,90.56,0,0,0,1.59-17.8,6.69,6.69,0,0,1,1.3-4.64,7.47,7.47,0,0,0,1.34-5.08c0-2.24-.09-4.49.08-6.72a10.91,10.91,0,0,0-2.2-7.51c-3.82-5.35-7.46-10.83-11.21-16.21a19.19,19.19,0,0,1-3.18-6.84c-.88-3.93-2-7.79-3.1-11.68a14.93,14.93,0,0,0-1.09-3.4c-1.54-2.72-1.72-5.65-1.73-8.66,0-4.18-.18-8.37-.26-12.55a12.83,12.83,0,0,0-1.91-6.8c-1.35-2.15-2.6-4.37-3.78-6.61-1.63-3.1-2-6.21.3-9.21a6.22,6.22,0,0,0,1.14-3.79c0-1.64.13-3.29.2-4.92a2.84,2.84,0,0,1,2-2.7c1.11-.39,2.26-.67,3.42-1a25.86,25.86,0,0,1,5.3,4.91,8.17,8.17,0,0,0,5.93,2.62,17.89,17.89,0,0,0,9.53-1.79c4.94-2.47,10-4.71,15-7,1.21-.56,2.44-1.08,3.92-1.73,1.5,1.16,3,2.3,4.53,3.52a8.11,8.11,0,0,0,4.82,2.07,13.57,13.57,0,0,1,4.73,1.18,15.19,15.19,0,0,0,7.39,1.36c.45,0,.9,0,1.35,0,6.8-.07,5.27.47,10-3.58a10.18,10.18,0,0,1,1.35-.8c.75.6,1.58,1.2,2.32,1.88,1.65,1.52,3.3,3,4.87,4.64a5.38,5.38,0,0,0,5.2,1.8c2.93-.52,5.92-.73,8.89-1.06,2.24-.25,4.41-.37,6.54.8a9,9,0,0,0,3.85.85c6.85.25,6.85.21,13.06-3.38,2.06-1.19,4.15-2.35,5.84-3.3,3.58.86,6.74,1.66,9.92,2.35a7.48,7.48,0,0,1,4.77,3c1.57,2.18,3.35,4.2,5,6.35a3,3,0,0,0,3.52,1.24c1.58-.47,3.17-.87,4.71-1.41a56.55,56.55,0,0,1,12.69-2.6,6.78,6.78,0,0,1,3.89.67c.4.2.8.39,1.2.62,7,4,14.65,6.68,22.23,9.42a22.79,22.79,0,0,0,8.3,1.44c11.5-.2,23-.27,34.51-.39,1.34,0,2.69-.07,4,0,2.07.16,2.81,1.49,1.92,3.45a30.26,30.26,0,0,1-2,3.52,16.3,16.3,0,0,0-2.53,8c-.38,6.1-1,12.2-1.58,18.29-.27,3-.6,5.94-.82,8.92-.85,11.49.13,23-.14,34.49a10.62,10.62,0,0,0,1.5,5.08c5.22,10.42,10.47,20.81,16.86,30.58.9,1.37,1.72,2.79,2.58,4.2,3.31,5.43,3.3,5.43,2.23,11.71-.25,1.47-.56,2.94-.68,4.42a6.64,6.64,0,0,1-3.1,5.15c-3.54,2.5-6.88,5.29-10.83,7.15-2.1,1-3.47,2.67-4.92,4.42-3.47,4.17-4.84,9.18-6.29,14.21-.58,2,0,3.83.62,5.68a51.37,51.37,0,0,1,2.26,11.85,7.63,7.63,0,0,1-2.07,6.09c-1.71,1.88-3.28,3.88-4.88,5.85a3.79,3.79,0,0,1-3.51,1.51,22.89,22.89,0,0,1-7.37-1.68c-3-1.3-6.12-2.36-9.19-3.52a5.77,5.77,0,0,0-5.51.69c-3.19,2-6.1,4.26-8.08,7.57a44.6,44.6,0,0,1-3.11,4.39,6.76,6.76,0,0,1-7.06,2.84c-4.45-.95-8.93-.5-13.41-.54a6.34,6.34,0,0,0-4.53,1.59c-2.32,2.1-4.62,4.23-7,6.28-1.59,1.39-1.73,2.89-1,4.82C300.12,1160.74,301.87,1166,303.83,1171.58Z" transform="translate(-4.18 -15.07)"></path></g>
With an image like this: (for example)
http://calciodanese.altervista.org/alterpages/hbkgepage.jpg

To have a <pattern> that outomatically fills the entirety of whatever shape you apply it to, you need to give it a viewBox that matches the dimensions of the image. And also set the preserveAspectRatio attribute to "xMidYMid slice".
<svg width="400" height="400">
<defs>
<pattern id="imgpattern" x="0" y="0" width="1" height="1"
viewBox="0 0 1024 576" preserveAspectRatio="xMidYMid slice">
<image width="1024" height="576" xlink:href="http://calciodanese.altervista.org/alterpages/hbkgepage.jpg"/>
</pattern>
</defs>
<path fill="url(#imgpattern)" stroke="black" stroke-width="4"
d="M 100,50 L 120,110 150,90 170,220 70,300 50,250 50,200 70,100 50,70 Z" />
<rect x="200" y="20" width="100" height="100"
fill="url(#imgpattern)" stroke="black"/>
<rect x="310" y="20" width="100" height="50"
fill="url(#imgpattern)" stroke="black"/>
<rect x="310" y="80" width="50" height="200"
fill="url(#imgpattern)" stroke="black"/>
<circle cx="220" cy="300" r="50"
fill="url(#imgpattern)" stroke="black"/>
</svg>

Related

Is there a way to rotate feImage or feTile pattern in an SVG?

In this example, I set up a filter that textures the given element with a checkboard pattern using SVG filter effects:
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="texture" x="0" y="0" width="100%" height="100%">
<feImage width="16" height="16" result="checkerboard-image"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEXMzMzLy8v////+/v7l
9thZAAAAO0lEQVR4ASXIUQ3AIBAFsJKcACQxu4/kBCAJFUu2ftbUYeWYI8G51kqU3VSCm68l
hpyH/nuWHaQH2eoF1bMYGK3LF0IAAAAASUVORK5CYII="/>
<feTile in="checkerboard-image" result="texture" />
<feBlend in="SourceGraphic" in2="texture" mode="multiply" />
<feTile/>
</filter>
</defs>
<image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"
x="0" y="0" width="100%" height="100%" style="filter:url(#texture);"/>
</svg>
Is there a way I can rotate the whole texture, so that I get e.g. a 45-degree rotated checkboard pattern applied on the same image?
I figured it out. You need to wrap the image in several nested <g> groups. From the innermost group:
Rotate the image in the negative desired angle
Apply the filter
Rotate the image in the positive desired angle
The image will remain in the original rotation, but the effect will have been applied on the rotated image, thus making the effect itself rotated.
Here's the code itself:
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="texture" x="0" y="0" width="100%" height="100%">
<feImage width="16" height="16" result="texture-image"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEXMzMzLy8v////+/v7l
9thZAAAAO0lEQVR4ASXIUQ3AIBAFsJKcACQxu4/kBCAJFUu2ftbUYeWYI8G51kqU3VSCm68l
hpyH/nuWHaQH2eoF1bMYGK3LF0IAAAAASUVORK5CYII="/>
<feTile in="texture-image" result="texture" />
<feBlend in="SourceGraphic" in2="texture" mode="multiply" />
<feTile/>
</filter>
</defs>
<g transform="rotate(30)">
<g filter="url(#texture)" >
<g transform="rotate(-30)">
<image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png" x="0" y="0" width="100%" height="100%"/>
</g>
</g>
</g>
</svg>
Theoretically, you could do it with a feDisplacementMap, but generating the right displacement map is quite difficult, so practically speaking, you have to rotate the checkerboard outside the filter (by redoing the checkerboard image, or using a patternTransform). Here is an example that inverts the filter inputs - it pulls in the main image via a feImage, and makes the rotated checkerboard the SourceGraphic.
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="checker-pattern" x="0" y="0" width="16" height="16" patternTransform="rotate(45) translate(-4 4)" patternUnits="userSpaceOnUse">
<image x="0" y="0" height="16" width="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAADFBMVEXMzMzLy8v////+/v7l9thZAAAAO0lEQVR4ASXIUQ3AIBAFsJKcACQxu4/kBCAJFUu2ftbUYeWYI8G51kqU3VSCm68l
hpyH/nuWHaQH2eoF1bMYGK3LF0IAAAAASUVORK5CYII="/>
</pattern>
<filter id="texture" x="0" y="0" width="100%" height="100%">
<feImage x="0%" y="0%" width="100%" height="100%" result="original-image"
xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"/>
<feBlend in="SourceGraphic" mode="multiply" />
</filter>
</defs>
<g filter="url(#texture)">
<rect x="0%" y="0%" width="100%" height="100%" fill="url(#checker-pattern)"/>
</g>
</svg>
A different solution would be using an SVG pattern, like so:
<svg viewBox='0 0 200 200' width='200' height='200' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<defs>
<pattern id='_texture' width='16' height='16' patternUnits='userSpaceOnUse' patternTransform="rotate(45)">
<g fill='rgba(0,0,0,.3)'>
<rect width='8' height='8'/>
<rect x='8' y='8' width='8' height='8'/>
</g>
</pattern>
</defs>
<image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"
x="0" y="0" width="100%" height="100%" />
<rect width='100%' height='100%' fill='url(#_texture)'/>
</svg>
UPDATE
this time I'm using an SVG dataURI image instead instead of your dataURI. The filter is still there. I hope it helps.
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="texture" x="0" y="0" width="100%" height="100%">
<feImage width="11.31" height="11.31" result="checkerboard-image"
xlink:href="data:image/svg+xml,%3Csvg viewBox='0 0 11.31 11.31' width='11.31' height='11.31' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cg fill='rgba(0,0,0,.3)' transform='rotate(45 5.655 5.655)'%3E%3Crect width='8' height='8' x='1.655' y='1.655'/%3E%3C/g%3E%3C/svg%3E"/>
<feTile in="checkerboard-image" result="texture" />
<feBlend in="SourceGraphic" in2="texture" mode="multiply" />
<feTile/>
</filter>
</defs>
<image xlink:href="https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png"
x="0" y="0" width="100%" height="100%" style="filter:url(#texture);"/>
</svg>

Rotate the direction of motion of a rect using animateMotion in SVG

I want the yellow rectangle to be rotated 45 degrees (which it is), but I also want the direction of motion to rotate, so that the yellow rectangle appear to go "downhill" (down the blue line). I don't want it to keep moving horizontally.
<svg width="800" height="400" viewBox="0 0 800 400"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<!-- decorative circles for the ends of the blue line. -->
<g transform="rotate(45, 400, 200)">
<path id="myPath" d="M150,200 L650,200" fill="none"
stroke="blue" stroke-width="5.6" />
<circle cx="150" cy="200" r="8.94" fill="blue" />
<circle cx="650" cy="200" r="8.94" fill="blue" />
</g>
<g>
<rect x="0" y="0"
fill="yellow" stroke="red" width="84" height="56"></rect>
<animateMotion dur="4s" repeatCount="1" rotate="45"
path="M150,200 L650,200" >
</animateMotion>
</g>
</svg>
Another way to do this is to put <mpath xlink:href="#myPath" /> as a sub-element of the animateMotion SVG element. In that case you can leave out path="M150,200 L650,200".
You mean like this? I've moved the animateMotion so it only applies to the rect and added a transform to the containing <g> element. I could have just put the rect in the other <g> element I guess which would have been simpler.
<svg width="800" height="400" viewBox="0 0 800 400"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<!-- decorative circles for the ends of the blue line. -->
<g transform="rotate(45, 400, 200)">
<path id="myPath" d="M150,200 L650,200" fill="none"
stroke="blue" stroke-width="5.6" />
<circle cx="150" cy="200" r="8.94" fill="blue" />
<circle cx="650" cy="200" r="8.94" fill="blue" />
</g>
<g transform="rotate(45, 400, 200)">
<rect x="0" y="0"
fill="yellow" stroke="red" width="84" height="56">
<animateMotion dur="4s" repeatCount="1"
path="M150,200 L650,200" >
</animateMotion>
</rect>
</g>
</svg>

Ordering shapes across groups

I know, that in SVG shapes are displayed in the order the elements are listed in the document, so by re-ordering them you can bring needed shapes to front. However, suppose, I have a document like:
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="500" version="1.1">
<g transform="translate(10, 10)">
<rect width="200" height="100" stroke="black" stroke-width="6" x="10" y="10" fill="green"/>
<rect width="200" height="100" stroke="black" stroke-width="6" x="50" y="50" fill="red"/>
</g>
<g transform="translate(80, 80)">
<rect width="200" height="100" stroke="black" stroke-width="6" x="10" y="10" fill="green"/>
<rect width="200" height="100" stroke="black" stroke-width="6" x="50" y="50" fill="red"/>
</g>
</svg>
(See JSFiddle). Within each group the elements are arranged so, that the red rectangles are shown on top of the corresponding green ones. However, because the groups are ordered as well, the second group is on top of the first one. I want all red rectangles to be shown on top of all green rectangles, and remain grouped like above. Is that possible in SVG / D3.js?

Firefox SVG shape not printing when it has stroke

I am having an issue with SVG shapes that have a stroke and trying to get them to print in firefox.
This is the simplest example:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="0" y="0" rx="15" ry="15" width="300" height="400" style="stroke:black;stroke-width:5;" fill="black" />
<circle id="FirstCircle" cx="50" cy="50" r="30" stroke="black" stroke-width="2" fill="white" style="opacity:0.75;"/>
<circle id="SecondCircle" cx="50" cy="150" r="30" fill="white" style="opacity:0.75;"/>
</svg>
When I try and print this the first shape does one of two things:
It does not show up at all
It shows up off center in its bounding box.
The second shape with no stroke shows up as expected, where expected.
When displaying on the screen it shows as expected where expected. The issue olny arises when I try and print.
I have tried with different scale factors (50% - 100%) and the default shrink to fit.
Here is what I get when I try and print it:
Is this defined behavior or does anyone know how to correct for this?
I am not in love with the stroke on this shape and can easily layer shapes to get the same effect, bt it would be nice to know why this is happeneing.
EDIT:
As Robert Longson pointed out this appears to be a Firefox bug. A report was filed here and they are looking into it.
You need to specify the width and height of the svg element to fix this:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" height="400">
<rect x="0" y="0" rx="15" ry="15" width="300" height="400" style="stroke:black;stroke-width:5;" fill="black" />
<circle id="FirstCircle" cx="50" cy="50" r="30" stroke="black" stroke-width="2" fill="white" style="opacity:0.75;"/>
<circle id="SecondCircle" cx="50" cy="150" r="30" fill="white" style="opacity:0.75;"/>
</svg>

SVG pattern inconsistency between chrome and firefox

I have a gradient overlaying a solid color (red) specified as a pattern:
<svg width="480" height="480">
<defs>
<pattern width="1" height="1" x="0" y="0" id="pattern">
<rect width="240" height="240" x="0" y="0" fill="rgba(255,0,0,1)"/>
<rect width="240" height="240" x="0" y="0" fill="url(#gradient)"/>
</pattern>
<linearGradient id="gradient" x1="0" y1="1" x2="0" y2="0">
<stop offset="0%" stop-color="rgb(0,0,0)" stop-opacity="1"/>
<stop offset="100%" stop-color="rgb(0,0,0)" stop-opacity="0"/>
</linearGradient>
</defs>
<path
transform="matrix(1,0,0,1,200,200)"
d="M0 0M 120 0 A 120 120 0 0 0 -120 0 A 120 120 0 0 0 120 0"
fill="url(#pattern)"
/>
</svg>
Left: Firefox. Right: Chrome
The one on the right (Chrome) is correct.
Does anyone know how to make this work in Firefox?
See it live: http://jsbin.com/eyenoh/edit#html,live
I was able to get it working by using the object bounding box as coordinate system for the pattern content.
<pattern width="1" height="1" x="0" y="0" id="pattern" patternContentUnits="objectBoundingBox">
<rect width="1" height="1" x="0" y="0" fill="rgba(255,0,0,1)"/>
<rect width="1" height="1" x="0" y="0" fill="url(#gradient)"/>
</pattern>
See it here:
http://jsbin.com/efesev/edit#html,live
I'll try to investigate further. Looks like a good candidate for a bug report.

Resources