How to animate SVG? - javascript

I'd like to use the jQuery "animate"-call to animate a SVG.
The SVG should get for example rotated or or scaled.
What I've tried so far was this simple code but obviously this is not working so far:
$("#svg").animate({
transform: "scale(0.4)"
}, 400)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" viewBox="0 0 1 1" style="fill:purple;stroke:red" id="svg">
<svg width="100%" height="100%">
<svg width="100%" ID="piece" y="0" x="0" class="black" height="100%">
<g transform="translate(0.005) scale(0.022)">
<path d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</g>
</svg>
I also added this line $("#svg").css({transform: "scale(0.4)"}) to try if the scale style will be applied on the element, and however - this is working.
How can I fix this issue why I'm not be able to animate the SVG element? Any help would be very appreciated, thanks.

You want it to animate and reduce the svg that's right ?
Here's a snipper where it works
$("#svg").animate({
width: "10%", height: "10%"
}, 400)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" viewBox="0 0 1 1" style="fill:purple;stroke:red" id="svg">
<svg width="100%" height="100%">
<svg width="100%" ID="piece" y="0" x="0" class="black" height="100%">
<g transform="translate(0.005) scale(0.022)">
<path d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</g>
</svg>
Here's the documentation to use the animate function : here
or do it with CSS
#svg {
animation: reduce 2s 2; /* To make the animation twice */
}
#keyframes reduce {
from {transform : scale(1);}
to {transform : scale(0.4);}
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" viewBox="0 0 1 1" style="fill:purple;stroke:red" id="svg">
<svg width="100%" height="100%">
<svg width="100%" ID="piece" y="0" x="0" class="black" height="100%">
<g transform="translate(0.005) scale(0.022)">
<path d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</g>
</svg>
I make the animation twice but do as you want with the animation-iteration-count property : documentation here
Wish it helped you !

Also one good web tool what SVG Gator made you can try here:
https://app.svgator.com/
There is a few assets of animations.
Best regards.

Related

How to align a group (instead of text) along a path in svg?

