2016-03-07 122 views
0

我有一個樹形圖(簡單),我想添加一個新元素(請參閱下面的代碼中的DS0和DS1)。我不想重新創建整個樹形圖,而是想更新數據。 置頂是假 更新部調整克變換(OK) 更新部調整包含矩形寬度/高度(未OK)d3 treemap動態數據不調整單元格寬度/高度

  • 與DEVMODE關閉(鉻)的rects寬度/高度沒有被更新(看起來像dx和dy值是舊值 - 可以用cosnole.log語句看到)
  • devmode on(chrome)「調試器」語句啓動時,如果我單步執行,則會更新一些寬度值好。

我看不出爲什麼這不是正確更新,但我可以做一些觀察。看起來,綁定到<g><rect><text>元素的數據在新數據進入時未被調整。當然,<text>數據仍然是「舊」的。

也許唯一有用的方法是重新創建整個SVG? diagrams

<!DOCTYPE html> 
<html> 
    <head> 
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> 
     <title>Test Dynamic Treemap</title> 
    <style> 
rect { fill: none; stroke: #fff;} 
text { font: 10px sans-serif;} 
    </style> 
<body> 
<input type="button" id="add" value="add"> 
<input type="button" id="remove" value="remove"> 
<br> 
<script src="http://d3js.org/d3.v3.min.js"></script> 
<script> 

var width = 960, 
    height = 500, 
    color = d3.scale.category20c(); 

var treemap = d3.layout.treemap() 
     .padding([15,5,5,5]) 
     .size([width, height]) 
     .sticky(false) 
     .value(function(d) { return 5; }); 

var svg = d3.select("body").append("svg") 
     .attr("width", width) 
     .attr("height", height) 
    .append("g") 
     .attr("transform", "translate(-.5,-.5)"); 

var DS0 = 
{'name': 'data', 'children': [ 
    {'name':'A', 'children':[ 
     {'name':'A01' }, 
     {'name':'A02'} 
    ]}, 
]} 
var DS1 = 
{'name': 'data', 'children': [ 
    {'name':'A', 'children':[ 
     {'name':'A01' }, 
     {'name':'A02'}, 
     {'name':'A03'} 
    ]}, 
]} 
d3.select('#add').on('click',function() {withData(DS1)}) 
d3.select('#remove').on('click',function() {withData(DS0)}) 
withData(DS0); 

function withData(json){ 
    var cell = svg.data([json]).selectAll("g") 
      .data(treemap.nodes) 

    // BEGIN UPDATE SECTION 
    var updates = cell.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
    // adjust the parameters of the updated objects 
    updates.selectAll("rect") // These only seem to use 'new' data when stepped through in debugger 
           // ====================================================================== 
       .attr("width", function(d) { debugger; console.log(d.name + ' setting width to ' + d.dx); return d.dx; }) 
       .attr("height", function(d) { debugger; console.log(d.name + ' setting height to ' + d.dy); return d.dy; }) 
       .style("fill", function(d) { return d.children ? color(d.name) : "yellow"; }) 
    // END UPDATE SECTION 

    // BEGIN ENTER SECTION (ADDS) 
    var adds = cell.enter().append("g") 
      .attr("class", function(d) {return "cell " + d.name}) 
      .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) 
    adds.append("rect") 
       .attr("width", function(d) { return d.dx; }) 
       .attr("height", function(d) { return d.dy; }) 
       .style("fill", function(d) { return d.children ? color(d.name) : null; }) 
    adds.append("text") 
      .attr("x", function(d) { return d.dx/2; }) 
      .attr("y", function(d) { return 5; }) 
      .attr("dy", ".35em") 
      .attr("text-anchor", "top") 
      .text(function(d) { return d.children ? d.name : d.name; }); 
    // END ENTER SECTION (ADDS) 

    // BEGIN UPDATE AND ENTER SECTION (Updates And ADDS) 
     //var updatesAndAdds = cell.attr("transform", function(d) { console.log("UpdateAndUpdate:" + d.name); return "translate(" + d.x + "," + d.y + ")"; }); 
    // END UPDATE AND ENTER SECTION (Updates And ADDS) 

    // BEGIN EXIT SECTION (Updates And ADDS) 
    var rems = cell.exit().remove(); 
    // END EXIT SECTION (Updates And ADDS) 

}; 

</script> 

回答

0

此代碼:

var adds = cell.enter().append("g") 
    ... 
adds.append("text") 
    .attr("x", function(d) { return d.dx/2; }) 
    .attr("y", function(d) { return 5; }) 

意味着你只處理的文本元素的輸入選擇。上面的代碼:

updates.selectAll("rect") 

正在處理rects的更新選擇(並且您需要類似於文本元素的東西)。

讓我們退後一步,並嘗試清理它一個位(未測試的代碼):

//////////// 
// this is the entire selection 
///////////// 
var cell = svg.data([json]).selectAll("g") 
     .data(treemap.nodes); 

///////////// 
// remove is easy, get it out of the way 
///////////// 
cell.exit().remove(); 

///////////// 
// do all the entering first 
//////////// 
// enter the gs 
var eCell = cell.enter().append("g") 
    .attr("class", function(d) {return "cell " + d.name});  
// and rect for that g 
eCell.append("rect") 
    .style("fill", function(d) { return d.children ? color(d.name) : null; }); 
// and a text for that g 
eCell.append("text") 
    .attr("y", function(d) { return 5; }) 
    .attr("dy", ".35em") 
    .attr("text-anchor", "top"); 

///////////// 
// now do all the updating, this is enter + update 
//////////// 
// move the g 
cell.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
// resize/move the rect 
cell.select("rect") 
    .attr("width", function(d) { debugger; console.log(d.name + ' setting width to ' + d.dx); return d.dx; }) 
    .attr("height", function(d) { debugger; console.log(d.name + ' setting height to ' + d.dy); return d.dy; }); 
// move the text and update value 
cell.select("text") 
    .attr("x", function(d) { return d.dx/2; }) 
    .text(function(d) { return d.children ? d.name : d.name; }); 
+0

馬克,同意更新不處理文本的效果,這保持了爲簡潔起見,有實際上是一個'updates.selectAll(「text」)'部分(不包括上面)。問題是更新rects沒有看到新的數據。將檢查爲什麼你的似乎這樣做;-) – twistedroutes

+0

@twistedroutes,'var updates = cell.attr ...'是沒有必要的,它只會有'細胞'已經包含的副本。它也應該是'updates.select'而不是'updates.selectAll',參見[這裏爲什麼](https://github.com/mbostock/d3/wiki/Selections#select)。 – Mark