Dynamic Animation for SVG Elements is not working in IE - javascript

I'm trying to do SVG element's animation while dynamically adding DOM elements with jquery. If I add those elements inside <body> as below its working.Working Sample for this is
http://jsfiddle.net/bZdfH/2/
<svg>
<script type="text/ecmascript" xlink:href="http://leunen.me/fakesmile/smil.user.js"/>
<circle cx="60" cy="60" r="20" style="fill: pink; stroke: red;" >
<animate attributeName="r" dur="4s" values="20; 0; 20" repeatCount="indefinite"/>
</circle>
</svg>
When I add it dynamically, animation will not start in IE, however it works with Chrome and FireFox.Here is what I have.
<svg>
<script type="text/ecmascript" xlink:href="http://leunen.me/fakesmile/smil.user.js"/>
<circle cx="60" cy="60" r="20" style="fill: pink; stroke: red;" onmouseover="changeImage(this)" >
</circle>
</svg>
<script>
function changeImage(circle) {
while (circle.firstChild) {
circle.removeChild(circle.firstChild);
}
circle.setAttributeNS(null, "fill", "blue");
var animate = document.createElementNS("http://www.w3.org/2000/svg", "animate");
animate.setAttributeNS(null, "attributeName", "r");
animate.setAttributeNS(null, "values", "20;0;20");
animate.setAttributeNS(null, "dur", "6s");
animate.setAttributeNS(null, "repeatCount", "indefinite");
circle.appendChild(animate);
}
</script>
Here is jsfiddle for the Working Sample.Can anyone please help me??

IE doesn't support SMIL animation.
Source : http://caniuse.com/#search=svg

Related

Can I make a transition on an SVG attribute that is not CSS?

