如何在 D3.js 中为地图上的路径设置动画?
How do I animate points down a path on a map in D3.js?
我有一张地图,我已经在地图上成功绘制了一组 LineStrings。
但我真正想做的是沿着每个 LineString 定义的路线制作动画圆圈。
我看过几个例子 (http://bl.ocks.org/zross/6a31f4ef9e778d94c204, http://www.tnoda.com/blog/2014-04-02),但我不确定我实际上是如何在起点放置圆圈,然后让它们沿着路径移动的。
这是我绘制路径的地图(以红色显示)
这是我的代码 - hydro_map
是一个转换为 GeoJSON FeatureCollection 的 shapefile,stations
是一个 GeoJSON 特征集合(只是点),links
是一个 LineString 数组。我想创建圆圈,并将它们沿着我创建的每条路径过渡。
var width = 900, height = 800;
var projection = d3.geo.mercator().center([-87.55,41.919]).scale(170000);
var path = d3.geo.path().projection(projection);
var svg = d3.select("#output").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom()
.on("zoom", redraw))
;
var g = svg.append("g");
var terrainGroup = g.append("g");
var arcGroup = g.append("g");
var stationGroup = g.append("g");
var tripGroup = g.append("g");
//draw terrain
terrainGroup.append("path")
.datum({type: "FeatureCollection", features: hydro_map.features})
.attr("d", path)
.style("fill", "#3db7e4");
//plot stations
stationGroup.selectAll("circle")
.data(stations.features).enter()
.append("path")
.attr("d", path.pointRadius(0.5));
//draw paths between stations
var pathArcs = arcGroup.selectAll(".arc")
.data(links);
pathArcs.enter()
.append("path")
.attr({"class": "arc"})
.style({fill: "none",})
.attr({d: path})
.style({
stroke: "red",
"stroke-width": "0.5px"
});
如果路径是直线,可以如下图所示沿路径移动一个圆圈。
var svg = d3.select("body")
.append("svg")
.attr("width",500)
.attr("height",500);
var path = svg.append("path")
.attr("d","M 100 350 l 150 -300")
.attr("fill","none")
.attr("stroke","black");
var circle = svg.append("circle")
.attr("r",5)
.attr("cx",100)
.attr("cy",350);
var pathEl = path.node();
for(var i=0;i<pathEl.getTotalLength();i++){
var pt = pathEl.getPointAtLength(i);
circle.transition()
.duration(3500)
.attr("cx",pt.x)
.attr("cy",pt.y);
}
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
如果路径是曲线,您可以使用 attrTween 来完成任务。
var svg = d3.select("body")
.append("svg")
.attr("width",500)
.attr("height",500);
var path = svg.append("path")
.attr("d","M 100 350 q 150 -300 300 0")
.attr("fill","none")
.attr("stroke","black").call(transition);
var startPoint = pathStartPoint(path);
var marker = svg.append("circle");
marker.attr("r", 7)
.attr("id", "marker")
.attr("transform", "translate(" + startPoint + ")");
function pathStartPoint(path) {
var d = path.attr("d"),
dsplitted = d.split(" ");
return dsplitted[1];
}
function transition(path) {
path.transition()
.duration(3500)
.attrTween("stroke", tweenDash)
//.each("end", function() { d3.select(this).call(transition); }); infinite loop
}
function tweenDash() {
var l = path.node().getTotalLength();
return function(t) {
var marker = d3.select("#marker");
var p = path.node().getPointAtLength(t * l);
marker.attr("transform", "translate(" + p.x + "," + p.y + ")");
return "black";
}
}
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
我有一张地图,我已经在地图上成功绘制了一组 LineStrings。
但我真正想做的是沿着每个 LineString 定义的路线制作动画圆圈。
我看过几个例子 (http://bl.ocks.org/zross/6a31f4ef9e778d94c204, http://www.tnoda.com/blog/2014-04-02),但我不确定我实际上是如何在起点放置圆圈,然后让它们沿着路径移动的。
这是我绘制路径的地图(以红色显示)
hydro_map
是一个转换为 GeoJSON FeatureCollection 的 shapefile,stations
是一个 GeoJSON 特征集合(只是点),links
是一个 LineString 数组。我想创建圆圈,并将它们沿着我创建的每条路径过渡。
var width = 900, height = 800;
var projection = d3.geo.mercator().center([-87.55,41.919]).scale(170000);
var path = d3.geo.path().projection(projection);
var svg = d3.select("#output").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom()
.on("zoom", redraw))
;
var g = svg.append("g");
var terrainGroup = g.append("g");
var arcGroup = g.append("g");
var stationGroup = g.append("g");
var tripGroup = g.append("g");
//draw terrain
terrainGroup.append("path")
.datum({type: "FeatureCollection", features: hydro_map.features})
.attr("d", path)
.style("fill", "#3db7e4");
//plot stations
stationGroup.selectAll("circle")
.data(stations.features).enter()
.append("path")
.attr("d", path.pointRadius(0.5));
//draw paths between stations
var pathArcs = arcGroup.selectAll(".arc")
.data(links);
pathArcs.enter()
.append("path")
.attr({"class": "arc"})
.style({fill: "none",})
.attr({d: path})
.style({
stroke: "red",
"stroke-width": "0.5px"
});
如果路径是直线,可以如下图所示沿路径移动一个圆圈。
var svg = d3.select("body")
.append("svg")
.attr("width",500)
.attr("height",500);
var path = svg.append("path")
.attr("d","M 100 350 l 150 -300")
.attr("fill","none")
.attr("stroke","black");
var circle = svg.append("circle")
.attr("r",5)
.attr("cx",100)
.attr("cy",350);
var pathEl = path.node();
for(var i=0;i<pathEl.getTotalLength();i++){
var pt = pathEl.getPointAtLength(i);
circle.transition()
.duration(3500)
.attr("cx",pt.x)
.attr("cy",pt.y);
}
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
如果路径是曲线,您可以使用 attrTween 来完成任务。
var svg = d3.select("body")
.append("svg")
.attr("width",500)
.attr("height",500);
var path = svg.append("path")
.attr("d","M 100 350 q 150 -300 300 0")
.attr("fill","none")
.attr("stroke","black").call(transition);
var startPoint = pathStartPoint(path);
var marker = svg.append("circle");
marker.attr("r", 7)
.attr("id", "marker")
.attr("transform", "translate(" + startPoint + ")");
function pathStartPoint(path) {
var d = path.attr("d"),
dsplitted = d.split(" ");
return dsplitted[1];
}
function transition(path) {
path.transition()
.duration(3500)
.attrTween("stroke", tweenDash)
//.each("end", function() { d3.select(this).call(transition); }); infinite loop
}
function tweenDash() {
var l = path.node().getTotalLength();
return function(t) {
var marker = d3.select("#marker");
var p = path.node().getPointAtLength(t * l);
marker.attr("transform", "translate(" + p.x + "," + p.y + ")");
return "black";
}
}
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>