如何在d3.js中对不同元素进行链式转换?

时间:2018-01-20 00:18:38

标签: javascript d3.js

我想对不同的元素进行链式转换。在整个程序中,我想运行一系列过渡。在元素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

1 个答案:

答案 0 :(得分: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);}
                });
    }

完整的例子在这里:

&#13;
&#13;
        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);}
                    });
        }
&#13;
<script src="https://d3js.org/d3.v4.js"></script>
&#13;
&#13;
&#13;

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