简体   繁体   English

D3 过渡中断重绘

[英]D3 Transition Breaking Redraw

I'm trying to animate the update of a D3 chart where I have rectangles with wrapped text inside them.我正在尝试为 D3 图表的更新设置动画,其中我有矩形,其中包含包装文本。 If I do this without a transition, everything functions as expected.如果我在没有过渡的情况下执行此操作,则一切都会按预期运行。 When I add a transition though, the text does not wrap at all.但是,当我添加过渡时,文本根本不会换行。 It looks like it would if the wrap function was never called.如果从未调用 wrap 函数,它看起来会这样。

To make things weirder, if I step through the debugger, I can see that is in fact going into the wrap function.更奇怪的是,如果我单步调试调试器,我可以看到它实际上进入了 wrap 函数。 At the end of the wrap function, the displayed result actually looks as it should.在 wrap 函数结束时,显示的结果实际上看起来应该如此。 However, once I step out of the function and back into the D3 library code, it reverts back to the unwrapped view.但是,一旦我退出函数并返回 D3 库代码,它就会恢复到展开的视图。

My best guess here is that the wrap function takes a while and causing some sort of issue with the transition, but I'm not sure.我最好的猜测是 wrap 函数需要一段时间并导致某种转换问题,但我不确定。

Here are the relevant snippits of the redraw function, which gets called when I want to update the page:以下是redraw函数的相关代码片段,当我想更新页面时会调用该函数:

MyChart.prototype.redraw = function(taskList) {
    var that = this;

    var svg = d3.select("svg");
    var chart = svg.select(".chart");

    var blocks = chart.selectAll(".block")
        .data(myData, this.keyFunction);

    blocks.transition()
        .attr("transform", function(d) {
            return rectTransform(d, that.xScale, that.yScale);
        })
        .attr("height", function(d) {
            return that.yScale.bandwidth() - GRIDLINE_WIDTH;
        })
        .attr("width", function(d) {
            return Math.max(that.xScale(new Date(d.date).addDays(1)) -
                            that.xScale(new Date(d.date)) -
                            GRIDLINE_WIDTH, 0);
        });

    blocks.exit().remove();

    // update block labels
    var blockLabels = svg.selectAll('.blockLabel')
        .data(myData, this.keyFunction);

    blockLabels.transition()
        .attr('visibility', function(d) {
            if (new Date(d.date) < that.xScale.domain()[0] ||
                new Date(d.date) >= that.xScale.domain()[1])
                return 'hidden';
            return 'visible';
        })
        .attr("transform", function(d) {
            return rectLabelTransform(d, that.xScale, that.yScale);
        })
        .text(function(d) {
            return getBlockText(d);
        })
        // 50 pixels for now, later will update to actual rect width
        .call(wrap, 50);

    return this;
}

And here is the wrap function, taken from this Mike Bostock example :这是wrap函数,取自Mike Bostock 示例

function wrap(text, width) {
    text.each(function(d) {
        var text = d3.select(this);
        // quickly ignore short labels
        if (text.text().length < 10) {
            text.attr('dy', '0.35em');
            return;
        }
        var words = text.text().split(/\s+/).reverse();
        var word;
        var line = [];
        var lineNumber = 0;
        var lineHeight = 0.9; // ems
        var y = text.attr("y");
        var dy = parseFloat(text.attr("dy"));
        var tspan = text.text(null)
            .append("tspan")
            .attr("x", 0)
            .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", 0)
                    .attr("y", y)
                    .attr("dy", ++lineNumber * lineHeight + dy + "em")
                    .text(word);
            }
        }
        // re-center if only one line
        if (lineNumber < 1) tspan.attr('dy', '0.35em');
    });
}

I'm thinking that I could try improving the speed of the wrap function, or, worst-case, just ditch the animations.我在想我可以尝试提高 wrap 函数的速度,或者,在最坏的情况下,只是放弃动画。 But I'm curious as to what the specific issue is..但我很好奇具体问题是什么..

EDIT--------编辑 - - - -

Mark's answer did help, however when I change .call(wrap, 200) to .call(wrap, function(d) {return 200;}) it breaks again.马克的回答确实有帮助,但是当我将.call(wrap, 200)更改为.call(wrap, function(d) {return 200;})它再次中断。 I'm assuming this is timing thing, but this behavior seems pretty strange to me that such a small change could have such a large impact.我假设这是时间问题,但这种行为对我来说似乎很奇怪,如此小的变化可能会产生如此大的影响。 Any ideas?有任何想法吗?

Your wrap function is being called within the transition.您的wrap函数在转换中被调用。 I think you really mean this:我想你的意思是这样的:

blockLabels.transition()
    .text(function(d) {
        return getBlockText(d);
    })
    .call(wrap, 50)
    .attr('visibility', function(d) {
        if (new Date(d.date) < that.xScale.domain()[0] ||
            new Date(d.date) >= that.xScale.domain()[1])
            return 'hidden';
        return 'visible';
    })
    .attr("transform", function(d) {
        return rectLabelTransform(d, that.xScale, that.yScale);
    });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM