The root problem here is that your svg variable is not assigned the choice of the <svg> element, which is assigned the final result of calls with chain calls, the first round of which is the <g> element, and after that is empty, because there is no 'enter' choice .
So the first thing to do is change to
var svg = container.select(".svg-container").selectAll('svg').data([0]);
At the first run, the update selection will be empty, and the input selection will contain one element. Then you bind this to the new <svg> element:
svg.enter() .append("svg") .append("g") // note that from this point you're setting attributes on the <g>, not the <svg> .attr("class", "canvas") .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
This add operation adds an item to the update selection stored in svg .
When resizing, the input selection will be empty, but the update selection in svg will already contain the existing <svg> element. One way or another, at this point you can set attributes in svg selection - it will work for both cases.
svg.attr("width", drawWidth) .attr("height", drawHeight);
Updated fiddle http://jsfiddle.net/3dgn5pz8/5/
source share