2

I want to morph/animate svg path data WITHOUT SMIL or libraries (jquery, Snap.svg, Velocity.js etc.), just pure javascript (and optionally with css if possible). I want to do this because Chrome deprecated SMIL and they suggest to animate with css or "Web animations" -what do they mean with web animations??-. For example I want to morph path with id "rect1" to path with id "rect2" in code below:

<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8">
  <title>morph/animate svg path data WITHOUT SMIL or libraries (jquery, Snap.svg, Velocity.js etc.), just pure javascript</title>
</head>
<body>

<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  version="1.1"
  width="500px" height="500px"
  viewBox="0 0 500 500"
  >
<g id="layer1">
  <path id="rect1" d="m25 7.3 61 12-6 57-71 6z" stroke="#f00" stroke-miterlimit="10" stroke-width="2" fill="none"/>
 </g>
 <g id="layer2">
  <path id="rect2" d="m9.3 34 59-27 26 41-54 42z" stroke="#f00" stroke-miterlimit="10" stroke-width="2" fill="none"/>
 </g>
</svg>

<script>

 // code for animating/morphing path with id "rect1" to path with id "rect 2"

</script>

</body>

</html>
Limon Monte
  • 52,539
  • 45
  • 182
  • 213
Joey Q
  • 21
  • 4
  • Possible duplicate of [How to animate path shape without using SMIL?](http://stackoverflow.com/questions/33420323/how-to-animate-path-shape-without-using-smil) – Kaiido Nov 20 '15 at 05:20
  • and [to quote](http://stackoverflow.com/questions/33420323/how-to-animate-path-shape-without-using-smil/33428336#comment-54649080) Robert Longson on this dupe question, : "SMIL has great browser support. Via https://leunen.me/fakesmile it works on pretty much anything that supports SVG and javascript no matter whether Chrome deprecates it or not. Chrome actually has a different non-native SMIL plugin: https://github.com/ericwilligers/svg-animation available so there's plenty of reasons to stick with SMIL" – Kaiido Nov 20 '15 at 05:23

1 Answers1

2

To animate the path data using just JavaScript, I would suggest caching the original path data for both paths. Then use a timer to step through the animation process. At each step, calculate current path data that smoothly moves from start path data to end path data.

The following code waits 1 second and then runs a 2 second animation...

<script>

(function() {

    var path1;
    var path2;
    var startPoints;
    var endPoints;
    var currentStep = 0;
    var maximumSteps = 100;
    var timeBeforeFirstStep = 1000;
    var timeBetweenSteps = 20;

    function animatePath() {
        if (currentStep < maximumSteps) {
            currentStep = currentStep + 1;
            for (var i = 0; i < path1.pathSegList.numberOfItems; i++) {
                var item = path1.pathSegList.getItem(i);
                if (item.pathSegType === SVGPathSeg.PATHSEG_MOVETO_REL || item.pathSegType === SVGPathSeg.PATHSEG_LINETO_REL) {
                    if (startPoints[i] && endPoints[i]) {
                        item.x = startPoints[i].x + (endPoints[i].x - startPoints[i].x) * (currentStep / maximumSteps);
                        item.y = startPoints[i].y + (endPoints[i].y - startPoints[i].y) * (currentStep / maximumSteps);
                    }
                }
            }
            setTimeout(animatePath, timeBetweenSteps);
        }
    }

    function window_load() {
        path1 = document.getElementById("rect1");
        path2 = document.getElementById("rect2");
        startPoints = [];
        for (var i = 0; i < path1.pathSegList.numberOfItems; i++) {
            var item = path1.pathSegList.getItem(i);
            if (item.pathSegType === SVGPathSeg.PATHSEG_MOVETO_REL || item.pathSegType === SVGPathSeg.PATHSEG_LINETO_REL) {
                startPoints.push({"x": item.x, "y": item.y});
            }
            else {
                startPoints.push(null);
            }
        }
        endPoints = [];
        for (var i = 0; i < path2.pathSegList.numberOfItems; i++) {
            var item = path2.pathSegList.getItem(i);
            if (item.pathSegType === SVGPathSeg.PATHSEG_MOVETO_REL || item.pathSegType === SVGPathSeg.PATHSEG_LINETO_REL) {
                endPoints.push({"x": item.x, "y": item.y});
            }
            else {
                endPoints.push(null);
            }
        }
        setTimeout(animatePath, timeBeforeFirstStep);
    }

    window.addEventListener("load", window_load);

}());

</script>
Bobby Orndorff
  • 3,265
  • 1
  • 9
  • 7