Reputation: 14179
First off, some related items I've research, tried, and haven't had a good result with.
Next, the relevant part of my code:
function moveMarker(i) {
var curr_i = parseInt(d3.select("#nomad").attr("nomad-index"));
var target_i = parseInt(i);
switch (curr_i) {
case 0:
switch (target_i) {
case 0:
break;
case 1:
moveToMark(1);
break;
case 2:
moveToMark(1);
moveToMark(2);
break;
case 3:
moveToMark(1);
moveToMark(2);
moveToMark(3);
break;
case 4:
moveToMark(1);
moveToMark(2);
moveToMark(3);
moveToMark(4);
break;
}
case 1:
switch (target_i) {
case 0:
moveToMark(0);
break;
case 1:
break;
case 2:
moveToMark(2);
break;
case 3:
moveToMark(2);
moveToMark(3);
break;
case 4:
moveToMark(2);
moveToMark(3);
moveToMark(4);
break;
}
case 2:
switch (target_i) {
case 0:
moveToMark(1);
moveToMark(0);
break;
case 1:
moveToMark(1);
break;
case 2:
break;
case 3:
moveToMark(3);
break;
case 4:
moveToMark(3);
moveToMark(4);
break;
}
case 3:
switch (target_i) {
case 0:
moveToMark(2);
moveToMark(1);
moveToMark(0);
break;
case 1:
moveToMark(2);
moveToMark(1);
break;
case 2:
moveToMark(2);
break;
case 3:
break;
case 4:
moveToMark(4);
break;
}
case 4:
switch (target_i) {
case 0:
moveToMark(3);
moveToMark(2);
moveToMark(1);
moveToMark(0);
break;
case 1:
moveToMark(3);
moveToMark(2);
moveToMark(1);
break;
case 2:
moveToMark(3);
moveToMark(2);
break;
case 3:
moveToMark(3);
break;
case 4:
break;
}
}
}
function moveToMark(i) {
var x = spot[i][7]; // Latitude
var y = spot[i][8]; // Longitude
d3.select("#nomad")
.attr("nomad-index", i)
.transition()
.delay(3000)
.duration(1000)
.attr("cx", x)
.attr("cy", y);
}
The gist of what I'm trying to do:
I have a table of events. On clicking any of the events in the table, I have a circle (nomad
) that moves to the respective location of that event as determined in the spot
dataset. Directly moving point-to-point is no issue. However, I have one particular constraint: I have to move according to the timeline of the events.
Say, I click on event #3. My circle must move first to event #1 and #2, after which they'll stay in event #3. If the circle is in any event, clicking on any other event, whether of a lower or a higher index, it will need to traverse the events between its current position and its target.
I believe my nested switch case can explain this further. I believe what I'm attempting is not as complicated as I'm making it out to be. However, I've hit a major snag: my nomad
circle does not go through the events step-by-step but rather jumps to the last event right away after the delay.
I have read in the above links that transitions have an issue about chaining, or that I have to employ end(...)
to make this work.
The question/s:
Is it possible to reduce this attempt to a recursive function instead? If so, how? If not, how can I make it so that each moveToMark
fires consecutively?
Upvotes: 0
Views: 63
Reputation: 109282
The problem is that creating a transition on a D3 selection cancels any other transitions that may have been created. That is, only your last call to .transition()
takes effect as all the previous transitions are cancelled.
The solution is to create another transition on the transition and not the selection (see the documentation). This would look something like the following:
var cur_trans;
function moveMarker(i) {
cur_trans = d3.select("#nomad");
// more code
}
function moveToMark(i) {
var x = spot[i][7]; // Latitude
var y = spot[i][8]; // Longitude
d3.select("#nomad")
.attr("nomad-index", i);
cur_trans = cur_trans
.transition()
.delay(3000)
.duration(1000)
.attr("cx", x)
.attr("cy", y);
}
This will overwrite cur_trans
with the new transition at each call, thus making sure that you don't lose any transitions.
Note that depending on the rest of your code and its call structure there may be race conditions etc that you may have to guard against.
Upvotes: 1