A Short Note on Making Your d3.js Viz Responsive

OK - this seems to work, and I wanted to make a note of it. It's not a new thing, but might save you some time when you need to do the same thing.

The basic thing we want to do is re-render a d3.js graph after a user has resized their browser window.

With this approach, on a window resize we reconstruct everything svg-related from scratch. This might not be feasible in your case, but otherwise it can be more involved and it is easy to miss something.

We also use David Walsh's "debounce" plugin that can be used to throttle how often you try to rerender while the user is still resizing. There might be a better way to tell when a user is "done resizing" - please let me know how: it doesn't affect the core idea here, just how often you call the "rebuild from scratch" method.

So, so here is one way that works (even when you change your iPhone from portrait to landscape - sweet yay):

  • Set up debounce when the page loads, via
    
        window.addEventListener('resize', debouncedResize);
    
  • Set up your "debouncedResize" method (this is using a delay of 250ms before calling the rerender)
    
    var debouncedResize = debounce(function() {yourRerenderAfterResizeMethod();},
                                    250);
    
  • Set up your rerender method (it might be a method on another object or whatever)
    
    function yourRerenderAfterResizeMethod() {
    
    //destroy existing svg elements
    d3.select('#idOfYourSvgElementToReconstruct').selectAll('*').remove()
    
    // ... other svg elements you will rebuilding
    
    //make sure you don't have straggler object properties hanging around that are used
    //  when rendering (this bit me once - I was trying to add svg elements to an empty thing, and
    //  all actions were silently ignored)
    
    //Now go to town and build all of your svg stuff, 
    // taking into account the new screen size.
    //Note that I have found (so far) that it seems best 
    // to set the width/height attributes of the svg elements so that
    //  when the user is resizing (and before the rerender is called), 
    //  things don't scale crazy. YMMV.
    
    }
    

From my experience so far, you can prevent potential inadvertent transient wacky scaling while the user is resizing by explicitly setting the width/height of the relevant svg elements. This might only matter when the enclosing element has a width set to 100% of the parent, but the jankiness until the rerender is called can be distracting otherwise.

Popular Posts