Dominik
Dominik

Reputation: 1325

Animating SVG polygons

I wrote a code to drawing polygons:

  var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  svg.setAttribute('width', '100%');
  svg.setAttribute('height', window.innerHeight);
  document.querySelector('#bg').appendChild(svg);

for(var x = 0; x < polygons.length; x++){
  var polygon = document.createElementNS(svg.namespaceURI, 'polygon');
  polygon.setAttribute('points', polygons[0 + x]);
  polygon.setAttribute('fill', polygons[0 + x][1]);
  svg.appendChild(polygon);
}

My full code with polygon points: http://codepen.io/anon/pen/WrqrbB

I would like to animate this polygons similar to this animation: http://codepen.io/zessx/pen/ZGBMXZ

How to animate my polygons?

Upvotes: 1

Views: 1324

Answers (1)

Andrew Willems
Andrew Willems

Reputation: 12448

You can

  • call an animation function to manipulate your coordinate values as desired,
  • convert them to a string, e.g. using .join(),
  • send the resulting string back to the polygon as its points attribute value, redrawing the shape (as you were already doing when you initially created your shapes), and
  • have the animation function, when it is finished, call itself again at a reasonable built-in time-delay using requestAnimationFrame.

The following snippet gives a basic idea of what can be done.

(Note that I've redefined the array polygons in my example so that it is different from what you had, but that was done for the sake of simplicity in this example.)

var svg = document.getElementsByTagName("svg")[0];
var polygons = [], numSteps = 100, stepNum = 0;
var coords = [
  [40, 20, 80, 20, 80, 60, 40, 60],
  [140, 20, 180, 20, 160, 50]
];

for (var x = 0; x < coords.length; x++) {  
  polygons[x] = document.createElementNS(svg.namespaceURI, 'polygon');
  polygons[x].setAttribute('points', coords[x].join());
  svg.appendChild(polygons[x]);
}

function anim() {
  for (var x = 0; x < coords.length; x++) {
    coords[x] = coords[x].map(function(coord) {
      return coord + 4 * (Math.random() - 0.5);
    });
    polygons[x].setAttribute('points', coords[x].join());
    stepNum += 1;
  }
  if (stepNum < numSteps) requestAnimationFrame(anim);
}

anim();
<svg></svg>

UPDATE The above snippet shows generally how to animate a polygon. In your case, however, there is a further issue. On your codepen demo, it is clear that you have hard-coded the point coordinates for each polygon separately. Thus, if you want to move one point, you're going to have to update coordinates in at least 2 if not more places, for every polygon that touches that point.

A better approach would be to create a separate array of all points and then define each polygon with respect to that array. (This is similar to how things are sometimes done in 3D graphics, e.g. WebGL.) The following code snippet demonstrates this approach.

var svg = document.getElementsByTagName("svg")[0];
var polyElems = [], numSteps = 100, stepNum = 0;
var pts = [[120,20], [160,20], [200,20], [240,20], [100,50], [140,50], [180,50], [220,50], [260,50], [120,80], [160,80], [200,80], [240,80]];
var polyPts = [[0,1,5], [1,2,6], [2,3,7], [0,4,5], [1,5,6], [2,6,7], [3,7,8], [4,5,9], [5,6,10], [6,7,11], [7,8,12], [5,9,10], [6,10,11], [7,11,12]];

for (var x = 0; x < polyPts.length; x++) {
  polyElems[x] = document.createElementNS(svg.namespaceURI, 'polygon');
  polyElems[x].setAttribute('fill', '#'+Math.floor(Math.random()*16777215).toString(16));
    // random hex color routine from http://www.paulirish.com/2009/random-hex-color-code-snippets/
  drawPolygon(x);
}

function anim() {
  pts = pts.map(function(pt) {
    return pt.map(function(coord) {
      return coord + 3 * (Math.random() - 0.5); // move each point
    });
  });
  for (var x = 0; x < polyPts.length; x++) {drawPolygon(x);}
  stepNum += 1;
  if (stepNum < numSteps) requestAnimationFrame(anim); // redo anim'n until all anim'n steps done
}

anim(); // start the animation

function drawPolygon(x) {
  var ptNums = polyPts[x];
  var currCoords = [pts[ptNums[0]], pts[ptNums[1]], pts[ptNums[2]]].join();
    // creates a string of coordinates; note that [[1,2],[3,4],[5,6]].join() yields "1,2,3,4,5,6"
  polyElems[x].setAttribute('points', currCoords);
  svg.appendChild(polyElems[x]);
}
<svg></svg>

Upvotes: 1

Related Questions