0

I'm visualising voyages on a map with D3.js' path. My data is in a JSON file like the following format:

[{"begin_date":1519,"trips":[[-13.821772,14.294839],[-9.517688,-7.958521],[0.598434,-34.704567],[18.374673,-86.850335]]},
{"begin_date":1549,"trips":[[12.821772,-16.294839],[5.517688,-20.958521],[13.598434,-54.704567],[18.374673,-86.850335]]},
{"begin_date":1549,"trips":[[12.821772,-16.294839],[5.517688,-20.958521],[13.598434,-54.704567],[18.374673,-86.850335]]}]

As can be seen, sometimes there are multiple voyages for a year. The following recursive function works:

d3.json("data/output.json", function(error, trips) {
            if (error) throw error

            var nest = d3.nest()
            .key(function(d){
                return d.begin_date;
            })
            .entries(trips)

            var trip = svg.selectAll(".voyage");

            // Add the year label; the value is set on transition.
            var label = svg.append("text")
                .attr("class", "year label")
                .attr("text-anchor", "end")
                .attr("y", height - 400)
                .attr("x", width+150)
                .text(function(d) {return d});

            var pnt = 0;

            doTransition();
            function doTransition() {
                trip.data(nest[pnt].values).enter()
                    .append("path")
                        .attr("class", "voyage")
                        .style("stroke", colorTrips)
                        .attr('d', function(d) {label.text(d.begin_date); return lineGen(d.trips.map(reversed).map(projection))})
                        .call(function transition(path) {
                            path.transition()
                                .duration(500)
                                .attrTween("stroke-dasharray", tweenDash)
                                .each("end", function(d) {
                                    d3.selectAll(".voyage")
                                        .remove()
                                        pnt++;
                                        if (pnt >= nest.length){return;}
                                        doTransition();
                                        })
                                    })
                                }

Some voyages plot as they should voyage_success However some of them, are never plotted (I can see in the log) and it jumps from year 1545-1569 despite there being data points in between. I suspect it is due to the recursive function calling itself before the transition is finished. But I am also not sure, in the slightest.

Hope it is sufficient, I am new to D3.js, and suddenly found myself out of depth.

  • 1
    At a glance - assuming you have multiple trips per year - you are calling `doTransition` multiple times each iteration of `doTranstion`, as such `pnt` is incremented more than one each transition. `transition.each("end"`, will trigger a function as many times as there are elements in the selection - in this case paths. – Andrew Reid Jun 03 '19 at 15:07
  • Yeah man, that was it. I added an increment variable that just counts the time it was called (similar to [this](https://stackoverflow.com/questions/10692100/invoke-a-callback-at-the-end-of-a-transition)) and then checking if it was equal to the number of items in the list of data points. – Sune Nutmeg Jun 03 '19 at 15:34
  • 2
    There is the option to do it non-recursively and set the transition with a delay dependent on what year the voyage was as well. – Andrew Reid Jun 03 '19 at 15:40

0 Answers0