mapsense / mapsense.js

Mapsense.js
Other
88 stars 22 forks source link

data(), key(), enter(), exit() #22

Open sttawm opened 9 years ago

sttawm commented 9 years ago

I've been thinking a bit about the heat-map (AKA gridded binning) problem and the steps necessary to enable heat-map updates in response to filtering. Generating contour lines also come to mind (essentially, any visualization of derived data does).

I've been playing with the idea of adding a few functions:

var layer = mapsense.geojson(); // or .topojson();

/**
  * Derive new features from the fetched and cached features, 
  * re-bind them with the feature selections, 
  * and trigger all subsequent processing.
  */ 
layer.data(function([features]) { });

/**
 * Defines the d3 key function to be used with .data()
 */
layer.key(function(feature) { return feature.id });

/**
  * Set the enter method to be invoked for each enter-selection.
  */
layer.enter(function(enterSelection) { });

/**
  * Set the exit method to be invoked for each exit-selection.
  */
layer.exit(function(exitSelection) { exitSelection.remove(); });

/**
 * Set the update method to be invoked for each update-selection, and immediately invoke it on the current selection. 
 * This is equivalent to .selection(), but instead uses d3's naming convention, to 
 * parallel the .enter() and .exit() functions.
 */ 
layer.update(function(updateSelection) { });

It'd probably also make sense to allow these functions to optionally take the tile as an argument.

Note that, today, selection(...) would be equivalent to (an alias of?) update(...). We may prefer a sort of "preUpdate" selection (to gain access to those elements that were bound to data both before and after .data())

This would allow us, in response to a new filter, to do something like:

var filter = function(f) { return f.properties.population > 5; };
geojson.data(function(features, tile) {
   return binCounts(tile, features.filter(filter)); // returns polygons
});

To get a sense of what it might look like, and to better explain myself, I have an (incomplete) commit. (Before digging into how to re-trigger the "draw()" function I'd like to make sure this is something we actually want.)