Before addressing your problem with the playButtonSlider
function, I'd like to advise you to avoid, as best as you can, this mix of D3 and jQuery.
The problem is not only that this mix is unnecessary, but also because it can make things fail silently, which can be a nightmare to debug. For instance, if you select an element using jQuery ($) and try to set a on()
D3 method on it, it will simply not work. The examples abound.
Back to your code: my suggestion here is replacing your native setTimeout
with the D3 timeout
method. It's a better method when compared to setTimeout
, and it will (hopefully) avoid this difference in the speed of the slider when dealing with a huge JSON.
According to D3 API:
d3-timer provides an efficient queue capable of managing thousands of concurrent animations, while guaranteeing consistent, synchronized timing with concurrent or staged animations. Internally, it uses requestAnimationFrame for fluid animation (if available), switching to setTimeout for delays longer than 24ms.
Also, I created a function to stop the slider when you click the "play" button again, which you don't have right now (you can turn the play button in a stop button — a square — when the slider is playing, which gives a better user experience).
This is my suggestion:
var player;
var playing = false;
var counter = 0;
d3.select("#playButtonSlider").on("click", function() {
if (!playing) {
playing = true;
playButtonSlider()
} else {
player.stop()
playing = false
}
function playButtonSlider() {
if (counter > 10) {
return
}
sliderValue = $("#slider").slider('value', 2005 + counter);
counter += 1;
player = d3.timeout(playButtonSlider, 1000)
}
});
Explanation:
First, using a boolean named playing
, se verify if the slider is already moving or not. If not, we call playButtonSlider
and toggle the boolean:
if (!playing) {
playing = true;
playButtonSlider()
}
Inside playButtonSlider
comes the important part. This...
player = d3.timeout(playButtonSlider, 1000)
... calls the function again, using d3.timeout
, every 1000ms, and increasing counter by 1 unit. Of course, you can tweak those values according to your needs.
It's important giving a name to the d3.timeout
, so we can stop it when clicking the play button:
player.stop()
playing = false
Here is a Plunkr with those changes: https://plnkr.co/edit/aj45HA6TLshzNZe56gxu?p=preview