From dd34d5bedaced602446ac2ea761ef88a45335113 Mon Sep 17 00:00:00 2001 From: Matt Huntington Date: Tue, 19 Sep 2017 21:41:37 -0400 Subject: [PATCH] Avoid redrawing entire screen during render --- BUILD.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/BUILD.md b/BUILD.md index 5eb16cd..f2610d4 100644 --- a/BUILD.md +++ b/BUILD.md @@ -22,6 +22,7 @@ 1. Create a zoom behavior that scales elements 1. Update axes when zooming 1. Update click points after a transform +1. Avoid redrawing entire screen during render ## Add link to d3 library @@ -718,3 +719,51 @@ if(lastTransform !== null){ y = lastTransform.invertY(d3.event.offsetY); } ``` + +## Avoid redrawing entire screen during render + +- At the moment, we wipe all `` elements in the `` each time we call `render()` + - This is inefficient. Let's just remove the ones we don't want +- We'll use `.exit()` to find the selection of circles that haven't been matched with data + - then we'll use `.remove()` to remove those circles + +```javascript +d3.select('#points').selectAll('circle') + .data(runs) + .enter() + .append('circle'); + +d3.selectAll('circle').exit().remove(); //remove all circles not associated with data + +d3.selectAll('circle') + .attr('cy', function(datum, index){ + return yScale(datum.distance); + }); + +d3.selectAll('circle') + .attr('cx', function(datum, index){ + return xScale(parseTime(datum.date)); + }); +``` + +- This can cause weird side effects, because some circles are being reassigned to a different set of data + - if we remove a piece of data in the center of the array, the `` in the the DOM that was assigned to it gets reassigned to the piece of data that used to be assigned to the next sibling `` in the DOM. Each `` gets reassigned over one space from there on out + - to avoid these affects, we need to make sure that each circle stays with the data it used to be assigned to + - to do this, we can tell D3 to map `` to datum by id, rather than index in the array + +```javascript +var circles = d3.select('#points').selectAll('circle').data(runs, function(datum){ //when redrawing circles, make sure pre-existing circles match with their old data + return datum.id +}); + +circles.enter() + .append('circle') + .attr('cy', function(datum, index){ + return yScale(datum.distance); + }) + .attr('cx', function(datum, index){ + return xScale(parseTime(datum.date)); + }); + +circles.exit().remove(); +```