2013-07-22 24 views
5

D3.jsを使用して、GeoJSONファイルからパスを生成してレンダリングしています。それはうまく動作しますが、今はそのパスに沿ってオブジェクトをアニメートしたいと思います。d3.jsを使用してGeoJSONパスに沿ってオブジェクトをアニメーション化する方法は?

  1. トランジションを作成し、設定された期間
  2. をトランジションの各フレームについて、パス
  3. 移動に沿った座標を見つけるために、完全な%を使用します。私はD3と標準SVGを使用していることを行う方法を知って手順2で見つかった座標のオブジェクト

これは簡単です。しかし、私が抱えている問題は、d3.geo.path()が、標準のD3パスオブジェクト(有用なgetPointAtLength()メソッドなど)のような長さまたは位置データを返さないように見えるということです。だから私は、パスに沿って、例えば、25%の点のx、y座標を見つけることができません。

このデータを取得する方法はありますか? (または、d3.geo.path()を通常のD3パスに変換するなど、より良い方法がありますか?)

以下は、私のコードを切り捨てたものです。実際の例はここにある:http://jsfiddle.net/5m35J/4/

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 +")"; 
    } 
}); 

答えて

8

まあ、私はそれを考え出したが、私は私の解決策は、それを行うには「正しい」方法であれば、完全にはわかりません。基本的には、D3を使用して、d3.geo.path()オブジェクトによって作成された生のSVG要素を選択しました。

targetPathpathNodeへの変更、およびpathLength変数、またtransform()attrTween()機能へ:

// Draw a red circle on the map: 

group = vis.append("svg:g"); 

var targetPath = d3.selectAll('.route')[0][0], 
    pathNode = d3.select(targetPath).selectAll('path').node(), 
    pathLength = pathNode.getTotalLength(); 

circle = group.append("circle") 
    .attr({ 
    r: 10, 
    fill: '#f33', 
    transform: function() { 
     var p = pathNode.getPointAtLength(0) 
     return "translate(" + [p.x, p.y] + ")"; 
    } 
}); 

// Animate the circle: 

duration = 10000; 
circle.transition() 
    .duration(duration) 
    .ease("linear") 
    .attrTween("transform", function (d, i) { 
    return function (t) { 
     var p = pathNode.getPointAtLength(pathLength*t); 
     return "translate(" + [p.x, p.y] + ")"; 
    } 
}); 

ライブの例はここにある:http://jsfiddle.net/5m35J/6/

関連する問題