Sunday 29 August 2021

Text gets flushed to initial state after applying wrapping function in D3

I have following function for wrapping text in D3 taken from this answer:

function wrap(text, width) {
    text.each(function () {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            x = text.attr("x"),
            y = text.attr("y"),
            dy = 0, //parseFloat(text.attr("dy")),
            tspan = text.text(null)
                        .append("tspan")
                        .attr("x", x)
                        .attr("y", y)
                        .attr("dy", dy + "em");
        while (word = words.pop()) {
            line.push(word);
            tspan.text(line.join(" "));
            if (tspan.node().getComputedTextLength() > width) {
                line.pop();
                tspan.text(line.join(" "));
                line = [word];
                tspan = text.append("tspan")
                            .attr("x", x)
                            .attr("y", y)
                            .attr("dy", ++lineNumber * lineHeight + dy + "em")
                            .text(word);
            }
        }
    });
}

I initialize the nodes in a following manner:

const nodes = [1, 2, 3]
const nodesTextsEnter = vis.g.selectAll('text.node').data(nodes).enter()
const nodesTextsUpdate = vis.g.selectAll('text.node').data(nodes)
vis.g.selectAll('text.node').data(nodes).exit().remove()
        
nodesTextsEnter.append('text')
                .attr('x', (d, i) => i*30)
                .attr('y', (d, i) => i*30)
                .attr('text-anchor', 'middle')
                .attr('dominant-baseline', 'middle')
                .attr('font-size', 12)
                .style('cursor', 'pointer')
                .attr('class', 'node')
                .attr('opacity', '0')
                .transition()
                .attr('opacity', '1')
                .attr('x', (d, i) => i*30)
                .attr('y', (d, i) => i*30)
                .text('This is a long text')
                .call(wrap, 30)

nodesTextsUpdate
                .transition(transitionDuration)
                .attr('x', (d, i) => i*30)
                .attr('y', (d, i) => i*30)
                .text('This is a long text')
                .call(wrap, 30)

The problem is that while debugging wrap function, I see all the wrapping changes happening to the nodes, but then at some point (specifically, I figured it is happening on timerFlush() in wake function of timer.js) content of nodes gets flushed as though it was never wrapped.

Why this could be happening? Any ideas are welcome.



from Text gets flushed to initial state after applying wrapping function in D3

No comments:

Post a Comment