Ordering shapes across groups - d3.js

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?

Related

SVG animation (blinking) inside of animation (blinking)

So i have page 1 and page 2 which are animated, inside of page 2 there is also animation but problem is that this object shows when page 2 is "hidden". How to prevent that ??
Black square should only be visible when page 2 is visible, but it ignores parent style.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 612 792" style="enable-background:new 0 0 612 792;" xml:space="preserve">
<rect x="0.5" y="0.167" fill="#ccc" stroke="#000" width="100" height="100"/>
<!-- square -->
<g>
<!-- page 1 -->
<g id="page_one" style="z-index:1">
<rect x="25" y="5" width="50" height="50" fill="red" style=""></rect>
</g>
<!-- page 2 -->
<g id="page_two" style="z-index:-1">
<rect x="25" y="5" width="50" height="50" fill="white" style=""></rect>
<g transform="scale(2.9) translate(6,0)">
<g transform="scale(0.205)translate(1,1)">
<!-- animation inside page 2 -->
<g style="z-index:-1">
<animate attributeName="visibility" dur="2" repeatCount="indefinite" keyTimes="0;0.5;1" values="visible;hidden;visible"></animate>
<rect x="25" y="15" width="50" height="50" fill="black" style=""></rect>
</g>
</g>
</g>
</g>
<!-- animate page 1 & 2 -->
<animate xlink:href="#page_one" attributeName="visibility" values="visible;hidden" dur="4s" begin="0s" repeatCount="indefinite"></animate>
<animate xlink:href="#page_two" attributeName="visibility" values="hidden;visible" dur="4s" begin="0s" repeatCount="indefinite"></animate>
</g>
</svg>
Tried some css styling, z-index but nothing solved issue.
animate the display property instead.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 612 792" style="enable-background:new 0 0 612 792;" xml:space="preserve">
<rect x="0.5" y="0.167" fill="#ccc" stroke="#000" width="100" height="100"/>
<!-- square -->
<g>
<!-- page 1 -->
<g id="page_one" style="z-index:1">
<rect x="25" y="5" width="50" height="50" fill="red" style=""></rect>
</g>
<!-- page 2 -->
<g id="page_two" style="z-index:-1">
<rect x="25" y="5" width="50" height="50" fill="white" style=""></rect>
<g transform="scale(2.9) translate(6,0)">
<g transform="scale(0.205)translate(1,1)">
<!-- animation inside page 2 -->
<g style="z-index:-1">
<animate attributeName="display" dur="2" repeatCount="indefinite" keyTimes="0;0.5;1" values="block;none;block"></animate>
<rect x="25" y="15" width="50" height="50" fill="black" style=""></rect>
</g>
</g>
</g>
</g>
<!-- animate page 1 & 2 -->
<animate xlink:href="#page_one" attributeName="display" values="block;none" dur="4s" begin="0s" repeatCount="indefinite"></animate>
<animate xlink:href="#page_two" attributeName="display" values="none;block" dur="4s" begin="0s" repeatCount="indefinite"></animate>
</g>
</svg>

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>

SVG with fill 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>

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>

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>

Resources