D3使用d3嵌套组沿多个路径设置动画标记

时间:2018-05-14 12:12:31

标签: javascript d3.js geojson

enter image description here我正在开发一个项目,让多条路径代表地图的路线。我跟着 this d3 nest example 通过密钥对我的数据进行分组以创建多个路由。

我想设置一个圆形元素的动画,以便沿着每个单独的路径路径进行过渡。我可以看到我的问题与this examplethis 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,,,,

1 个答案:

答案 0 :(得分:1)

您可以在paths以及delay同时使用path功能后,为marker设置动画:

.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.
});

要为每个circle获取path标记,您需要创建相同数量的circles,如下所示:

var marker = g.selectAll('circle')
            .data(dataNest).enter()
            .append("circle")...

还可以使用d3.curveCatmullRom来获得更好的path

这是plunker