maxko87
maxko87

Reputation: 2940

d3 Dynamically Updating Treemap

I'm trying to update elements in the treemap:

    drawTreeMap = (data) ->
      margin =
        top: 0
        right: 0
        bottom: 0
        left: 0

      width = window.innerWidth
      height = window.innerHeight
      color = d3.scale.category20c()

      treemap = d3.layout.treemap().size([width, height]).sticky(true).value((d) -> d.size)

      div = d3.select("body").append("div")
        .style("position", "relative")
        .style("width", (width + margin.left + margin.right) + "px")
        .style("height", (height + margin.top + margin.bottom) + "px")
        .style("left", margin.left + "px")
        .style("top", margin.top + "px")

      node = div.datum(data).selectAll(".node")
          .data(treemap.nodes)

      node.enter()
          .append("div")
            .attr("class", "node")
            .call(position)
            .style("background", (d) -> (if d.children then color(d.name) else null))
            .on "click", ->
              el = d3.select(this)
              data = el[0][0].__data__
              while (data.parent.parent)
                data = data.parent
              console.log("updated to data:")
              console.log(data)
              drawTreeMap(data)
              #updateTreemap(div, treemap, data)

      node.exit()
        .remove()

      node.transition().duration(1500).call position

data is what I want it to be in the console.log statement, but the treemap isn't getting updated. Most of the code is directly from the treemap example.

Upvotes: 1

Views: 1283

Answers (1)

meetamit
meetamit

Reputation: 25157

Like Lars points out, you're creating a new div (the one assigned to var div) every time you call drawTreeMap(). For starters, you need to either simply move that div creation outside of drawTreeMap so that it only runs once. Or, if you want to get fancy, you could leave the creation inside the function, but do something like this:

div = d3.select("body").selectAll("div.treemap-container").data([null])
div.enter()
  .append('div')// only creates the div the first time this runs
  .attr('class', 'treemap-container')
  // etc...

That's the only odd thing I can see. Maybe there's another bug, but it's hard to track down without a working jsFiddle. If you can provide one, post a comment here and I'll take a look further.

As an aside, for style, rather than doing this: data = el[0][0].__data__, you should just do this: data = el.datum()

Finally, note that you're not using a key function for the data binding, so even if you get the treemap to re-render, there would be no object persistence (i.e. existing divs could get reassigned to a different data point arbitrarily).

Upvotes: 1

Related Questions