Lets assume I have programmatically created a circle and some text,
that I want to align along the circle.
I am able to do so using the textPath element.
In addition I have a rectangular image (or any svg group <g>),
that I also would like to align to the circle
(the red rectangle in the image below is just an example; actually I would like to be able to align arbitrary svg groups <g> as image labels on the nodes of a chord diagram.).
However, textPath only seems to work for text elements.
=> Is there something similar that works for group elements?
Or do I need to manually calculate the transformation for my group
(following from some tangent of the circle)?
(A workaround could be to create some hidden text with a single letter and
the same size as my group ... align it and grab its transformation. However, that feels ugly.)
In addition I have a rectangular image (or any svg group ), that I
also would like to align to the circle (see red rectangle in the
example image below).
However, textPath only seems to work for text elements.
You can use the rectangle unicode character ▮
In this case you will be able to include it in one textPath command along with other words
<svg width="400" height="400" viewBox="0 0 400 400">
<path id="pathChain" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<text font-size="36" font-family="Times New Roman" fill="grey" >
<textPath id="result" startOffset="7%" xlink:href="#pathChain">
<tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-20" dy="-10" fill="red" font-size="72px"> ▮</tspan>
</textPath>
</text>
</svg>
You can use any unicode character that suits you
<svg width="400" height="400" viewBox="0 0 400 400">
<path id="pathChain" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<text font-size="36" font-family="Times New Roman" fill="grey" >
<textPath id="result" startOffset="7%" xlink:href="#pathChain">
<tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-5" fill="red" font-size="72px"> ⮔</tspan>
</textPath>
</text>
</svg>
If necessary, you can make the animation of the letters
<svg width="400" height="400" viewBox="0 0 400 400">
<path id="pathChain" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<text font-size="36" font-family="Times New Roman" fill="grey" >
<textPath id="result" xlink:href="#pathChain">
<tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-5" fill="red" font-size="72px"> ⮔</tspan>
<animate dur="10s" repeatCount="5" attributeName="startOffset" values="5%;50%;50%;5%;5%"/>
</textPath>
</text>
</svg>
As #Paul LeBeau commented:
No there is no automatic way to do that. You have to position it
yourself
Consider adding svg images to text using absolute positioning
Since any text in SVG is a vector object, it has absolute coordinates x, y, as the first character of the word and the last.
Using this you can position an icon or any other vector image to the beginning or end of the text.
I put the icon in the <symbol> tag and position it at the end of the word using the <use> tag
<use xlink:href="#speaker" x="245" y="35" />
<svg width="400" height="400" viewBox="0 0 400 400">
<symbol>
<g id="speaker" style="transform-origin:center;transform-box: fill-box;transform:rotate(15deg);" >
<path fill="#089421" d="M28,7.1v2c7.3,1,13,7.3,13,14.9s-5.7,13.9-13,14.9v2c8.4-1,15-8.2,15-16.9S36.4,8.1,28,7.1z"/>
<path fill="#546E7A" d="M14,32H7c-1.1,0-2-0.9-2-2V18c0-1.1,0.9-2,2-2h7V32z"/>
<polygon fill="#78909C" points="26,42 14,32 14,16 26,6"/>
<path fill="#089421" d="M28,17.3v2.1c1.8,0.8,3,2.5,3,4.6s-1.2,3.8-3,4.6v2.1c2.9-0.9,5-3.5,5-6.7S30.9,18.2,28,17.3z"/>
<path fill="#089421" d="M28,12.2v2c4.6,0.9,8,5,8,9.8s-3.4,8.9-8,9.8v2c5.7-1,10-5.9,10-11.8S33.7,13.1,28,12.2z"/>
</g>
</symbol>
<path id="pathChain" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<text font-size="36" font-family="Times New Roman" fill="grey" >
<textPath id="result" xlink:href="#pathChain">
<tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello Wordl </tspan>
</textPath>
</text>
<use xlink:href="#speaker" x="245" y="35" />
</svg>
An example with a growing line on which text and an icon are located
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0 0 400 400" version="1">
<symbol id="grow">
<g>
<circle fill="#FF9800" cx="28" cy="9" r="5"/>
</g>
<path fill="#00796B" d="M29,27.3l-9.2-4.1c-1-0.5-1.5,1-2,2c-0.5,1-4.1,7.2-3.8,8.3c0.3,0.9,1.1,1.4,1.9,1.4c0.2,0,0.4,0,0.6-0.1 L28.8,31c0.8-0.2,1.4-1,1.4-1.8C30.2,28.4,29.7,27.6,29,27.3z"/>
<path fill="#009688" d="M26.8,15.2l-2.2-1c-1.3-0.6-2.9,0-3.5,1.3L9.2,41.1c-0.5,1,0,2.2,1,2.7c0.3,0.1,0.6,0.2,0.9,0.2 c0.8,0,1.5-0.4,1.8-1.1c0,0,9.6-13.3,10.4-14.9s4.9-9.3,4.9-9.3C28.7,17.4,28.2,15.8,26.8,15.2z"/>
<path fill="#FF9800" d="M40.5,15.7c-0.7-0.8-2-1-2.8-0.3l-5,4.2l-6.4-3.5c-1.1-0.6-2.6-0.4-3.3,0.9c-0.8,1.3-0.4,2.9,0.8,3.4 l8.3,3.4c0.3,0.1,0.6,0.2,0.9,0.2c0.5,0,0.9-0.2,1.3-0.5l6-5C41.1,17.8,41.2,16.6,40.5,15.7z"/>
<path fill="#FF9800" d="M11.7,23.1l3.4-5.1l4.6,0.6l1.5-3.1c0.4-0.9,1.2-1.4,2.1-1.5c-0.1,0-0.2,0-0.2,0h-9c-0.7,0-1.3,0.3-1.7,0.9 l-4,6c-0.6,0.9-0.4,2.2,0.6,2.8C9.2,23.9,9.6,24,10,24C10.6,24,11.3,23.7,11.7,23.1z"/>
</symbol>
<path id="txtPath" d="m22 366c0 0 59-24 74-50C132 253 129 213 128 161 125 33 200 2 200 2" style="fill:none;stroke:#00796B;stroke-width:3"/>
<use xlink:href="#grow" x="123" y="10" />
<text dx="0" dy="-10px" font-size="20" font-family="Times New Roman" fill="#414141" >
<textPath id="result" startOffset="5%" xlink:href="#txtPath"> Stock growth in the first half of the year </textPath>
</text>
</svg>
One more example
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0 0 400 400" version="1">
<symbol id="Cactus" style="transform-origin:center;transform-box: fill-box;transform:rotate(15deg);">
<path fill="#7CB342" d="M35.3,9.6c-1.6-0.2-1.3,0.9-1.9,2.7l-1,4.3c-0.3,1-0.7,1.4-2,1.3L25,17.3c-1.6-0.2-3.1,1-3.2,2.6 c-0.2,1.6,1,3.1,2.6,3.2l6.3,0.7c3,0.3,5.5-0.9,6-5.4c0,0,0.6-4.7,0.3-6.6C36.7,10.2,36.6,9.7,35.3,9.6z"/>
<path fill="#7CB342" d="M12.2,13.6c1.6-0.1,1.3,0.9,1.9,2.8l1.3,6.3c0.3,1,0.7,1.4,2,1.3l5.4-0.4c1.6-0.1,3,1.1,3.2,2.7 c0.1,1.6-1.1,3-2.7,3.2l-6.3,0.5c-3,0.2-5.5-1-5.9-5.5c0,0-0.8-6.7-0.5-8.5C10.7,14.2,10.8,13.7,12.2,13.6z"/>
<path fill="#8BC34A" d="M24,5c-2.4,0-4,0.6-4.5,3.2c0,0-2.1,16.9,0,32.1c0.3,3.2,2,1.2,4.4,1.2s3.8,2.7,4.4-0.8 c2.5-15.1,0-32.6,0-32.6C27.7,5.2,26.4,5,24,5z"/>
<path fill="#FFB74D" d="M38.8,43H9.2c0,0,4.9-2.3,14.8-2.3S38.8,43,38.8,43z"/>
</symbol>
<path id="txtPath" d="m200 2c0 0 36 31 57 42 15 8 34 6 47 16 15 11 26 27 33 43 8 18 2 41 11 58 9 17 41 40 41 40" fill="none" stroke="green" stroke-width="2"/>
<use xlink:href="#Cactus" x="355" y="150" />
<text font-size="20" font-family="Times New Roman" fill="grey" >
<textPath id="result" startOffset="7%" xlink:href="#txtPath">
<tspan dx="0" dy="-5" fill="black" >Decrease in stocks per year </tspan>
</textPath>
</text>
</svg>
As a starting point here is the workaround I mentioned.
It uses some invisible placeholder text and extracts the transformation information with
placeHolder.getBoundingClientRect();
and
placeHolder.getRotationOfChar(0);
The result is only an approximation that depends on the font size and on the character of the placeholder.
var svg = document.getElementById('svg');
var text = document.createElement('text');
text.setAttribute('fill','black');
svg.appendChild(text);
var placeHolder = document.getElementById('placeholder');
var placeHolderBounds = placeHolder.getBoundingClientRect();
var angle = placeHolder.getRotationOfChar(0);
var group = document.getElementById('my-group');
var groupBounds = group.getBoundingClientRect();
var dx = 0; //groupBounds.width/2;
var dy = -groupBounds.height;
var x = placeHolderBounds.x;
var y = placeHolderBounds.y;
var transform = 'translate(' + x +','+ y +') '+
'rotate('+ angle +') '+
'translate('+ dx +','+ dy +')';
group.setAttribute('transform', transform);
<svg id='svg' width="400" height="400" viewBox="0 0 400 400">
<path id="my-path" d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/>
<g id="my-group">
<rect width="30" height="20" style="fill:red"/>
</g>
<text font-size="12px" >
<textPath startOffset="10%" xlink:href="#my-path">
<tspan>Hello World</tspan><tspan id='placeholder' visibility="hidden" >-</tspan>
</textPath>
</text>
</svg>

