d3 treemap dynamic data not adjusting cell width/height

不羁岁月 提交于 2019-12-12 05:20:00

问题


I have a treemap (simple) to which I want to add a new element (see DS0 and DS1 in the code below). I don't want to re-create the whole treemap, instead I want to "update" the data. Sticky is false update section adjusts the g transform (OK) update section adjusts the contained rect width/height (not OK)

  • with devmode off (chrome) the rects width/heights are not being updated (looks like the d.x and d.y values are the old values - can be seen with the cosnole.log statements)
  • with devmode on (chrome) the 'debugger' statements kick in, and if I step through, the some width values update OK.

I can't see why this is not updating properly, but I can make a few observations. It appears that the data binding to the <g>, <rect> and <text> elements is not being adjusted when new data comes in. certainly the <text> data remains 'old'.

Perhaps the only intended way to do this is to re-create the whole SVG again? 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>

回答1:


This code:

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

Means you are only handling the enter selection for the text elements. The code above it:

updates.selectAll("rect")

Is handling the update selection for the rects (and you need something like it for the text elements).

Let's take a step back and try to clean this up a bit (untested code):

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


来源:https://stackoverflow.com/questions/35848237/d3-treemap-dynamic-data-not-adjusting-cell-width-height

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!