| 
          <!DOCTYPE html> | 
        
        
           | 
          <svg width="960" height="500"> | 
        
        
           | 
            <path transform="translate(180,150)scale(2,2)" fill="none" stroke="black" stroke-width="1.5"></path> | 
        
        
           | 
          </svg> | 
        
        
           | 
          <script src="https://d3js.org/d3.v4.min.js"></script> | 
        
        
           | 
          <script> | 
        
        
           | 
          
 | 
        
        
           | 
          var d0 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100", | 
        
        
           | 
              d1 = "M0,0c100,0 0,100 100,100c100,0 0,-100 100,-100c100,0 0,100 100,100"; | 
        
        
           | 
          
 | 
        
        
           | 
          d3.select("path") | 
        
        
           | 
              .attr("d", d0) | 
        
        
           | 
            .transition() | 
        
        
           | 
              .duration(2000) | 
        
        
           | 
              .on("start", function repeat() { | 
        
        
           | 
                d3.active(this) | 
        
        
           | 
                    .attrTween("d", pathTween(d1, 4)) | 
        
        
           | 
                  .transition() | 
        
        
           | 
                    .attrTween("d", pathTween(d0, 4)) | 
        
        
           | 
                  .transition() | 
        
        
           | 
                    .on("start", repeat); | 
        
        
           | 
              }); | 
        
        
           | 
          
 | 
        
        
           | 
          function pathTween(d1, precision) { | 
        
        
           | 
            return function() { | 
        
        
           | 
              var path0 = this, | 
        
        
           | 
                  path1 = path0.cloneNode(), | 
        
        
           | 
                  n0 = path0.getTotalLength(), | 
        
        
           | 
                  n1 = (path1.setAttribute("d", d1), path1).getTotalLength(); | 
        
        
           | 
          
 | 
        
        
           | 
              // Uniform sampling of distance based on specified precision. | 
        
        
           | 
              var distances = [0], i = 0, dt = precision / Math.max(n0, n1); | 
        
        
           | 
              while ((i += dt) < 1) distances.push(i); | 
        
        
           | 
              distances.push(1); | 
        
        
           | 
          
 | 
        
        
           | 
              // Compute point-interpolators at each distance. | 
        
        
           | 
              var points = distances.map(function(t) { | 
        
        
           | 
                var p0 = path0.getPointAtLength(t * n0), | 
        
        
           | 
                    p1 = path1.getPointAtLength(t * n1); | 
        
        
           | 
                return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]); | 
        
        
           | 
              }); | 
        
        
           | 
          
 | 
        
        
           | 
              return function(t) { | 
        
        
           | 
                return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1; | 
        
        
           | 
              }; | 
        
        
           | 
            }; | 
        
        
           | 
          } | 
        
        
           | 
          
 | 
        
        
           | 
          </script> |