I have an SVG that I would like to transition to extend when the mouse hovers over it, and ease back to its normal size when the mouse is not hovering. Because it is not adjusted through CSS, I can't figure out how to make that transition happen.
https://codepen.io/BrendanOB/pen/LYYepQQ
^ A link to an example of what I've got so far
Im new to javascript, any help is greatly appreciated, thank you.
I have already tried CSS transform scale and matrix, without working results.
<style>
.st2{fill:#E5CACA;}
.st3{fill:none;stroke:#FFF;stroke-width:17;stroke-linecap:round;stroke-miterlimit:10;}
</style>
<g id="Layer_2">
<line class="st3" x1="500" y1="142" x2="500" y2="95"/>
<line onmouseover="bigLine()" onmouseleave="smallLine()" id="move" class="st3" x1="518.2" y1="142.9" x2="521.8" y2="96.1"/>
<line id="stretch" class="st3" x1="536" y1="144.7" x2="544" y2="98.3"/>
</g>
<script>
function bigLine(){
var lines = document.querySelector('#Layer_2')
var l = lines.querySelector('#move')
console.log(l);
l.transition = "all 2s";
l.setAttribute("y2", "26");
}
function smallLine(){
var lines = document.querySelector('#Layer_2')
var l = lines.querySelector('#move')
console.log(l);
l.transition = "all 2s";
l.setAttribute("y2", "96");
}
</script>
As Robert Longson commented you can use SMIL animations: Inside the line #move there are 2 <animate> elements: the first for the mouseover and the second for mouseleave.
The first animation is changing the value of the x2 attribute of the line from="96.1" to="26". The second element has no from attribute but is animating the value of the y2 to="96.1" The duration of both animations is dur="1s" and fill="freeze" is similar to the animation-fill-mode: forwards from CSS.
I hope it helps.
.st2 {
fill: #e5caca;
}
.st3 {
fill: none;
stroke: #ddd;
stroke-width: 17;
stroke-linecap: round;
stroke-miterlimit: 10;
}
<svg viewBox="0 0 1000 1000" style="enable-background:new 0 0 1000 1000;">
<g id="Layer_2">
<line class="st3" x1="500" y1="142" x2="500" y2="95"/>
<line id="move" class="st3" x1="518.2" y1="142.9" x2="521.8" y2="96.1">
<animate
attributeType="XML"
attributeName="y2"
from="96.1" to="26"
begin="mouseover"
dur="1s"
fill="freeze" />
<animate
attributeType="XML"
attributeName="y2"
to="96.1"
begin="mouseleave"
dur="1s"
fill="freeze" />
</line>
<line id="stretch" class="st3" x1="536" y1="144.7" x2="544" y2="98.3"/>
</g>
</svg>

How do I style one of the parameters in a circle inside an SVG?

I have a SVG with circles inside it. And I want them to be increasing and decreasing in radius for ever (like a pulsating circle).
My problem is, can I do it with #keyframes? Or do I need jquery? And if so, how?
Here is my code:
<div class="mapa">
<svg (svg code here......)
<circle opacity="0.3" cx="842" cy="451.814" r="25.582" id="1"/>
<circle opacity="0.3" cx="542" cy="405.814" r="25.582" id="1"/>
</svg>
</div>
How do I style the 'r' parameter?
I read I cannot style the 'r' parameter, but this worked:
<circle cx="168" cy="179" r="59"
fill="white" stroke="black"
onmouseover="evt.target.setAttribute('r', '72');"
onmouseout="evt.target.setAttribute('r', '59');"
/>
However, I want to do it with continuous increase and decrease in radius? And not on mouseover/mouseleave. Something like (r=25, then r=30, then back to 25, and goes on forever). How do I do this?
Thanks for your time, if you can give me any tips I'd apreciate it a lot!
Try to use svg smil animate
<svg width="150" height="150">
<circle opacity="0.3" cx="84%" cy="45%" r="3" id="1">
<animate attributeName="r" values="3; 10; 3" keyTimes="0; 0.5; 1" dur="1s" repeatCount="indefinite" />
</circle>
<circle opacity="0.3" cx="50%" cy="50%" r="10" id="2">
<animate attributeName="r" values="10; 3; 10" keyTimes="0; 0.5; 1" dur="1s" repeatCount="indefinite"/>
</circle>
</svg>
The easiest solution in CSS with a little hack around SVG containers. You change the container, not the svg. The circle element just fills 100% of the container. And the container artificially makes a circle with a border-radius.
svg {
border-radius: 50%;
transition: all 1s;
}
svg:hover {
width: 200px;
height: 200px;
}
<svg width="100" height="100">
<circle cx="50" cy="50" r="100%"
fill="green" />
</svg>
You can figure out how to implement your own keyframes, if this solution works for you.
And just to be clear, JQuery is a framework. You shouldn't bring up JQuery unless this question is about JQuery's framework. The language you're looking for is "Javascript" and it's in all major browsers by default. You can use Javascript to do this.
const grow = function(radius) {
var circle = document.getElementsByTagName("circle")[0];
circle.setAttribute('r', radius);
}
setTimeout(function() {
grow(100);
setTimeout(function() {
grow(40);
}, 2000);
}, 2000);
circle {
transition: all 1s;
}
<svg width="200" height="200">
<circle cx="100" cy="100" r="40"
fill="green" />
</svg>

"ellipse" element created through JS doesn't appear in html

I'm new to svg. What i'm trying to do is to create an ellipse element with JS and append it to the SVG tag. The HTML code is
<svg width="640" height="480">
<ellipse cx="200" cy="100" rx="90" ry="60" stroke-width="10" stroke="orange" fill="none" opacity="0.6"/>
<ellipse cx="200" cy="100" rx="70" ry="40" stroke-width="10" stroke="green" fill="none" opacity="0.6"/>
</svg>
Below is the JS code
<script type="text/javascript">
var el=document.createElement('ellipse');
$(el).attr("cx",300);
$(el).attr("cy",200);
$(el).attr("stroke","red");
$(el).attr("stroke-width","10");
$(el).attr("fill","green");
$(el).attr("rx",120);
$(el).attr("ry",80);
$("svg").append(el);
</script>
But the ellipse didn't appear on the viewport ,but when i inspect HTML i found the ellipse element that i created is appended to SVG. what makes the difference when created this way & what is the correct approach to dynamically add elements to SVG
FYI see the image below
What you have is a custom HTML element instead of an SVG element. Use createElementNS to create the SVG element:
$(function(){
var el = document.createElementNS("http://www.w3.org/2000/svg", 'ellipse');
el.setAttribute('cx', 300);
el.setAttribute('cy', 200);
el.setAttribute('stroke', "red");
el.setAttribute('stroke-width', 10);
el.setAttribute('fill', "green");
el.setAttribute('rx', 120);
el.setAttribute('ry', 80);
$("svg").append(el);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<svg width="640" height="480">
<ellipse cx="200" cy="100" rx="90" ry="60" stroke-width="10" stroke="orange" fill="none" opacity="0.6"/>
<ellipse cx="200" cy="100" rx="70" ry="40" stroke-width="10" stroke="green" fill="none" opacity="0.6"/>
</svg>

Changing style of SVG elements in a g group using JS

Can I change the css style, such as fill or stroke, for all elements within a g group using JS?
Here's the svg, script and the external css:
<g id="trajectories" class="trajectory">
<circle id="tr1" cx="0" cy="0" r="75" />
<circle id="tr2" cx="0" cy="0" r="110" />
<circle id="tr3" cx="0" cy="0" r="160" />
<circle id="tr4" cx="0" cy="0" r="230" />
<circle id="tr5" cx="0" cy="0" r="350" />
<circle id="tr6" cx="0" cy="0" r="475" />
<circle id="tr7" cx="0" cy="0" r="625" />
<circle id="tr8" cx="0" cy="0" r="750" />
</g>
function mouseDown() {
svgElement = document.getElementById("trajectories");
svgElement.style.stroke = "Black";
}
g.trajectory{
fill: none;
stroke: rgba(30,30,30,1);
}
The circles in the g inherit the fill and stroke of the class g.trajectory when first drawn, but attempting to change the styling of the g element does nothing. I could change the styles of the circles individually, but is it possible to change them all just by targeting the g element?
You tried targetting the circle with straight css?
I.E
g circle {color:#ff0000;}
On the fiddles below i added a little bit in between your circle tags just for demo purpose
Here is a fiddle of this http://jsfiddle.net/vTNrR/
Or with jquery
$('#trajectories circle').css('color','#ff0000');
Here is a fiddle of the JQuery approach http://jsfiddle.net/vTNrR/4/
Or with javascript
var svgElement = document.getElementById("trajectories"); // get the parent node
var circles = svgElement.getElementsByTagName('circle'); // get child nodes
You now have an array of elements in circles so can do something like
for (var i=0;i<circles.length;i++)
{
circles[i].style.color="#ff0000";
}
Here is a fiddle of the pure JS version http://jsfiddle.net/vTNrR/1/
What you are doing should work. It works for me. See here:
http://jsfiddle.net/cSk3f/
However you are changing from dark grey to black, so the change is not very noticeable. So in my demo I have used green (rgb(30,80,30)) instead.

Accessing SVG file directly from Javascript code

I have this HTML code, which is invoking my javascript code. The code is for a gauge. In the javascript code, I am trying to access a SVG file, and modifying the needle (of the gauge) to display the desired value. The code is working fine. However, I do not wish to call "object id" in HTML. I want to access SVG file through javascript directly, instead of using object id in HTML. I tried using el.setAttribute('data', 'gauge.svg'); But then svg_doc isn't able to retrieve the SVG image and modify the needle. Any help would be highly appreciated.
PS : I tried my best to be as thorough in explaining the problem. However, please let me know if I am unclear somewhere.
This is Gauge.png image which is embedded in the svg code I have pasted below https://sphotos-b.xx.fbcdn.net/hphotos-snc6/179594_10150982737360698_1827200234_n.jpg
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g name="gauge" width="122px" height="127px">
<image xlink:href="gauging.png" width="122" height="127"/>
<circle id="led" cx="39" cy="76" r="5" style="fill: #999; stroke: none">
<animateColor id="ledAnimation" attributeName="fill" attributeType="css" begin="0s" dur="1s"
values="none;#f88;#f00;#f88;none;" repeatCount="0"/>
</circle>
<g id="needle" transform="rotate(0,62,62)">
<circle cx="62" cy="62" r="4" style="fill: #c00; stroke: none"/>
<rect transform="rotate(-130,62,62)" name="arrow" x="58" y="38" width="8" height="24" style="fill: #c00; stroke: none"/>
<polygon transform="rotate(-130,62,62)" points="58,39,66,39,62,30,58,39" style="fill: #c00; stroke: none"/>
</g>
<text id="value" x="51" y="98" focusable="false" editable="no" style="stroke:none; fill:#fff; font-family: monospace; font-size: 12px"></text>
</g>
</svg>
HTML+Javascript code
<head>
<title>SVG Gauge example</title>
<script>
function update1(){
var scale=100;
var value;
var value1 = 69;
var el=document.getElementById('gauge1');
if (!el) return;
/* Get SVG document from HTML element */
var svg_doc = el.contentDocument;
if (!svg_doc) return;
/* Rotate needle to display given value */
var needle_el = svg_doc.getElementById('needle');
if (!needle_el) return;
/* Calc rotation angle (0->0%, 260->100%) */
value = parseInt(value1);
scale = parseInt(scale);
if (value > scale) value = scale;
var angle = value / scale * 260;
/* On-the-fly SVG transform */
needle_el.setAttribute('transform','rotate('+angle+',62,62)');
}
document.addEventListener('load', update1, true);
</script>
</head>
<div>
<object id="gauge1" type="image/svg+xml" data="gauge.svg" width="127" height="122"/>
</div>
</html>
As robertc already mentioned, you can embed the javascript code into your SVG file:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g name="gauge" width="122px" height="127px">
<image xlink:href="gauging.png" width="122" height="127"/>
<circle id="led" cx="39" cy="76" r="5" style="fill: #999; stroke: none">
<animateColor id="ledAnimation" attributeName="fill" attributeType="css" begin="0s" dur="1s"
values="none;#f88;#f00;#f88;none;" repeatCount="0"/>
</circle>
<g id="needle" transform="rotate(0,62,62)">
<circle cx="62" cy="62" r="4" style="fill: #c00; stroke: none"/>
<rect transform="rotate(-130,62,62)" name="arrow" x="58" y="38" width="8" height="24" style="fill: #c00; stroke: none"/>
<polygon transform="rotate(-130,62,62)" points="58,39,66,39,62,30,58,39" style="fill: #c00; stroke: none"/>
</g>
<text id="value" x="51" y="98" focusable="false" editable="no" style="stroke:none; fill:#fff; font-family: monospace; font-size: 12px"></text>
</g>
<script type="text/javascript">
var scale=100;
var value;
var value1 = 69;
/* Rotate needle to display given value */
var needle_el = document.getElementById('needle');
/* Calc rotation angle (0->0%, 260->100%) */
value = parseInt(value1);
scale = parseInt(scale);
if (value > scale) value = scale;
var angle = value / scale * 260;
/* On-the-fly SVG transform */
needle_el.setAttribute('transform','rotate('+angle+',62,62)');
</script>
</svg>
I've put the code below the actual SVG contents so that the document is already loaded when the script is executed.
Then, you can view the SVG file directly e.g. in Firefox (I've tested it right now).

Categories

Resources