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

Javascript 如何在d3.js中的不同元素上进行链式转换?,javascript,d3.js,Javascript,D3.js,我想在不同的元素上做链式转换。在整个程序中,我希望运行一系列转换。在元素x上的第一次转换完成后,我想从元素y上的转换开始,以此类推。过渡的持续时间应该有所不同 “解决”该问题的一种方法是根据先前转换的持续时间之和延迟后面的所有转换。但这是相当丑陋的,因为它是相当混乱和不准确的 以下是我尝试完成的一个示例: <!DOCTYPE html> <meta charset="utf-8"> <head> <script src="https://

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

让sel=d3。选择(“主体”)
让selFirst=sel.append(“h1”).attr(“class”,“first”).text(“first”);
让selsond=sel.append(“h2”).attr(“class”,“second”).text(“second”);
让selThird=sel.append(“h3”).attr(“class”,“third”).text(“third”);
设trans=d3.过渡(“体”);
让firstTrans=trans.each(function(){selFirst.transition().style(“不透明”,0).transition().style(“不透明”,1);})
设secondTrans=firstTrans.each(函数(){selsond.transition().style(“不透明”,0).transition().style(“不透明”,1);})
设thirdTrans=secondTrans.each(function(){selThird.transition().style(“不透明”,0).transition().style(“不透明”,1);})

感谢Gerardo Furtado,这里有一个可能的解决方案

步骤1:必须使用相同的类标记所有对应的元素,即
链式转换

    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中创建元素时还没有这样做,可以与其他数据一起进行)

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

完整的示例如下:

让sel=d3.选择(“主体”)
让selFirst=sel.append(“h1”).attr(“类”,“链式转换优先”).text(“优先”);
让selSecond=sel.append(“h1”).attr(“类”,“链式转换秒”).text(“秒”);
让selThird=sel.append(“h1”).attr(“class”,“chained transition third”).text(“third”);
让chainedSel=d3.selectAll(“.chained transition”).data([100020003000]);
transitionNext(chainedSel);
函数transitionNext(_selection,_index=0){
log(“索引:”+_索引);
让newSel=
_filter(函数(d,i){return_index==i;});
newSel.transition()
.持续时间(d=>d)
.style(“不透明度”,0)
.transition()
.持续时间(d=>d)
.style(“不透明度”,1)
.style(“颜色”、“绿色”)
.on(“结束”,函数(){
_指数=_指数+1;
如果(_selection.size()>_index){transitionNext(_selection,_index);}
});
}

我用一个非常简单的解决方案写了一个答案,假设持续时间相同。如果不是这样,请告诉我,我会删除它。哇,你的方法非常优雅,我不知道延迟函数中的第二个参数。但事实上,我需要不同的过渡时间。很抱歉没有在问题中回答它-我会编辑它好的,我刚刚删除了我的答案。另外,因为不同的元素可能不会被简单的d3所掌握。selectAll()。。。我希望看到一个通用的解决方案。所以我的猜测是,您必须通过选择一个合适的根元素(比如这里的body)来引用它们,然后向下导航到函数中相应的元素。很抱歉没有弄清楚。你可以给他们一个普通的类。好吧,我删除了在
delay
方法中显示第二个参数的答案,因为根据你的说法,持续时间是不同的。。。但是,在您的回答中,持续时间是相同的!最重要的是,你正在将整个选择传递给连续的调用,而你应该只传递元素。好的,感谢Alocumlus和Gerardo的评论-我将编辑我的答案,并希望澄清,Gerardo:我不知道如何轻松地将函数更改为只有一个元素作为参数Gerardo:我添加了一个版本,在该版本中,您只需将带有一个元素的选择传递给后续函数调用。
    let chainedSel = d3.selectAll(".chained-transition").data([1000,2000,3000]);
    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);}
                });
    }