Animate SVG Elements

This example dynamically builds and renders an array of rects, circles, plus ellipses. It uses React.createClass to build an object (<SVGElems />) holding all elements. After the element is rendered in the DOM, onclick events are included on the ellipse as an attribute value. Click on an ellipse to start its rotation animation.


React Root SVG Source:

Babel Script (code):
  1.  
  2.     var randColor = function() //---create random colors---
  3.     {
  4.         return '#'+Math.floor(Math.random()*16777215).toString(16);
  5.     }
  6.  
  7.     //---create a React svg root element---
  8.     //-- svgRoot=ReactDOM.render(<svg id="mySVG" overflow="visible" xmlns="http://www.w3.org/2000/svg" />, svgDiv);
  9.  
  10.     //---create a React rect, circle, and ellipse SVG template element with properties (i.e. svg typical attributes)---
  11.     var rect = (props) => React.createElement("rect",{x:props.x, y:props.y, width:props.width, height:props.height, fill:props.fill}) //---ES6 arrow function---
  12.     var circle = (props) => React.createElement("circle",{cx:props.cx, cy:props.cy, r:props.r,  fill:props.fill}) //---ES6 arrow function---
  13.     var ellipse = (props) => React.createElement("ellipse",{cx:props.cx, cy:props.cy, rx:props.rx, ry:props.ry, fill:props.fill}) //---ES6 arrow function---
  14.  
  15.     //---dynamically build an array of elements---
  16.     var svgElems=[]
  17.     for(var k=0;k<6;k++)  //---provide a key value for each element---
  18.     {
  19.         svgElems.push(<rect className="rect-svg" key={"rect"+k} x={100*k} y={0} width={100} height={100} fill={randColor()} />)
  20.         svgElems.push(<circle   className="circle-svg" key={"circle"+k} cx={125*k} cy={180} r={50}  fill={randColor()} />)
  21.         svgElems.push(<ellipse  className="ellipse-svg" key={"ellipse"+k} cx={100*k} cy={280} rx={50} ry={30} fill={randColor()} />)
  22.     }
  23.  
  24.     //---object holding all elements---
  25.     var SVGElems = React.createClass({
  26.         render: function()
  27.         {
  28.            return  <g>{ svgElems }</g>  //---encapsulate in <g> element---
  29.         }
  30.     });
  31.  
  32.     ReactDOM.render(<SVGElems />, mySVG);
  33.  
  34.      //----add events---
  35.  
  36.     var elems=mySVG.firstChild.childNodes
  37.      for(var k=0;k<elems.length;k++)
  38.      {
  39.         var elem=elems.item(k)
  40.         if(elem.nodeName=="ellipse")
  41.             elem.setAttribute("onclick","rotateMe(evt)")
  42.      }
  43.  
  44.     //---local function to show svg source on page: React Root SVG Source---
  45.     showSourceSVG()
  46. //===================ANIMATION========================
  47.   //---cross-browser animate core function
  48.  
  49. //----Animate Object---
  50. var AnimateJS=function(options){
  51.     this.options=options
  52. var start = new Date
  53. var iT = setInterval(
  54. function(){
  55. var timePassed = new Date - start
  56. var progress = timePassed / options.duration
  57. if (progress > 1) progress = 1
  58. this.progress=progress
  59. var delta = options.delta(progress)
  60. options.output(delta)
  61. if (progress == 1)clearInterval(iT);
  62. },options.delay)
  63. }
  64.  
  65. function rotateMe(evt)
  66. {
  67.     //----add animate rotate from center---
  68.     var elem=evt.target
  69.     var bb=elem.getBBox()
  70.     var bbx=bb.x
  71.     var bby=bb.y
  72.     var bbw=bb.width
  73.     var bbh=bb.height
  74.     var cx=bbx+.5*bbw
  75.     var cy=bby+.5*bbh
  76.  
  77. var range=360 //---degrees rotation---
  78. var FPS=80   //---frames per second---
  79. var duration=3000 //---ms, 3 seconds---
  80. var delta=function linear(p){return p}//---linear---
  81. //----core animation function---
  82.     new AnimateJS(
  83.     {
  84.         delay: 1000/FPS,
  85.         duration: duration,
  86.         delta: delta, //---linear---
  87.         output: function(delta)
  88.         {
  89.             //---this application's output---
  90.             elem.setAttribute("transform","rotate("+(range*delta)+" "+cx+" "+cy+")")
  91.             if(progress==1)
  92.                 rotateMe(evt) //---run again---
  93.         }
  94.     })
  95. }
  96.     window["rotateMe"]=rotateMe