Dynamically create svg group clones which is store in a variable using java script or jquery

i have a lot shapes created using svg tags and which in turn stored in js variables . I want to clone and append the groups to svg element with unique ids using js.
var ped_pb = '<g transform="scale(1.5)" stroke-width=".0005"><path i:knockout="Off" fill-rule="evenodd" clip-rule="evenodd" d="M10.411,0.506V13.17h12.697V0.506H10.411z"/><g> <defs><path id="XMLID_1_" d="M0,0.253h23.87v23.809H0V0.253z"/> </defs> <clipPath id="XMLID_2_"><use xlink:href="#XMLID_1_" /></clipPath><path i:knockout="Off" clip-path="url(#XMLID_2_)" fill="none" stroke="#000000" stroke-width="1.0131" stroke-miterlimit="8" d="M10.411,0.506h12.697V13.17H10.411V0.506z"/></g><g stroke-width=".000000000000000000005"><path i:knockout="Off" clip-path="url(#XMLID_4_)" stroke="#000000" stroke-width="0.0317" stroke-linejoin="round" stroke-miterlimit="10" d="M1.523,23.777l7.555-8.422l-1.523-1.361l-7.523,8.422L1.523,23.777zM7.904,21.782l1.777-8.611l-8.38,2.723c-0.54,0.158-0.825,0.729-0.667,1.267c0.19,0.538,0.762,0.823,1.301,0.665l6.698-2.185l-1.301-1.172l-1.429,6.902c-0.095,0.538,0.254,1.076,0.794,1.203C7.269,22.668,7.777,22.321,7.904,21.782z"/></g></g>';
i need a js function to populate the above shapes stored in variable to an svg element in different x or y coordinates as when required.
i have achieved the goal in the following way
var ped_pb = '<g transform="scale(1.5)" stroke-width=".0005" style="border: 1px dashed black;"><path i:knockout="Off" fill-rule="evenodd" clip-rule="evenodd" d="M10.411,0.506V13.17h12.697V0.506H10.411z"/><g> <defs><path id="XMLID_1_" d="M0,0.253h23.87v23.809H0V0.253z"/> </defs> <clipPath id="XMLID_2_"><use xlink:href="#XMLID_1_" /></clipPath><path i:knockout="Off" clip-path="url(#XMLID_2_)" fill="none" stroke-width="1.0131" stroke-miterlimit="8" d="M10.411,0.506h12.697V13.17H10.411V0.506z"/></g><g stroke-width=".000000000000000000005"><path i:knockout="Off" clip-path="url(#XMLID_4_)" stroke-width="0.0317" stroke-linejoin="round" stroke-miterlimit="10" d="M1.523,23.777l7.555-8.422l-1.523-1.361l-7.523,8.422L1.523,23.777zM7.904,21.782l1.777-8.611l-8.38,2.723c-0.54,0.158-0.825,0.729-0.667,1.267c0.19,0.538,0.762,0.823,1.301,0.665l6.698-2.185l-1.301-1.172l-1.429,6.902c-0.095,0.538,0.254,1.076,0.794,1.203C7.269,22.668,7.777,22.321,7.904,21.782z"/></g></g>';
function clone(){
var element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
element.setAttributeNS(null, 'id', 'lk');
element.innerHTML= ped_pb;
gg.appendChild(element)
element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
element.setAttributeNS(null, 'id', 'lk1');
element.setAttributeNS(null, 'transform', 'translate(40,80)');
element.setAttributeNS(null, 'fill', '#0FF');
element.innerHTML= ped_pb;
gg.appendChild(element)
element = document.createElementNS('http://www.w3.org/2000/svg', 'g');
element.setAttributeNS(null, 'id', 'lk2');
element.setAttributeNS(null, 'transform', 'translate(80,120)');
element.setAttributeNS(null, 'fill', '#f00');
element.innerHTML= ped_pb;
gg.appendChild(element)
}
document.addEventListener("onload",init(),false)
function init()
{
//clone()
clone()
}
<svg id="mySVG" width="400" height="400" xmlns="http://www.w3.org/2000/svg" >
<g id="gg">
<path id="pawn" d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</g>
</svg>

