Edit: Looks like your edit overlapped with my reply.
There are a few things here that are bound to cause problems:
- Your code produces side effects. Every time you run your cell, you select from the already modified SVG DOM. Instead, you should
- label your SVG cell (e.g.
chart
) - clone the DOM:
const svg = d3.select(chart.cloneNode(true));
- select from the cloned DOM, e.g.:
const axisX = svg.select(".xAxis>.xAxisBottom>.domain");
- return the cloned and animated DOM at the end of your cell:
return svg.node();
- label your SVG cell (e.g.
- You’re doing math with strings, which may cause unexpected behavior. I recommend to always cast to Number, so that you’d at least get NaN in the right place. Example (note the “+”):
const end = +child.getAttribute("y2");
- In this line you always fetch the same value:
const b = axisX.node().getPointAtLength(axisXLen * 0).x;
There are other problems here like your interpolator function not returning any value. In general I highly recommend that you keep an eye out for errors in your dev tools console and use methods like console.assert()
to verify that your code is doing what you think it does (e.g. to check with isNaN()
).
I won’t go into more detail for the updated version that you shared, because I feel that in it you’re making things more difficult for yourself than they need to be.
Instead I’ll pick up from the second option that I mentioned and use d3.local (we could also use a JS Map instead). The full streamlined implementation then looks like this:
{
const duration = 5000;
const svg = d3.select(chart.cloneNode(true));
const axisX = svg.select(".xAxis>.xAxisBottom>.domain");
const axisXLen = axisX.node().getTotalLength();
const x0 = axisX.node().getPointAtLength(0).x;
////////////////////////////////////////////////////////////
//////////////////////// Axis transition////////////////////
////////////////////////////////////////////////////////////
axisX
.attr("stroke-dasharray", `0 ${axisXLen}`)
.transition()
.duration(duration)
.ease(d3.easeQuadIn)
.attr("stroke-dasharray", `${axisXLen} ${axisXLen}`);
////////////////////////////////////////////////////////////
//////////Axis gridline transition with tranition.attr//////
////////////////////////////////////////////////////////////
const y2Values = d3.local();
svg.selectAll(".xAxis>.xAxisBottom>.tick>line")
.each(function() {
y2Values.set(this, +this.getAttribute("y2"));
})
.attr("y2", 0)
.transition()
.duration(duration)
.delay(function() {
const p = +this.parentNode
.getAttribute("transform")
.match(/(\d+\.\d+)(?=\,)|(\d+)(?=\,)/gm);
const elapsedTimePct = Math.sqrt((p - x0) / axisXLen);
return duration * elapsedTimePct;
})
.attrTween("y2", function () {
const end = y2Values.get(this);
return d3.interpolate(0, end);
});
return svg.node();
}