Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding dc.js to Google Maps with crossfilter

Question: The gist being, can anyone provide a toy example using dc.js + google maps where when I brush on a dc.js chart, the map's markers are updated according to what is selected/brushed in the chart?

What I have so far: pages.github. The full repo is here. I also found this cool snack dashboard example, but this uses leaflet. I was trying to avoid leaflet if possible.

I am trying to bind dc.js (crossfilter) to Google Maps. I have seen this video and I am able to to adapt the example.

However, when I attempt to adapt this to use dc.js I am unable to bind crossfilter back to Google Maps. (I can still bind the map to crossfilter/dc.js, just not the other way around). That is, when scrolling on the map, the charts adjust, but when I brush the charts, I cannot seem to get my updateMarkers() function to fire.

function init() {
  initMap();
  initCrossFilter();

  // bind map bounds to lat/lng ndx dimensions
  latDim = ndx.dimension(function(p) { return p.lat; });
  lngDim = ndx.dimension(function(p) { return p.lng; });
  google.maps.event.addListener(map, 'bounds_changed', function() {
    var bounds = this.getBounds();
    var northEast = bounds.getNorthEast();
    var southWest = bounds.getSouthWest();

    // NOTE: need to be careful with the dateline here
    lngDim.filterRange([southWest.lng(), northEast.lng()]);
    latDim.filterRange([southWest.lat(), northEast.lat()]);

    // NOTE: may want to debounce here, perhaps on requestAnimationFrame
    dc.renderAll();
  });

  // dimension and group for looking up currently selected markers
  idDim = ndx.dimension(function(p, i) { return i; });
  idGroup = idDim.group(function(id) { return id; });

  renderAll();
}

function updateMarkers() {
  var pointIds = idGroup.all();
  for (var i = 0; i < pointIds.length; i++) {
    var pointId = pointIds[i];
    markers[pointId.key].setVisible(pointId.value > 0);
  }
}

function renderAll() {
  updateMarkers();
  dc.renderAll();
}
like image 267
JasonAizkalns Avatar asked Nov 11 '22 00:11

JasonAizkalns


1 Answers

It looks like you are missing the callback from dc.js back into the Google Maps. In the original example, they were using

domCharts = d3.selectAll(".chart")
      .data(charts)
      .each(function(chart) { chart.on("brush", renderAll).on("brushend", renderAll); });

which may or may not work with dc.js.

Although there are other ways to do it, the most idiomatic way to attach a non-dc.js chart to a set of dc.js charts is to register it in the chart registry.

Unfortunately this is undocumented, but take a look at this SO answer, along with the helpful comments that were added to it, to learn how to register your Google Map to hear the render events from the other charts when they are brushed:

dc.js - Listening for chart group render

like image 185
Gordon Avatar answered Nov 14 '22 21:11

Gordon