I am attempting to make a reusable chart in D3. The figure draws a line using .curve(d3.curveStepAfter)
and I am attempting to animate the lines using the stroke-dasharray attribute with a tween function. The following code is how I initialize the visualization:
selection
.append('g')
.selectAll('path.line')
.data(grouped_data)
.join(
(enter) => enter
.append('path')
.attr('class', 'step_line')
.call(initializeLine)
.call(lineTransition),
(update) => update,
(exit) => exit.remove());
const initilizeLine = (enter) => {
enter
.attr('d', (d) => drawCurve(d[1]))
.attr('stroke', d => {
return color(d[0]);
})
.attr('fill', 'none');
}
const lineTween = () => {
let l = this.getTotalLength(),
i = d3.interpolateString('0,' l, l ',' l);
return function(t) { return i(t) };
}
const lineTransition = (enter) => {
enter
.transition()
.duration(2500)
.attrTween('stroke-dasharray', lineTween);
}
The lines draw correctly in the svg, but the transition doesn't work. When I look in the console I see the error this.getTotalLength is not a function. This is because the enter object is being passed. I need to be able to pass the path to the lineTween function, but am scratching my head.
CodePudding user response:
In the context of your arrow function this
is the window
. Therefore, either use a regular function or use the third and second parameters combined to get the element you want:
const lineTween = (_, j, n) => {
let l = n[j].getTotalLength(),
i = d3.interpolateString('0,' l, l ',' l);
return function(t) { return i(t) };
}