Plane rotate along path

by Viet Phan

HTML

<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="https://raw.githubusercontent.com/markmarkoh/datamaps/v0.2.10/dist/datamaps.world.min.js"></script>
<div id="container" style="position: relative; width: 700px; height: 400px;">
    <div id="spiral" style="width: 100%; height: 100%;">
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" id="spiralSVG" width = 100% height="280px" preserveAspectRatio="none" viewBox="0 0 1600 800" >        
        
        <path id="planeSVG" d="M 45.102065,97.705811 C 43.951007,97.612411 38.945827,96.864561 38.853217,96.772201 38.809017,96.728101 38.809017,96.658341 38.853217,96.617081 38.897417,96.575881 47.128741,91.537912 57.14511,85.421702 72.972389,75.757222 75.641253,74.061202 77.53027,72.467322 L 79.703865,70.633322 79.318206,70.143042 C 79.106096,69.873382 78.932557,69.454252 78.932557,69.211622 78.932557,68.251422 80.524374,67.023742 82.55786,66.415632 83.055469,66.266822 83.540368,65.953452 83.768287,65.633372 84.183716,65.049952 86.480822,63.813072 87.50616,63.620722 87.950789,63.537322 89.021597,62.761832 90.975043,61.108552 L 93.800757,58.717042 71.245872,58.717042 C 58.840687,58.717042 48.645238,58.643042 48.589308,58.552522 48.533408,58.462022 47.855999,58.329772 47.083991,58.258602 43.037809,57.885592 35.552564,56.554232 28.919017,55.027712 14.832555,51.786102 3.1621393,47.490622 0.4766545,44.559052 0.02057542,44.061182 -0.00495453,43.914962 5.7545885e-4,41.831602 0.00657545,39.738142 0.0302754,39.606352 0.49340447,39.143232 1.2638731,38.372752 4.0330275,37.570952 8.4508283,36.839182 9.1843868,36.717672 9.1945868,36.704392 9.091017,36.005792 8.3790384,31.203272 4.281117,0.29533282 4.3475469,0.22890282 4.3968468,0.17960282 6.7295921,0.32920282 9.5314261,0.56134282 L 14.625666,0.98341282 25.333854,15.929952 36.042043,30.876492 38.103399,32.662782 40.164745,34.449072 56.801731,34.435872 C 74.987585,34.421472 74.855325,34.428872...

CSS

#spiral {
  z-index: 100;
  position:absolute;
  top: 0;
  left:-5%; 
}

#spiralSVG {
    position:absolute;
   bottom: 0;
   left: 5%;
}

path {
    fill: none;
}

#planeSVG {
    fill: #e67e22;
    stroke: #666;
    opacity: 0;
}

JavaScript

var spiralData = "m 190.79664,517.11414 c 30.90934,-6.54998 -3.92944,-41.28388 -16.658,-46.55459 C 101.629,440.53436 31.208349,503.75377 19.691609,553.37288 -7.0984697,668.79611 142.50632,777.8444 277.35418,759.01888 511.6369,726.3117 1429.5677,239.15024 1550.4691,101.7018";
//define Spiral path for plane
var canvas = d3.select("#spiralSVG").append("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("x", "5%")
    .style("overflow","visible");

var path = canvas.append("path")
    .attr("d", spiralData)
    .style("fill","none")
    .style("stroke","#666")
    .style("opacity","0");
   
var plane = d3.select("#planeSVG");

function transitionThis(d,i) {
    d3.select(this).transition()
    .duration(3000)
    .delay(3000) //causes error in the animation
    .ease("exp")
    .each("start", function() { d3.select(this).style("opacity", "1"); })    
      .attrTween("transform", translateAlong(path.node()))
      .styleTween("opacity", function () {return d3.interpolate("1", "0");});
}


plane.each(transitionThis);

// Returns an attrTween for translating along the specified path element.
function translateAlong(path) {
  var l = path.getTotalLength();
    var t0 = 0;
    return function(i) {
      return function(t) {
        // Happens every once in a while
        if(t == t0) {
            // Move t0 "back in time" a bit
            t0 -= .00001;
        }
        var p0 = path.getPointAtLength(t0 * l);//previous point
        var p = path.getPointAtLength(t * l);////current point
        var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//angle for tangent
        t0 = t;
      return "translate(" + p.x + "," + p.y +  ")scale(" + (0.2+t*4) + ")rotate(" + angle +"15"+")";
    };
  };
}