SVG animateTransform with href - javascript

Trying to move an SVG element using javascript for an interactive game;
<!DOCTYPE html>
<html>
<body>
<svg width="300" height="300">
<circle id="circ" cx="50" cy="50" r="40" fill="black" ></circle>
<animateTransform xlink:href="#circ" attributeName="transform" attributeType="XML" type="translate" from="50 50" to="200 200" dur="1s" repeatCount="1"></animateTransform>
</svg>
</body>
</html>
However, the element drops back to its original position after the animation.
Any suggestions to make the element stay put in the new position?
.

Add fill="freeze" if you want the final animation state to apply after the animation has ended.
<!DOCTYPE html>
<html>
<body>
<svg width="300" height="300">
<circle id="circ" cx="50" cy="50" r="40" fill="black" >
</circle>
<animateTransform xlink:href="#circ" attributeName="transform" attributeType="XML" type="translate" from="50 50" to="200 200" dur="1s" repeatCount="1" fill="freeze"></animateTransform>
</svg>
</body>
</html>

<!DOCTYPE html>
<html>
<body>
<svg width="300" height="300">
<circle id="circ" cx="50" cy="50" r="40" fill="black" >
</circle>
<animateTransform xlink:href="#circ" attributeName="transform" attributeType="XML" type="translate" from="50 50" to="200 200" dur="1s" repeatCount="1" fill="freeze" ></animateTransform>
</svg>
</body>
</html>
You just required to use fill freeze.

Related

How to increase stroke outside of svg path without using paint-order="stroke"?

I am facing a problem while increasing stroke width. When I am using the attribute paint-order="stroke" it's not meet my requirement, because stroke width increasing on both sides (inside and outside). Please look into the attached images.
original svg :-
Actual svg :-
Expected svg(Which is my requirement) :-
Code :-
<html>
<body>
<svg height="300" width="500">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="20" paint-order="stroke" fill="red" />
<circle cx="152" cy="50" r="40" stroke="black" stroke-width="20" paint-order="stroke" fill="none" />
<circle cx="252" cy="50" r="40" stroke="black" stroke-width="10" paint-order="stroke" fill="none" />
</svg>
</body>
</html>
A stroke with a width of 20px of a circle is symmetrically located on either side of the centerline. 10px outside, 10px inside the circle
The circle at the top has a smaller radius equal to half the stroke of the lower circle 40 - 10 = 30px
Therefore, the inside of the stroke of the lower, larger circle will be hidden. Only the outside of the large circle will be visible.
<html>
<body>
<svg height="300" width="500">
<!-- Sample circle without overlap -->
<circle cx="52" cy="50" r="40" stroke="black" stroke-width="20" paint-order="stroke" fill="none" /> >
<circle cx="152" cy="50" r="40" stroke="blue" stroke-width="20" paint-order="stroke" fill="none" />
<!-- The circle at the top has a smaller radius equal to half the stroke of the lower circle -->
<circle cx="152" cy="50" r="30" stroke="white" stroke-width="20" paint-order="stroke" fill="none" />
</svg>
</body>
</html>

How to combine two animateTransformation not silmutaneously but consecutively?

I have the following transformations
<svg height="205" width="365" xmlns="http://www.w3.org/2000/svg"> <!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ --> <g>
<title></title>
<rect fill="none" height="207" id="canvas_background" width="367" x="-1" y="-1"></rect> </g> <g>
<title></title>
<g id="svg_3"> <path class="hinh1" d="m22,88.5a67.5,67.5 0 0 1 135,0l-135,0z" fill="none" id="svg_1" stroke="#000" stroke-width="1.5" style="fill: rgb(92, 188, 214);stroke-linejoin: round;/* x: 100; *//* y: 100px; */"></path> <g transform="translate(-132.281 0)"><path class="hinh2" d="m207.0027,88.5a67.5,67.5 0 0 1 135,0l-135,0z" fill="none" id="svg_2" stroke="#000" stroke-width="1.5" transform="rotate(180 274.503 54.7665) translate(0 70.8138) translate(0 -82.7702)" style="fill: rgb(214, 92, 188); stroke-linejoin: round;">
</path>
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="0 56" begin="0s" dur="5s" repeatCount="indefinite" id="one">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="-185 0" begin="one.end" dur="5s" repeatCount="indefinite">
</animateTransform>
</g> </g> </g> </svg>
I want the right semicircle to go down THEN go left (not simultaneously) to snap to the left semicircle.
I found that, the following code does not work as I expect, only the second one is triggered. Isn't it the case that one.end has no meaning here?
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="0 56" begin="0s" dur="5s" repeatCount="indefinite" id="one">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" from="0 0" to="-185 0" begin="one.end" dur="5s" repeatCount="indefinite">
</animateTransform>
In addition, at the end of the animations, I want the right to stop for about 3s before repeating, how to do so?
Instead of using the to and for attributes you can animate between several values by using the values attribute where the values for the transformation are separates by semicolons:
<svg height="205" width="365" xmlns="http://www.w3.org/2000/svg">
<g>
<rect fill="none" height="207" id="canvas_background" width="367" x="-1" y="-1"></rect>
</g>
<g id="svg_3">
<path class="hinh1" d="m22,88.5a67.5,67.5 0 0 1 135,0l-135,0z" fill="none" id="svg_1" stroke="#000" stroke-width="1.5" style="fill: rgb(92, 188, 214);stroke-linejoin: round;"></path>
<g>
<path class="hinh2" d="m207.0027,88.5a67.5,67.5 0 0 1 135,0l-135,0z" fill="none" id="svg_2" stroke="#000" stroke-width="1.5" transform="rotate(180 274.503 54.7665) translate(0 70.8138) translate(0 -82.7702)" style="fill: rgb(214, 92, 188); stroke-linejoin: round;">
</path>
<animateTransform attributeName="transform" attributeType="XML" type="translate" values="0 0;0 56;-185,56" begin="0s" dur="5s" repeatCount="1" fill="freeze" id="one">
</animateTransform>
</g>
</g>
</svg>

