【问题标题】:d3 treemap dynamic data not adjusting cell width/heightd3树图动态数据不调整单元格宽度/高度
【发布时间】:2016-03-08 01:32:30
【问题描述】:

我有一个树形图(简单),我想在其中添加一个新元素(请参阅下面代码中的 DS0 和 DS1)。我不想重新创建整个树形图,而是想“更新”数据。 粘性是假的 更新部分调整g变换(OK) 更新部分调整包含的矩形宽度/高度(不好)

  • 在 devmode 关闭 (chrome) 的情况下,矩形宽度/高度不会更新(看起来 d.x 和 d.y 值是旧值 - 可以通过 cosnole.log 语句查看)
  • 在 (chrome) 上使用 devmode 时,“调试器”语句会启动,如果我逐步执行,某些宽度值会更新正常。

我不明白为什么这没有正确更新,但我可以做一些观察。当新数据进入时,与<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>

【问题讨论】:

    标签: d3.js treemap


    【解决方案1】:

    这段代码:

    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")
    

    正在处理矩形的更新选择(您需要类似的东西用于文本元素)。

    让我们退后一步,尝试清理一下(未经测试的代码):

    ////////////
    // 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; });
    

    【讨论】:

    • 马克,同意更新不处理文本的影响,为简洁起见,这被保留了,实际上有一个 updates.selectAll("text") 部分(不包括在上面)。问题是更新矩形没有看到新数据。会检查你为什么会这样做;-)
    • @twistedroutes, var updates = cell.attr... 不是必需的,它只会拥有cell 已经包含的内容的副本。也应该是updates.select 而不是updates.selectAll,参见here for why
    猜你喜欢
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 2011-04-13
    相关资源
    最近更新 更多