2016-11-23 61 views
1

我有一組節點數據的子選擇刪除與動畫

var dataNodes = [ 
    { id: 1, x: 10, y:30, text: "node 1", muteText: false }, 
    { id: 2, x: 30, y:50, text: "node 2", muteText: false }, 
    { id: 3, x: 50, y:70, text: "node 3", muteText: false } 
]; 

我添加(因爲很多業務複雜的不是我真正的代碼),使用這種功能在DOM元素:

function redraw(newData) { 
    var node = d3 
     .select("body") 
     .selectAll("g.node") 
     .data(dataNodes) 
     .transition().duration(500) 
     .attr("transform", d => "translate(" + d.x + "," + d.y + ")"); 

    node.enter() 
     .append("g") 
     .attr("class", "node") 
     .attr("transform", d => "translate(" + d.x + "," + d.y + ")") 
     .append("text") 
     .text(d => d.text) 
     .style("opacity", "0") 
     .transition().duration(500) 
     .style("opacity", "1"); 

    node.exit() 
     .style("opacity", "0"); 
} 

我希望能夠做到以下所有當數據得到更新:

  • 添加在輸入節點
  • 化妝現有節點與過渡移動
  • 隱藏exitings節點(不透明度0),因爲它們可能會重新出現
  • 當節點獲取它們的「muteText」屬性更改爲true,使內部文本disapear

我對第一個要求非常滿意,但我真的不知道如何做最後一個要求:如何根據過濾的數據集刪除(甚至更改)子元素?我可以在d3.data函數中使用過濾器來做到這一點嗎?

讓我知道我的問題是否不清楚。

回答

2

如果要篩選,它做你的更新的選擇:

var node = svg 
    .selectAll("g.node") 
    .data(someData); 

    var nodeE = node.enter() 
    .append("g") 
    .attr("class", "node"); 

    nodeE.append("text") 
    .text(d => d.text); 

    // node is now UPDATE + ENTER 
    node = nodeE.merge(node); 

    // filter the text and set how you care 
    node.filter(function(d) { 
     return d.muteText 
    }) 
    .select("text") 
    .style("opacity", 1) 
    .transition() 
    .style("opacity", 0); 

    node.filter(function(d) { 
     return !d.muteText 
    }) 
    .select("text") 
    .style("opacity", 0) 
    .transition() 
    .style("opacity", 1); 

這裏是一個正在運行的例子:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
    <style> 
 
    text { 
 
     fill: black; 
 
     font-family: arial; 
 
    } 
 
    </style> 
 
</head> 
 

 
<body> 
 
    <script> 
 
    var dataNodes = [{ 
 
     id: 1, 
 
     x: 10, 
 
     y: 30, 
 
     text: "node 1", 
 
     muteText: false 
 
    }, { 
 
     id: 2, 
 
     x: 30, 
 
     y: 50, 
 
     text: "node 2", 
 
     muteText: false 
 
    }, { 
 
     id: 3, 
 
     x: 50, 
 
     y: 70, 
 
     text: "node 3", 
 
     muteText: false 
 
    }]; 
 

 
    var svg = d3.select('body') 
 
     .append('svg') 
 
     .attr('width', 500) 
 
     .attr('height', 500); 
 

 
    redraw([{ 
 
     id: 1, 
 
     x: 10, 
 
     y: 30, 
 
     text: "node 1", 
 
     muteText: false 
 
     }, { 
 
     id: 2, 
 
     x: 30, 
 
     y: 50, 
 
     text: "node 2", 
 
     muteText: false 
 
     }, { 
 
     id: 3, 
 
     x: 50, 
 
     y: 70, 
 
     text: "node 3", 
 
     muteText: false 
 
     }]); 
 
    
 
    setTimeout(function() { 
 
     redraw([{ 
 
     id: 1, 
 
     x: 10, 
 
     y: 30, 
 
     text: "node 1", 
 
     muteText: true 
 
     }, { 
 
     id: 2, 
 
     x: 100, 
 
     y: 50, 
 
     text: "node 2", 
 
     muteText: false 
 
     }, { 
 
     id: 3, 
 
     x: 50, 
 
     y: 70, 
 
     text: "node 3", 
 
     muteText: true 
 
     }]) 
 
    }, 2000) 
 
    
 
    setTimeout(function() { 
 
     redraw([{ 
 
     id: 1, 
 
     x: 10, 
 
     y: 30, 
 
     text: "node 1", 
 
     muteText: true 
 
     }, { 
 
     id: 2, 
 
     x: 100, 
 
     y: 50, 
 
     text: "node 2", 
 
     muteText: false 
 
     }, { 
 
     id: 3, 
 
     x: 50, 
 
     y: 70, 
 
     text: "node 3", 
 
     muteText: false 
 
     },{ 
 
     id: 4, 
 
     x: 60, 
 
     y: 90, 
 
     text: "node 4", 
 
     muteText: false 
 
     }]) 
 
    }, 4000) 
 

 
    function redraw(someData) { 
 

 
     var node = svg 
 
     .selectAll("g.node") 
 
     .data(someData); 
 

 
     var nodeE = node.enter() 
 
     .append("g") 
 
     .attr("class", "node") 
 
     .attr("transform", d => "translate(" + d.x + "," + d.y + ")"); 
 

 
     nodeE.append("text") 
 
     .text(d => d.text) 
 
     .style("opacity", 0) 
 
     .transition() 
 
     .style("opacity", 1); 
 

 
     node = nodeE.merge(node); 
 

 
     node.exit() 
 
     .style("opacity", "0"); 
 

 
     node.transition().duration(500) 
 
     .attr("transform", d => "translate(" + d.x + "," + d.y + ")"); 
 

 
     node.filter(function(d) { 
 
      return d.muteText 
 
     }) 
 
     .select("text") 
 
     .transition() 
 
     .style("opacity", 0);  
 

 
    } 
 
    </script> 
 
</body> 
 

 
</html>

+0

感謝您的答覆!你知道我是否可以讓輸入節點淡入並且現有的節點被翻譯?過渡似乎與我的情況相沖突。你也知道爲什麼我會得到一個類似於你的代碼中的「nodeE.merge不是函數」錯誤嗎? –

+1

@SimonBudin,查看更新後的答案。你看到'nodeE.merge不是函數'的原因可能是因爲你正在使用d3 **版本3 **,我的答案是在d3 **版本4 **中。 – Mark

+0

我會計劃升級,謝謝! –