【问题标题】:How to do chained transitions on different elements in d3.js?如何在 d3.js 中对不同元素进行链式转换?
【发布时间】:2018-06-29 07:10:47
【问题描述】:

我想对不同的元素进行链式过渡。在整个程序中,我想运行一系列转换。在元素 x 的第一次转换完成后,我想从元素 y 的转换开始,依此类推。过渡的持续时间应有所不同。

“解决”它的一种方法是根据先前转换的持续时间总和延迟所有后面的转换。但这很丑陋,因为它非常混乱且不准确。

这是我尝试完成的一个示例:

<!DOCTYPE html>
<meta charset="utf-8">
<head>
        <script src="https://d3js.org/d3.v4.js"></script>
</head>
<body>
    <script>
        let sel = d3.select("body")
        let selFirst = sel.append("h1").attr("class", "first").text("first");
        let selSecond = sel.append("h2").attr("class", "second").text("second");
        let selThird = sel.append("h3").attr("class", "third").text("third");

        let trans = d3.transition("body");
        let firstTrans = trans.each(function() {selFirst.transition().style("opacity", 0).transition().style("opacity",1); })
        let secondTrans = firstTrans.each(function() {selSecond.transition().style("opacity", 0).transition().style("opacity",1); })
        let thirdTrans = secondTrans.each(function() {selThird.transition().style("opacity", 0).transition().style("opacity",1); })

    </script>
</body>
</html> 

See this JSfiddle

【问题讨论】:

  • 假设持续时间相同,我用一个非常简单的解决方案写了一个答案。如果不是这样,请告诉我,我会删除它。
  • 哇,你的方法非常优雅,我不知道延迟函数中的第二个参数。但事实上,我需要不同的过渡持续时间。很抱歉没有在问题中解决它 - 我会编辑它
  • 好的,我刚刚删除了我的答案。
  • 另外,由于简单的 d3.selectAll() 可能无法掌握不同的元素...我希望看到一个通用的解决方案。所以我的猜测是,您必须通过选择适当的根元素(如此处的主体)来引用它们,然后向下导航到函数中的相应元素。抱歉,不清楚。
  • 你可以给他们一个通用的类。

标签: javascript d3.js


【解决方案1】:

感谢 Gerardo Furtado,这是一种可能的解决方案。

第1步:你必须用相同的类标记所有对应的元素,即chained-transition

    let sel = d3.select("body")
    let selFirst = sel.append("h1").attr("class", "chained-transition first").text("first");
    let selSecond = sel.append("h1").attr("class", "chained-transition second").text("second");
    let selThird = sel.append("h1").attr("class", "chained-transition third").text("third");

第 2 步:现在您可以创建一个选择,其中包含应连续转换的所有元素。要为每个选择设置不同的持续时间,您可以将所需的持续时间(以毫秒为单位)附加到每个元素。 (如果您尚未在步骤 1 中创建元素,则可能与其他数据一起完成)

    let chainedSel = d3.selectAll(".chained-transition").data([1000,2000,3000]);

第 3 步:创建一个函数,该函数一次接受一个选择,将其转换(及其持续时间)并使用下一个元素调用自身。下面的代码是一个使用整个链接选择调用的函数。它过滤到相应的(下一个)元素。

    transitionNext(chainedSel);

    // function gets the chained selection with 
    // all the corresponding elements. 
    // It start with the first one by default.
    function transitionNext(_selection, _index = 0){ 
        console.log("index: " + _index);
        // start off with the first element (_index === 0)
        let newSel = 
            _selection.filter(function(d,i) { return _index === i;});

            newSel.transition()
                    .duration(d => d) // take the corresponding duration
                    .style("opacity", 0)
                .transition()
                    .duration(d => d) // as above
                    .style("opacity",1)
                    .style("color", "green")
                // this function is called after the transition is finished
                .on ("end", function() { 
                    _index = _index + 1;
                    // call function and filter the next element
                    if (_selection.size() > _index) { transitionNext(_selection, _index);}
                });
    }

完整的例子在这里:

        let sel = d3.select("body")
        let selFirst = sel.append("h1").attr("class", "chained-transition first").text("first");
        let selSecond = sel.append("h1").attr("class", "chained-transition second").text("second");
        let selThird = sel.append("h1").attr("class", "chained-transition third").text("third");

        let chainedSel = d3.selectAll(".chained-transition").data([1000,2000,3000]);

        transitionNext(chainedSel);

        function transitionNext(_selection, _index = 0){
            console.log("index: " + _index);
            let newSel = 
                _selection.filter(function(d,i) { return _index === i;});

                newSel.transition()
                        .duration(d => d)
                        .style("opacity", 0)
                    .transition()
                        .duration(d => d)
                        .style("opacity",1)
                        .style("color", "green")
                    .on ("end", function() {
                        _index = _index + 1;
                        if (_selection.size() > _index) { transitionNext(_selection, _index);}
                    });
        }
&lt;script src="https://d3js.org/d3.v4.js"&gt;&lt;/script&gt;

具有重复函数调用的版本仅传递一个元素的选择而不是所有元素是here

【讨论】:

  • 好吧,我删除了在delay 方法中向您显示第二个参数的答案,因为根据您的说法,持续时间不同......但是,在您的回答中,持续时间是相同的!最重要的是,当您应该只传递元素时,您会将整个选择传递给后续调用。
  • 好的,感谢 alocumulus 和 Gerardo 的 cmets - 我将编辑我的答案并希望澄清,
  • Gerardo:我不知道如何轻松地将函数更改为只有一个元素作为参数
  • Gerardo:我添加了一个版本,您只需将带有一个元素的选择传递给连续的函数调用。
猜你喜欢
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
  • 2013-03-25
  • 2013-04-23
  • 2022-01-22
  • 2019-05-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多