How can this path stroke set the opacity of the group behind it?

I have this code which shows my current output when the snippet is run.
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 300 300" viewBox="0 0 300 300" x="0px" y="0px" xmlns:xml="http://www.w3.org/XML/1998/namespace" xml:space="preserve" version="1.1">
<g fill-opacity=".2">
<path fill="#f79820" d="M 150 0 c 82.8 0 150 67.2 150 150 s -67.2 150 -150 150 S 0 232.8 0 150 S 67.2 0 150 0" />
<circle fill="#f5f4b7" cx="150" cy="150" r="141.9" />
<path fill="#f79820" d="M 135.7 103.3 c 3.5 18.3 4 19 7.8 19.2 c 3.8 0.2 10.4 -4.1 13.6 -12.1 c 3.1 -8 5 -20.2 7.8 -27.9 s 15.4 -29.6 18.7 -39.2 s 0.2 -19.2 -3.1 -23.6 c -3.3 -4.4 -10.7 -4.4 -23.5 -3.4 c -12.7 1 -33.4 -0.1 -40.8 3.4 c -8.4 3.9 -12.1 4.8 -8.9 15.5 C 110.2 45.9 132.2 84.9 135.7 103.3 Z" />
<path fill="#f79820" d="M 153.9 124.2 c -1.7 2.9 3.3 5.6 5.3 5.6 c 2 0 10.1 -2.9 23 -10.4 c 12.9 -7.5 49.9 -25.1 60.2 -35.2 c 10.2 -10 4.3 -22.8 0 -28.9 c -4.3 -6.1 -21 -22.8 -34.4 -29.7 c -13.4 -7 -16.7 1.2 -19.2 12.4 c -2.5 11.2 -12.1 31.1 -15.4 38.2 C 170 83.4 155.5 121.3 153.9 124.2 Z" />
<path fill="#f79820" d="M 213.5 108.7 c -23.7 12.8 -50.5 24.7 -50.4 27.2 c 0.1 3.1 11.1 6.5 27.4 9.9 c 16.4 3.4 29.1 2.5 44.6 9 c 15.5 6.5 36.7 9.9 45 -5.4 s 0.5 -47.6 -8.3 -58.1 c -8.8 -10.5 -10.9 -15.1 -25.6 -3.6 C 240.8 92 227.6 101.1 213.5 108.7 Z" />
<path fill="#f79820" d="M 283.6 167.2 c -2.2 -8.7 -11.1 1.4 -55.9 -8.5 c -44.8 -9.9 -60.7 -13.6 -63 -10.2 c -1.3 1.9 13.4 14.1 36 25.1 c 22.5 11 34.6 21.6 43.7 27.9 c 9.1 6.3 20.2 6.3 26.9 0 C 278.1 195.2 285.8 175.8 283.6 167.2 Z" />
<path fill="#f79820" d="M 226.6 194.7 c -16 -3.6 -35.4 -19 -42.1 -23.8 c -6.8 -4.8 -21.2 -17.1 -25.4 -13.3 c -2.6 2.4 -0.7 15.6 8.4 38.7 s 18.7 56.7 21.6 73.6 c 3 16.8 10.9 9.5 19 2.5 c 8.1 -7 26.4 -21.4 40 -30.7 c 13.6 -9.3 11.6 -19 10.1 -21.7 S 242.6 198.2 226.6 194.7 Z" />
<path fill="#f79820" d="M 157.9 178.9 c -4.1 -13.1 -5.2 -20.5 -9 -20.4 c -4.5 0.2 -9.1 18.7 -12.4 27.4 c -3.3 8.7 -12.7 52.3 -16.7 72.4 c -4 20 -1.8 25.8 15.2 26.7 s 36.7 4.9 42.8 -1 c 6.1 -5.9 5.3 -23.1 0 -44.5 C 172.5 217.9 161.9 192 157.9 178.9 Z" />
<path fill="#f79820" d="M 135.5 171.9 c 2.5 -9.2 3.2 -13.5 -2 -14.3 c -7.1 -1 -17.5 10.5 -25.3 22.1 S 77.5 213.4 63 228.7 c -14.5 15.3 -4 23.8 16 36.2 c 20 12.4 27.9 13.8 31.6 10.9 c 3.6 -2.9 6.6 -26.3 11.1 -43.8 C 126.1 214.4 133 181.1 135.5 171.9 Z" />
<path fill="#f79820" d="M 61.1 227.1 c 5.1 -6.8 32.2 -34.3 40 -44.8 c 7.8 -10.5 26.3 -28.2 27.9 -29.2 c 1.7 -1 -1.1 -4 -3.8 -6.8 c -2.1 -2.1 -2.8 -1.2 -11.1 0 c -8.3 1.2 -39 13.4 -53.4 17.7 c -14.4 4.2 -22.5 3.9 -31.1 7.5 c -8.6 3.6 -11.7 12.4 -1.7 26.8 c 10.1 14.4 6.3 18.9 13.6 28.9 C 48.9 237.1 56 233.9 61.1 227.1 Z" />
<path fill="#f79820" d="M 25.8 169.4 c 9.1 -1 41.5 -11.6 59.2 -18.9 c 17.7 -7.3 40.9 -11.4 40.7 -13.9 c -0.5 -5.6 -29.9 -17 -40.5 -22.6 c -10.6 -5.6 -25 -19.9 -35.4 -25.1 c -10.4 -5.3 -23.3 -4.8 -25.4 8.2 c -2.1 12.9 -8.8 27.9 -11.4 48 C 10.2 165.1 16.7 170.4 25.8 169.4 Z" />
<path fill="#f79820" d="M 54.5 88.3 c 16 5.4 37.5 19.7 43.1 24 c 5.6 4.2 31.2 20.9 35.2 17.5 c 3.4 -2.9 0.3 -21.1 -6.3 -31.8 c -6.6 -10.7 -9.1 -29.4 -14.5 -45.2 c -5.5 -15.8 -17.7 -28.4 -34 -18 s -33.4 24.8 -37.8 36 C 35.7 82 38.5 82.9 54.5 88.3 Z" />
</g>
<svg style="display: block; width: 100%;" viewBox="0 0 100 100">
<path stroke="#f79820" stroke-opacity=".4" fill-opacity="0" style="stroke-dasharray: 157.698, 157.698; stroke-dashoffset: 55;" stroke-width="49.81" d="M 50,50 m 0,-25.095 a 25.095,25.095 0 1 1 0,50.19 a 25.095,25.095 0 1 1 0,-50.19" />
</svg>
</svg>
My goal is to get everything covered by the stroke to be shown "darker" than the remaining portion of the circle. However the effect that is happening is the opacity of the stroke is compounding with the groups opacity so it doesn't have the contrast it needs to have.
Ideally it would look something like this...
Would inverting the pieces be an option? Instead of darkening the section, lighten the inverse? I removed the fill-opacity on the outer svg, changed the stroke of the inner path to white and increased the opacity to .6. I did not change the path, though, this was just to demonstrate the concept.
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 300 300" viewBox="0 0 300 300" x="0px" y="0px" xmlns:xml="http://www.w3.org/XML/1998/namespace" xml:space="preserve" version="1.1">
<g>
<path fill="#f79820" d="M 150 0 c 82.8 0 150 67.2 150 150 s -67.2 150 -150 150 S 0 232.8 0 150 S 67.2 0 150 0" />
<circle fill="#f5f4b7" cx="150" cy="150" r="141.9" />
<path fill="#f79820" d="M 135.7 103.3 c 3.5 18.3 4 19 7.8 19.2 c 3.8 0.2 10.4 -4.1 13.6 -12.1 c 3.1 -8 5 -20.2 7.8 -27.9 s 15.4 -29.6 18.7 -39.2 s 0.2 -19.2 -3.1 -23.6 c -3.3 -4.4 -10.7 -4.4 -23.5 -3.4 c -12.7 1 -33.4 -0.1 -40.8 3.4 c -8.4 3.9 -12.1 4.8 -8.9 15.5 C 110.2 45.9 132.2 84.9 135.7 103.3 Z" />
<path fill="#f79820" d="M 153.9 124.2 c -1.7 2.9 3.3 5.6 5.3 5.6 c 2 0 10.1 -2.9 23 -10.4 c 12.9 -7.5 49.9 -25.1 60.2 -35.2 c 10.2 -10 4.3 -22.8 0 -28.9 c -4.3 -6.1 -21 -22.8 -34.4 -29.7 c -13.4 -7 -16.7 1.2 -19.2 12.4 c -2.5 11.2 -12.1 31.1 -15.4 38.2 C 170 83.4 155.5 121.3 153.9 124.2 Z" />
<path fill="#f79820" d="M 213.5 108.7 c -23.7 12.8 -50.5 24.7 -50.4 27.2 c 0.1 3.1 11.1 6.5 27.4 9.9 c 16.4 3.4 29.1 2.5 44.6 9 c 15.5 6.5 36.7 9.9 45 -5.4 s 0.5 -47.6 -8.3 -58.1 c -8.8 -10.5 -10.9 -15.1 -25.6 -3.6 C 240.8 92 227.6 101.1 213.5 108.7 Z" />
<path fill="#f79820" d="M 283.6 167.2 c -2.2 -8.7 -11.1 1.4 -55.9 -8.5 c -44.8 -9.9 -60.7 -13.6 -63 -10.2 c -1.3 1.9 13.4 14.1 36 25.1 c 22.5 11 34.6 21.6 43.7 27.9 c 9.1 6.3 20.2 6.3 26.9 0 C 278.1 195.2 285.8 175.8 283.6 167.2 Z" />
<path fill="#f79820" d="M 226.6 194.7 c -16 -3.6 -35.4 -19 -42.1 -23.8 c -6.8 -4.8 -21.2 -17.1 -25.4 -13.3 c -2.6 2.4 -0.7 15.6 8.4 38.7 s 18.7 56.7 21.6 73.6 c 3 16.8 10.9 9.5 19 2.5 c 8.1 -7 26.4 -21.4 40 -30.7 c 13.6 -9.3 11.6 -19 10.1 -21.7 S 242.6 198.2 226.6 194.7 Z" />
<path fill="#f79820" d="M 157.9 178.9 c -4.1 -13.1 -5.2 -20.5 -9 -20.4 c -4.5 0.2 -9.1 18.7 -12.4 27.4 c -3.3 8.7 -12.7 52.3 -16.7 72.4 c -4 20 -1.8 25.8 15.2 26.7 s 36.7 4.9 42.8 -1 c 6.1 -5.9 5.3 -23.1 0 -44.5 C 172.5 217.9 161.9 192 157.9 178.9 Z" />
<path fill="#f79820" d="M 135.5 171.9 c 2.5 -9.2 3.2 -13.5 -2 -14.3 c -7.1 -1 -17.5 10.5 -25.3 22.1 S 77.5 213.4 63 228.7 c -14.5 15.3 -4 23.8 16 36.2 c 20 12.4 27.9 13.8 31.6 10.9 c 3.6 -2.9 6.6 -26.3 11.1 -43.8 C 126.1 214.4 133 181.1 135.5 171.9 Z" />
<path fill="#f79820" d="M 61.1 227.1 c 5.1 -6.8 32.2 -34.3 40 -44.8 c 7.8 -10.5 26.3 -28.2 27.9 -29.2 c 1.7 -1 -1.1 -4 -3.8 -6.8 c -2.1 -2.1 -2.8 -1.2 -11.1 0 c -8.3 1.2 -39 13.4 -53.4 17.7 c -14.4 4.2 -22.5 3.9 -31.1 7.5 c -8.6 3.6 -11.7 12.4 -1.7 26.8 c 10.1 14.4 6.3 18.9 13.6 28.9 C 48.9 237.1 56 233.9 61.1 227.1 Z" />
<path fill="#f79820" d="M 25.8 169.4 c 9.1 -1 41.5 -11.6 59.2 -18.9 c 17.7 -7.3 40.9 -11.4 40.7 -13.9 c -0.5 -5.6 -29.9 -17 -40.5 -22.6 c -10.6 -5.6 -25 -19.9 -35.4 -25.1 c -10.4 -5.3 -23.3 -4.8 -25.4 8.2 c -2.1 12.9 -8.8 27.9 -11.4 48 C 10.2 165.1 16.7 170.4 25.8 169.4 Z" />
<path fill="#f79820" d="M 54.5 88.3 c 16 5.4 37.5 19.7 43.1 24 c 5.6 4.2 31.2 20.9 35.2 17.5 c 3.4 -2.9 0.3 -21.1 -6.3 -31.8 c -6.6 -10.7 -9.1 -29.4 -14.5 -45.2 c -5.5 -15.8 -17.7 -28.4 -34 -18 s -33.4 24.8 -37.8 36 C 35.7 82 38.5 82.9 54.5 88.3 Z" />
</g>
<svg style="display: block; width: 100%;" viewBox="0 0 100 100">
<path stroke="#ffffff" stroke-opacity=".6" fill-opacity="0" style="stroke-dasharray: 157.698, 157.698; stroke-dashoffset: 55;" stroke-width="49.81" d="M 50,50 m 0,-25.095 a 25.095,25.095 0 1 1 0,50.19 a 25.095,25.095 0 1 1 0,-50.19" />
</svg>
</svg>

How do I use javascript to clone an SVG element?

I am trying to follow the example here under the cloneNode section (fourth occurrence of 'cloneNode' in the document). The document says it's a DRAFT so i'm wondering if these features don't exist with SVG yet??
Here is my HTML:
<html>
<head>
<script>
var Root=document.documentElement
function clone(){
var G=document.getElementById("groupid")
alert('hi')
var NewG=G.cloneNode(true)
alert('bye')
var move="translate("+0+","+30+")"
NewG.setAttributeNS(null,"transform",move)
Root.appendChild(NewG)
}
clone()
</script>
</head>
<body>
<div style="" width="100px" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" viewBox="0 0 1 1" style="fill:purple;stroke:red" id="bigsvg"><?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<svg width="100%" ID="piece" y="0" x="0" class="black" height="100%">
<g transform="translate(0.005) scale(0.022)" id="groupid">
<path class="onepointsix" d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</g>
</svg>
</svg>
</div>
</body>
</html>
As you can see, the alert 'bye' doesn't work. Thanks in advance for the help.
When you call getElementById, the element doesn't yet exist. Put the script at the end of the body :
<head>
</head>
<body>
<div style="" width="100px" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200px" viewBox="0 0 1 1" style="fill:purple;stroke:red" id="bigsvg"><?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%">
<svg width="100%" ID="piece" y="0" x="0" class="black" height="100%">
<g transform="translate(0.005) scale(0.022)" id="groupid">
<path class="onepointsix" d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</g>
</svg>
</svg>
</div>
<script>
var Root=document.documentElement
function clone(){
var G=document.getElementById("groupid")
alert('hi')
var NewG=G.cloneNode(true)
alert('bye')
var move="translate("+0+","+30+")"
NewG.setAttributeNS(null,"transform",move)
Root.appendChild(NewG)
}
clone()
</script>
</body>
</html>
This seems to be more complicated than need be. Start with just your pawn path in your root svg. Then clone, and append to root. One of the important things to address that once you clone, you should change the id of the cloned element. Otherwise you will get a conflict when addressing the original cloned element.
Try This:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Title</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style='font-family:arial'>
<center>
<div id="svgDiv" style='background-color:lightgreen;width:400px;height:400px;'>
<svg id="mySVG" width="400" height="400" xmlns="http://www.w3.org/2000/svg" >
<path id="pawn" d="M 22 9 C 19.792 9 18 10.792 18 13 C 18 13.885103 18.29397 14.712226 18.78125 15.375 C 16.829274 16.496917 15.5 18.588492 15.5 21 C 15.5 23.033947 16.442042 24.839082 17.90625 26.03125 C 14.907101 27.08912 10.5 31.578049 10.5 39.5 L 33.5 39.5 C 33.5 31.578049 29.092899 27.08912 26.09375 26.03125 C 27.557958 24.839082 28.5 23.033948 28.5 21 C 28.5 18.588492 27.170726 16.496917 25.21875 15.375 C 25.70603 14.712226 26 13.885103 26 13 C 26 10.792 24.208 9 22 9 z " />
</svg>
</div>
<br />SVG Source:<br />
<textarea id=svgSourceValue style='font-size:110%;font-family:lucida console;width:90%;height:200px'></textarea>
<br />Javascript:<br />
<textarea id=jsValue style='border-radius:26px;font-size:110%;font-weight:bold;color:midnightblue;padding:16px;background-color:beige;border-width:0px;font-size:100%;font-family:lucida console;width:90%;height:400px'></textarea>
</center>
<script id=myScript>
var Root=mySVG
function clone(){
var newPawn=pawn.cloneNode(true)
newPawn.id="newPawn1"
var move="translate("+0+","+30+")"
newPawn.setAttribute("transform",move)
Root.appendChild(newPawn)
}
</script>
<script>
document.addEventListener("onload",init(),false)
function init()
{
clone()
svgSourceValue.value=svgDiv.innerHTML
jsValue.value=myScript.text
}
</script>
</body>
</html>
To make it clear what was causing errors:
var Root=document.documentElement was wrong because we need to make sure the new clone gets added to its parent SVG, not at the end of the page. Instead we must add an id="mySVG" to the parent and then use var Root=mySVG.
var G=document.getElementById("groupid") didn't grab the 'groupid' element because the code ran before the element existed. The solution is to trigger the code to run AFTER the page loads (use onload event, or move the script to the bottom of the body).
var move="translate("+0+","+30+")" was replacing the transform property in the SVG group, overwriting the old translate AND the scale(0.022). Therefore, while the clone existed after fixing the above two errors, it was so far down that it was out of the viewBox. Instead I should use var move="translate(0,1) scale(0.022)"

