title: How to animate an object along a GeoJSON path using d3.js?
body: <p>I'm using D3.js to generate and render a path from a GeoJSON file. That works fine, but now I'd like to animate an object along that path. I know how to do that using D3 and standard SVG:</p>
  
  <ol>
  <li>Create a transition and set its duration</li>
  <li>For each frame of the transition, use the % complete to find the coordinates along the path</li>
  <li>Move the object to the coordinates found in step 2</li>
  </ol>
  
  <p>That's simple. But the problem I'm having is that d3.geo.path() doesn't seem to return any length or position data like a standard D3 path object (such as the helpful getPointAtLength() method). So I'm unable to find the x,y coordinates of a point at, say, 25% along the path.</p>
  
  <p>Is there a way to obtain this data? (Or is there a better way, such as converting the d3.geo.path() to a regular D3 path?)</p>
  
  <p>Below is a truncated version of my code; a live example is here: <a href="http://jsfiddle.net/5m35J/4/">http://jsfiddle.net/5m35J/4/</a></p>
  
  <pre><code>json = {
      ... // snipped for brevity
  };
  
  // Draw a GeoJSON line on the map:
  
  map = $('#map');
  xy = d3.geo.mercator().scale(480000).translate([630700, 401100]);
  path = d3.geo.path().projection(xy);
  
  vis = d3.select("#map")
      .append("svg:svg")
      .attr("width", 960)
      .attr("height", 600);
  
  vis.append("svg:g")
      .attr("class", "route")
      .selectAll("path")
      .data(json.features)
      .enter()
      .append("svg:path")
      .attr("d", path)
      .attr("fill-opacity", 0.5)
      .attr("fill", "#fff")
      .attr("stroke", "#333");
  
  // Draw a red circle on the map:
  
  //len = 100; // how do I find the length of the path?
  origin_x = 100;
  origin_y = 100;
  
  group = vis.append("svg:g");
  
  circle = group.append("circle")
      .attr({
      r: 10,
      fill: '#f33',
      transform: function () {
          //var p = path.getPointAtLength(0)
          //return "translate(" + [p.x, p.y] + ")";
          return "translate("+ origin_x +","+ origin_y +")";
      }
  });
  
  // Animate the circle:
  
  duration = 5000;
  circle.transition()
      .duration(duration)
      .ease("linear")
      .attrTween("transform", function (d, i) {
      return function (t) {
          //var p = path.node().getPointAtLength(len*t) // d3.geo.path() doesn't provide a getPointAtLength() method!
          //return "translate("+[p.x,p.y]+")"
          var current_x = origin_x + origin_x * t;
          var current_y = origin_y + origin_y * t;            
          return "translate("+ current_x +","+ current_y +")";
      }
  });
  </code></pre>