I am trying to create a timeline using D3.js v4. I have successfully created my scatter plot with its axis and a brush to allow users define a specific time period.
I want to allow users to be able to 'play' the timeline just like an audio/video player having an indicator that will move from left to right using a customizable duration. In order to achieve this I've placed a vertical line with a transition to act as the indicator.
My problem is that I cannot retrieve the x-axis coordinates while the transition is running. I want to achieve this because the x-axis values need to interact with another part of the code.
I've tried everything including playing around with tween and attrTween functions but I couldn't make it work. Ideally I would like the indicator to begin and stop within the brush limits.
svg.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append('line')
.attr("class", "timeline-indicator")
.attr("stroke-width", 2)
.attr("stroke", "black")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 0)
.attr("y2", height)
.transition()
.duration(9000)
.attr("x1", 500)
.attr("y1", 0)
.attr("x2", 500)
.attr("y2", height);
You should be able to accomplish this using a tween function in your transition. A tween function will trigger on every tick of the transition and is one way to call a function every tick.
The tween method needs an attribute name (as it is intended to provide custom interpolation for an attribute), but this can be a dummy attribute, or one that isn't changed (as in my example below). Documentation on the method is here.
In my example I pull the x property (well, cx property) of a circle as it moves across the screen, using a tween function:
.tween("attr.fill", function() {
var node = this;
return function(t) {
console.log(node.getAttribute("cx"));
}
})
Here is a snippet of it at work:
var svg = d3.select("body").append("svg")
.attr("width",400)
.attr("height",400);
var circle = svg.append("circle")
.attr("cx",20)
.attr("cy",20)
.attr("r",10);
circle.transition()
.attr("cx",380)
.attr("cy",20)
.tween("attr.fill", function() {
var node = this;
return function(t) {
console.log(node.getAttribute("cx"));
}
})
.duration(1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>