使用 d3 嵌套组沿多条路径设置 D3 动画标记
D3 animate marker along multiple paths with d3 nest group
我正在开发一个项目,该项目有多个路径代表一张地图的路线。我正在关注
this d3 nest example 按键对我的数据进行分组以创建多条路线。
我想为圆形元素设置动画以沿每个单独的路线路径过渡。我可以看到我的问题与 this example and this solution 非常相似,但我不明白如何将解决方案应用于我的示例。
我不明白如何将我的组的索引/键放入 createPathTween 函数中。因此,我的第一个组中只有一个圆形元素,而不是沿每条路线/路径过渡的圆形元素。有人可以帮我弄清楚如何在每条路线路径上放置过渡圆元素吗?
这是我的 d3 代码
<html>
<head>
<title>Hello</title>
<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<style>
}
.placeVisited{
fill:#999;
}
.journey{
fill: none;
}
</style>
</head>
<body>
<script>
var width = 1200;
var height = 550;
var svg = d3.select( "body" )
.append( "svg" )
.attr( "width", width )
.attr( "height", height );
var g = svg.append( "g" );
var projection = d3.geoMercator()
.center([55, 12])
.scale(220)
.translate([width/2,height/2])
var geoPath = d3.geoPath()
.projection(projection);
var voyageLine = d3.line()
.x(function(d) { return projection([d.lon,d.lat])[0] ; })
.y(function(d) { return projection([d.lon,d.lat])[1]; })
.curve(d3.curveBasis);
var parseDate = d3.timeParse("%d %B %Y");
var parseYear = d3.timeParse("%Y");
var color = d3.scaleOrdinal(d3.schemeCategory10);
d3.queue()
.defer(d3.csv, "multipleVoyages2.csv")
.await(ready);
function ready (error, data){
data.forEach(function(d) {
d.year = parseYear(d.year);
d.lon= +d.lon;
d.lat = +d.lat;
});
var dataNest = d3.nest()
.key(function(d){return d.VoyageID;})
.entries(data);
var journey = g.selectAll(".journey")
.data(dataNest)
.enter()
.append("path")
.attr("class", "journey")
.style("stroke", function(d) {
return d.color = color(d.key); })
.attr("d", function(d){
return voyageLine(d.values);
})
.attr("stroke-dasharray", function() {
var totalLength = this.getTotalLength();
return totalLength + " " + totalLength;
})
.attr("stroke-dashoffset", function() {
var totalLength = this.getTotalLength();
return totalLength;
})
.transition()
.ease(d3.easeLinear)
.duration(5000)
.attr("stroke-dashoffset", 0);
var marker = g.append("circle")
.attr("r", 7)
.style("fill", "pink")
.attr("transform", "translate(-100,-100)")
.transition()
.ease(d3.easeLinear)
.duration(5000)
.attrTween("transform", createPathTween);
var placeGroups = g.selectAll(".placeVisited")
.data(dataNest)
.enter()
.append( "g" )
.attr("class","placeVisited");
var placeVisited = placeGroups.selectAll("placeVisited")
.data(function(d){
return d.values;
})
.enter()
.append("circle")
.attr("fill", function(d){
return d.color = color(d.VoyageID);
})
.attr("cx", function(d, i) {
return projection([d.lon, d.lat])[0];
})
.attr("cy", function(d, i) {
return projection([d.lon, d.lat])[1];
})
.attr("r", 5)
//transitioning marker
//from this example -- http://fiddle.jshell.net/RnNsE/2/
function createPathTween(d, i, a) {
// var path = this.parentNode.getElementsByTagName("journey")[0];
var path = this.parentNode.getElementsByClassName("journey")[i]; //don't understand how to get the index for each group
var l = path.getTotalLength();
console.log("path");
console.log(path);
return function(t) {
var p = path.getPointAtLength(t * l);
return "translate(" + p.x + "," + p.y + ")";
};
}
}
</script>
</body>
</html>
和我的 csv:
VoyageID,VoyageType,voyageName,ObjectID,arrivalDateTxt,year,ObjectNumber,placeName,lon,lat,url,,,
1,Pleasure cruise,Postcards home,170207,14 January 1906,1906,ANMS1113[006],Port Pirie,138.16,-33.183,http://collections.anmm.gov.au/en/objects/details/170207/,,,
1,Pleasure cruise,Postcards home,170205,1 May 1907,1907,ANMS1113[004],Mount Lofty Ranges,138.6,-34.933,http://collections.anmm.gov.au/en/objects/details/170205/,,,
1,Pleasure cruise,Postcards home,170216,26 October 1907,1907,ANMS1113[015],Brisbane,153,-27.5,http://collections.anmm.gov.au/en/objects/details/170216/,,,
1,Pleasure cruise,Postcards home,170200,4 November 1907,1907,ANMS1113[001],Adelaide,138.6,-34.933,http://collections.anmm.gov.au/en/objects/details/170200/,,,
1,Pleasure cruise,Postcards home,170213,26 November 1907,1907,ANMS1113[012],Fremantle,115.766,-32.5,http://collections.anmm.gov.au/en/objects/details/170213/,,,
1,Pleasure cruise,Postcards home,170209,3 December 1907,1907,ANMS1113[008],Adelaide,138.6,-34.933,http://collections.anmm.gov.au/en/objects/details/170209/,,,
1,Pleasure cruise,Postcards home,170212,10 December 1907,1907,ANMS1113[011],Melbourne,144.966,-37.75,http://collections.anmm.gov.au/en/objects/details/170212/,,,
1,Pleasure cruise,Postcards home,170217,20 December 1907,1907,ANMS1113[016],Sydney,151.166,-33.916,http://collections.anmm.gov.au/en/objects/details/170217/,,,
1,Pleasure cruise,Postcards home,170203,26 December 1907,1907,ANMS1113[002],Brisbane,153,-27.5,http://collections.anmm.gov.au/en/objects/details/170203/,,,
1,Pleasure cruise,Postcards home,170215,26 December 1907,1907,ANMS1113[014],Brisbane,153,-27.5,http://collections.anmm.gov.au/en/objects/details/170215/,,,
1,Pleasure cruise,Postcards home,170211,8 January 1908,1908,ANMS1113[010],Port Pirie,138.16,-33.183,http://collections.anmm.gov.au/en/objects/details/170211/,,,
1,Pleasure cruise,Postcards home,170208,14 January 1908,1908,ANMS1113[007],Port Pirie,138.16,-33.183,http://collections.anmm.gov.au/en/objects/details/170208/,,,
2,Kayak adventure,Oskar,1,1 March 1961,1961,,London,-0.127758,51.507351,,,,
2,Kayak adventure,Oskar,2,2 April 1961,1961,,Paris,2.352222,48.856614,,,,
2,Kayak adventure,Oskar,3,3 June 1961,1961,,Lyon,4.835659,45.764043,,,,
2,Kayak adventure,Oskar,4,28 June 1961,1961,,Calais,1.858686,50.95129,,,,
2,Kayak adventure,Oskar,5,10 July 1961,1961,,Frankfurt,8.682127,8.682127,,,,
2,Kayak adventure,Oskar,6,19 December 1961,1961,,Berlin,13.404954,52.520007,,,,
2,Kayak adventure,Oskar,7,25 January 1962,1962,,Amsterdam,4.895168,52.370216,,,,
2,Kayak adventure,Oskar,8,30 June 1962,1962,,rome,12.496366,41.902783,,,,
2,Kayak adventure,Oskar,9,24 November 1962,1962,,Milan,9.189982,45.464204,,,,
2,Kayak adventure,Oskar,10,19 January 1963,1963,,Turin,7.686856,45.070312,,,,
2,Kayak adventure,Oskar,11,27 January 1963,1963,,Florence,11.255814,43.76956,,,,
2,Kayak adventure,Oskar,12,30 April 1963,1963,,Vienna,16.373819,48.208174,,,,
3,Whaling ,Barque Terror,123,12 March 1845,1845,,Island 1,155.370833,-24.916667,,,,
3,Whaling ,Barque Terror,777,15 March 1845,1845,,Island 2,162.81738,-20.6739,,,,
3,Whaling ,Barque Terror,546,22 March 1845,1845,,Place in ocean 3,160.26464,-11.66325,,,,
3,Whaling ,Barque Terror,888,23 July 1845,1845,,Place in ocean 4,161.94638,-10.18388,,,,
3,Whaling ,Barque Terror,543,19 December 1845,1845,,Place in ocean 5,160.90712,-8.94461,,,,
3,Whaling ,Barque Terror,2134,22 January 1846,1846,,Place in ocean 6,158.74232,-9.01835,,,,
3,Whaling ,Barque Terror,6666,30 January 1846,1846,,Back home,157.26555,-8.19361,,,,
你可以让 paths
在你的 path
和你的 marker
完成使用 delay
函数后进行动画处理,如下所示:
.duration(5000)
.delay(function(d, i) { // 'i' will give you the index
return i * 5000; // Multiply by 5000 so that it starts after the previous one has finished.
});
并为每个 path
获得一个 circle
标记,您需要像这样创建相同数量的 circles
:
var marker = g.selectAll('circle')
.data(dataNest).enter()
.append("circle")...
也使用d3.curveCatmullRom
以获得更好的path
。
这是一个plunker
我想为圆形元素设置动画以沿每个单独的路线路径过渡。我可以看到我的问题与 this example and this solution 非常相似,但我不明白如何将解决方案应用于我的示例。
我不明白如何将我的组的索引/键放入 createPathTween 函数中。因此,我的第一个组中只有一个圆形元素,而不是沿每条路线/路径过渡的圆形元素。有人可以帮我弄清楚如何在每条路线路径上放置过渡圆元素吗?
这是我的 d3 代码
<html>
<head>
<title>Hello</title>
<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<style>
}
.placeVisited{
fill:#999;
}
.journey{
fill: none;
}
</style>
</head>
<body>
<script>
var width = 1200;
var height = 550;
var svg = d3.select( "body" )
.append( "svg" )
.attr( "width", width )
.attr( "height", height );
var g = svg.append( "g" );
var projection = d3.geoMercator()
.center([55, 12])
.scale(220)
.translate([width/2,height/2])
var geoPath = d3.geoPath()
.projection(projection);
var voyageLine = d3.line()
.x(function(d) { return projection([d.lon,d.lat])[0] ; })
.y(function(d) { return projection([d.lon,d.lat])[1]; })
.curve(d3.curveBasis);
var parseDate = d3.timeParse("%d %B %Y");
var parseYear = d3.timeParse("%Y");
var color = d3.scaleOrdinal(d3.schemeCategory10);
d3.queue()
.defer(d3.csv, "multipleVoyages2.csv")
.await(ready);
function ready (error, data){
data.forEach(function(d) {
d.year = parseYear(d.year);
d.lon= +d.lon;
d.lat = +d.lat;
});
var dataNest = d3.nest()
.key(function(d){return d.VoyageID;})
.entries(data);
var journey = g.selectAll(".journey")
.data(dataNest)
.enter()
.append("path")
.attr("class", "journey")
.style("stroke", function(d) {
return d.color = color(d.key); })
.attr("d", function(d){
return voyageLine(d.values);
})
.attr("stroke-dasharray", function() {
var totalLength = this.getTotalLength();
return totalLength + " " + totalLength;
})
.attr("stroke-dashoffset", function() {
var totalLength = this.getTotalLength();
return totalLength;
})
.transition()
.ease(d3.easeLinear)
.duration(5000)
.attr("stroke-dashoffset", 0);
var marker = g.append("circle")
.attr("r", 7)
.style("fill", "pink")
.attr("transform", "translate(-100,-100)")
.transition()
.ease(d3.easeLinear)
.duration(5000)
.attrTween("transform", createPathTween);
var placeGroups = g.selectAll(".placeVisited")
.data(dataNest)
.enter()
.append( "g" )
.attr("class","placeVisited");
var placeVisited = placeGroups.selectAll("placeVisited")
.data(function(d){
return d.values;
})
.enter()
.append("circle")
.attr("fill", function(d){
return d.color = color(d.VoyageID);
})
.attr("cx", function(d, i) {
return projection([d.lon, d.lat])[0];
})
.attr("cy", function(d, i) {
return projection([d.lon, d.lat])[1];
})
.attr("r", 5)
//transitioning marker
//from this example -- http://fiddle.jshell.net/RnNsE/2/
function createPathTween(d, i, a) {
// var path = this.parentNode.getElementsByTagName("journey")[0];
var path = this.parentNode.getElementsByClassName("journey")[i]; //don't understand how to get the index for each group
var l = path.getTotalLength();
console.log("path");
console.log(path);
return function(t) {
var p = path.getPointAtLength(t * l);
return "translate(" + p.x + "," + p.y + ")";
};
}
}
</script>
</body>
</html>
和我的 csv:
VoyageID,VoyageType,voyageName,ObjectID,arrivalDateTxt,year,ObjectNumber,placeName,lon,lat,url,,,
1,Pleasure cruise,Postcards home,170207,14 January 1906,1906,ANMS1113[006],Port Pirie,138.16,-33.183,http://collections.anmm.gov.au/en/objects/details/170207/,,,
1,Pleasure cruise,Postcards home,170205,1 May 1907,1907,ANMS1113[004],Mount Lofty Ranges,138.6,-34.933,http://collections.anmm.gov.au/en/objects/details/170205/,,,
1,Pleasure cruise,Postcards home,170216,26 October 1907,1907,ANMS1113[015],Brisbane,153,-27.5,http://collections.anmm.gov.au/en/objects/details/170216/,,,
1,Pleasure cruise,Postcards home,170200,4 November 1907,1907,ANMS1113[001],Adelaide,138.6,-34.933,http://collections.anmm.gov.au/en/objects/details/170200/,,,
1,Pleasure cruise,Postcards home,170213,26 November 1907,1907,ANMS1113[012],Fremantle,115.766,-32.5,http://collections.anmm.gov.au/en/objects/details/170213/,,,
1,Pleasure cruise,Postcards home,170209,3 December 1907,1907,ANMS1113[008],Adelaide,138.6,-34.933,http://collections.anmm.gov.au/en/objects/details/170209/,,,
1,Pleasure cruise,Postcards home,170212,10 December 1907,1907,ANMS1113[011],Melbourne,144.966,-37.75,http://collections.anmm.gov.au/en/objects/details/170212/,,,
1,Pleasure cruise,Postcards home,170217,20 December 1907,1907,ANMS1113[016],Sydney,151.166,-33.916,http://collections.anmm.gov.au/en/objects/details/170217/,,,
1,Pleasure cruise,Postcards home,170203,26 December 1907,1907,ANMS1113[002],Brisbane,153,-27.5,http://collections.anmm.gov.au/en/objects/details/170203/,,,
1,Pleasure cruise,Postcards home,170215,26 December 1907,1907,ANMS1113[014],Brisbane,153,-27.5,http://collections.anmm.gov.au/en/objects/details/170215/,,,
1,Pleasure cruise,Postcards home,170211,8 January 1908,1908,ANMS1113[010],Port Pirie,138.16,-33.183,http://collections.anmm.gov.au/en/objects/details/170211/,,,
1,Pleasure cruise,Postcards home,170208,14 January 1908,1908,ANMS1113[007],Port Pirie,138.16,-33.183,http://collections.anmm.gov.au/en/objects/details/170208/,,,
2,Kayak adventure,Oskar,1,1 March 1961,1961,,London,-0.127758,51.507351,,,,
2,Kayak adventure,Oskar,2,2 April 1961,1961,,Paris,2.352222,48.856614,,,,
2,Kayak adventure,Oskar,3,3 June 1961,1961,,Lyon,4.835659,45.764043,,,,
2,Kayak adventure,Oskar,4,28 June 1961,1961,,Calais,1.858686,50.95129,,,,
2,Kayak adventure,Oskar,5,10 July 1961,1961,,Frankfurt,8.682127,8.682127,,,,
2,Kayak adventure,Oskar,6,19 December 1961,1961,,Berlin,13.404954,52.520007,,,,
2,Kayak adventure,Oskar,7,25 January 1962,1962,,Amsterdam,4.895168,52.370216,,,,
2,Kayak adventure,Oskar,8,30 June 1962,1962,,rome,12.496366,41.902783,,,,
2,Kayak adventure,Oskar,9,24 November 1962,1962,,Milan,9.189982,45.464204,,,,
2,Kayak adventure,Oskar,10,19 January 1963,1963,,Turin,7.686856,45.070312,,,,
2,Kayak adventure,Oskar,11,27 January 1963,1963,,Florence,11.255814,43.76956,,,,
2,Kayak adventure,Oskar,12,30 April 1963,1963,,Vienna,16.373819,48.208174,,,,
3,Whaling ,Barque Terror,123,12 March 1845,1845,,Island 1,155.370833,-24.916667,,,,
3,Whaling ,Barque Terror,777,15 March 1845,1845,,Island 2,162.81738,-20.6739,,,,
3,Whaling ,Barque Terror,546,22 March 1845,1845,,Place in ocean 3,160.26464,-11.66325,,,,
3,Whaling ,Barque Terror,888,23 July 1845,1845,,Place in ocean 4,161.94638,-10.18388,,,,
3,Whaling ,Barque Terror,543,19 December 1845,1845,,Place in ocean 5,160.90712,-8.94461,,,,
3,Whaling ,Barque Terror,2134,22 January 1846,1846,,Place in ocean 6,158.74232,-9.01835,,,,
3,Whaling ,Barque Terror,6666,30 January 1846,1846,,Back home,157.26555,-8.19361,,,,
你可以让 paths
在你的 path
和你的 marker
完成使用 delay
函数后进行动画处理,如下所示:
.duration(5000)
.delay(function(d, i) { // 'i' will give you the index
return i * 5000; // Multiply by 5000 so that it starts after the previous one has finished.
});
并为每个 path
获得一个 circle
标记,您需要像这样创建相同数量的 circles
:
var marker = g.selectAll('circle')
.data(dataNest).enter()
.append("circle")...
也使用d3.curveCatmullRom
以获得更好的path
。
这是一个plunker