Will hidden / obscured SVG animations still cause browser repaints and or performance issues?

I'm considering putting an SVG spinner animation behind some images I'm loading and then having the image stacked on top of the spinner so that the spinner is obscured when the image is loaded. Planning to apply this to a list view with potentially hundreds of items.
First question is, will the obscured SVG spinner (once its respective image loads) continue to cause the browser to repaint? (that sounds expensive)
If yes, the next question would be, if I hide (display: none) the spinner when the image loads, will the hidden spinner continue to cause repainting?
Any other performance thoughts are very welcome.
FWIW, this is an Electron app, so Chromium (a relatively up to date version) is the only browser we're concerned with.
This got me interested... using an example SVG I whipped together this test (excuse how scrummy the code is):
document.onclick = function() {
output.innerHTML += (mySVG.innerHTML + output.innerHTML).replace(/<circle /g,"<circle style='opacity: 0' ");
preview.innerHTML += mySVG.innerHTML;
}
<div id="mySVG">
<svg width="30px" height="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-dual-ring">
<circle cx="50" cy="50" fill="none" stroke-linecap="round" r="40" stroke-width="4" stroke="#facd9e" stroke-dasharray="62.83185307179586 62.83185307179586" transform="rotate(115.488 50 50)">
<animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform>
</circle>
<circle cx="50" cy="50" fill="none" stroke-linecap="round" r="35" stroke-width="4" stroke="#389798" stroke-dasharray="54.97787143782138 54.97787143782138" stroke-dashoffset="54.97787143782138" transform="rotate(-115.488 50 50)">
<animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;-360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform>
</circle>
</svg>
</div>
<div id="output"></div>
<div id="preview"></div>
As you can see, when you click lots on the document, all the fully transparent spinning circles start to slow down the browser rendering. Looks like the animations do still trigger.
In this example with display: none; we get the same result, the div#preview is noticeably slower:
document.onclick = function() {
output.innerHTML += (mySVG.innerHTML + output.innerHTML).replace(/<circle /g,"<circle style='display: none' ");
preview.innerHTML += mySVG.innerHTML;
}
<div id="mySVG">
<svg width="30px" height="30px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-dual-ring">
<circle cx="50" cy="50" fill="none" stroke-linecap="round" r="40" stroke-width="4" stroke="#facd9e" stroke-dasharray="62.83185307179586 62.83185307179586" transform="rotate(115.488 50 50)">
<animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform>
</circle>
<circle cx="50" cy="50" fill="none" stroke-linecap="round" r="35" stroke-width="4" stroke="#389798" stroke-dasharray="54.97787143782138 54.97787143782138" stroke-dashoffset="54.97787143782138" transform="rotate(-115.488 50 50)">
<animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;-360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform>
</circle>
</svg>
</div>
<div id="output"></div>
<div id="preview"></div>

How to implement a html element inside a javascript code?

I am trying to design a sample web page, and I'm facing some issues with svg....
I have created an svg circle with a line over it which will rotate with in the circle. Here is the sample code.
<?xml version="1.0" encoding="iso-8859-1"?>
<svg width="100%" height="100%">
<circle cx="200" cy="200" r="100" stroke="black" stroke-width="4" fill="black" />
<g transform="translate(200,200)">
<line x1="0" y1="0" x2="100" y2="0" style="stroke:rgb(255,255,255);stroke-width:2">
<animateTransform attributeName="transform"
attributeType="XML"
type="rotate"
from="25" to="360" dur="100s"/>
</line>
</svg>
In the sample code above the 'line' will start rotating immediately when the page is launched, but I want the line to be rotated after I press the START button, something like this...
<input type="button" value=" START " onclick="start()" class="control-menu-top-btn" id="green-btn">
<script language="javascript" type="text/javascript">
function start()
{
.. ?
}
</script>
The beginElement method will start an animation. Setting the begin attribute to indefinite in the markup will stop it from running before the javascript starts it.
html, body {
width: 100%;
height: 100%;
}
<input type="button" value=" START " onclick="start()" class="control-menu-top-btn" id="green-btn">
<script>
function start()
{
document.getElementById("transform").beginElement();
}
</script>
<svg width="100%" height="100%">
<circle cx="200" cy="200" r="100" stroke="black" stroke-width="4" fill="black" />
<g transform="translate(200,200)">
<line x1="0" y1="0" x2="100" y2="0" style="stroke:rgb(255,255,255);stroke-width:2">
<animateTransform id="transform" attributeName="transform"
attributeType="XML"
type="rotate"
from="25" to="360" dur="100s" begin="indefinite" />
</line>
</g>
</svg>

How to get coordinates of element during animation in SVG

I have such code:
<defs>
<g id="g0">
<circle cx="0" cy="1" r="16" fill="blue" id="pr0" stroke-width="0" stroke="#2986dc"/>
<circle cx="0" cy="0" r="14" fill="red" id="pp0" />
</g>
</defs>
<use x="603" y="484" id="u0" href="#g0">
<animateTransform attributeName="transform" attributeType="XML" type="rotate" id="t0" dur="30s" repeatCount="indefinite" from="0 494 494" to="360 494 494"/>
</use>
How can i get coordinates of group during animation using JavaScript?
The SVG 1.2 Micro DOM provides the get*PresentationTrait*() class of methods for accessing animated values, but I don't think they are supported yet by browsers. So maybe the easiest way would be to resort to JavaScript animation.

Categories