Guy G
Guy G

Reputation: 375

D3 Convention for (re)drawing a single object

I'm using D3 to draw a custom graphs with a border rectangle around it. On window resize, I recalculate the SVG size and want to redraw this border. I'm currently doing this in a drawGraph() function which gets called on resize / new data:

...
svg.selectAll('rect')
     .data([true])
     .attr('width', w)
     .attr('height', h)
     .enter()
     .append('rect')
     .attr('x', 0)
     .attr('y', 0)
     .attr('width', w)
     .attr('height', h)
     .style('fill', 'none')
...

i.e. - I am binding a single value in an array ([true]) to the selection so that I can either draw the box, or just change its size if it's already been drawn once. It certainly works, but it feels slightly odd to bind data which is guaranteed to be ignored, and possibly a slightly hacky way of doing things.

Is this a well-used convention, or is there another standard way of doing this, such as:

Upvotes: 1

Views: 169

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102188

Removing and redrawing elements is what I call lazy coding or lazy update in D3.

That being said, why don't you simply assign the rectangle to a variable and change it on resize? Something like this (click "full page" and resize the window):

var div = document.getElementById("div");
var svg = d3.select("svg")
var rect = svg.append("rect")//here you define your rectangle
  .attr("width", 300)
  .attr("height", 150)
  .attr("stroke-width", 3)
  .attr("stroke", "black")
  .attr("fill", "none");

function resize() {
  var width = div.clientWidth;

  svg.attr("width", width)
    .attr("height", width / 2);
  
  //here you just change its width and height
  rect.attr("width", width)
    .attr("height", width / 2);
}

window.addEventListener("resize", resize);
svg {
  background-color: tan;
}
<script src="//d3js.org/d3.v4.min.js"></script>
<div id="div">
  <svg></svg>
</div>

Upvotes: 1

Related Questions