Parse SVG and add it to a svg element

I have a service where I want to dynamically add SVG parts to a g element. This is what the service returns:
<g xmlns="http://www.w3.org/2000/svg" style="pointer-events: all;" opacity="1">
<title style="pointer-events: inherit;">Layer 1</title>
<path id="svg_1" style="pointer-events: inherit;" fill="none" stroke="#000000" stroke-width="5" d="M 231.5 122.5 C 230.5 122.5 221.666 124.214 214.5 125.5 C 201.667 127.803 184.514 129.581 173.5 131.5 C 167.508 132.544 164.077 131.928 158.5 136.5 C 155.219 139.19 152 144.469 151.5 156.5 C 151.375 159.497 150.696 163.582 151.5 167.5 C 153.031 174.96 161.804 180.205 170.5 189.5 C 177.762 197.263 185.013 204.954 192.5 212.5 C 200.981 221.048 208.5 226.5 214.5 232.5 C 219.5 237.5 224.834 240.27 227.5 244.5 C 230.219 248.814 230.986 251.324 231.5 253.5 C 231.96 255.447 231.5 258.5 231.5 260.5 C 231.5 262.5 228.786 265.712 226.5 268.5 C 224.707 270.687 221.213 274.151 217.5 277.5 C 213.17 281.405 207.5 283.5 203.5 285.5 C 199.5 287.5 195.676 289.986 193.5 290.5 C 190.58 291.189 188.5 292.5 187.5 292.5 L 186.5 292.5 L 186.5 293.5" />
<path id="svg_2" style="pointer-events: inherit;" fill="none" stroke="#000000" stroke-width="5" d="M 39.5 35.5 C 40.5 35.5 42.5 35.5 45.5 35.5 C 47.5 35.5 50.5 35.5 52.5 35.5 C 54.5 35.5 56.5 35.5 57.5 35.5 L 58.5 35.5 L 59.5 35.5" />
<path id="svg_3" style="pointer-events: inherit;" fill="none" stroke="#000000" stroke-width="5" d="M 40.5 95.5 C 40.5 97.5 39.8088 103.572 38.5 108.5 C 36.8767 114.613 35.5 117.5 35.5 119.5 C 35.5 121.5 34.5 122.5 34.5 123.5 L 33.5 123.5 L 33.5 124.5 L 33.5 125.5" />
<path id="svg_6" style="pointer-events: inherit;" fill="none" stroke="#000000" stroke-width="5" d="M 81.5 176.5" /><path id="svg_7" style="pointer-events: inherit;" fill="none" stroke="#000000" stroke-width="5" d="M 79.5 167.5 C 79.5 170.5 80.1835 178.521 79.5 189.5 C 78.999 197.547 76.9069 204.357 75.5 211.5 C 73.75 220.385 72.663 227.522 71.5 235.5 C 70.6226 241.519 70.5 245.5 70.5 247.5 C 70.5 249.5 70.5 250.5 69.5 250.5 L 69.5 251.5 L 69.5 252.5" />
</g>
The code I'm trying to use which has been modified many times is something to the affect of this:
function parseSVG(s, layer) {
var div= $(s);
for(var i = 0; i < div.children.length; i++) {
layer.append(div.children[i]);
}
}
layer is the g element s is the svg from above. The closest I can get is adding title then all the path elements at once inside of svg_1.
You can use DOMParser to parse an XML string.
var parser = new DOMParser();
var doc = parser.parseFromString(stringContainingXMLSource, "image/svg+xml");
The <g> in your example will be doc.documentElement
In addition to Robert's answer, you can convert the HTMLCollection to SVGElement in this way :
const yourSvgElement = doc.getElementsByTagNameNS("http://www.w3.org/2000/svg", "svg").item(0);
// yourSvgElement is now a SVGElement type
Please note that the converted element is the first in the collection.
See : HTMLCollection.item

Categories

Resources