5

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();
}
JasonAizkalns
  • 20,243
  • 8
  • 57
  • 116
  • Great idea. Can you produce a jsfiddle or similar, for us to see what you've got so far? Note there is also [dc.leaflet.js](https://github.com/yurukov/dc.leaflet.js) in development. – Gordon Oct 18 '14 at 04:17
  • I posted what I have on: [pages.github](http://jaysunice3401.github.io/dc.js-with-Google-Maps/). The full repo is [here](https://github.com/jaysunice3401/dc.js-with-Google-Maps/tree/master). I also found this cool [snack dashboard](http://jeroenooms.github.io/dashboard/snack/) example, but this uses leaflet. I was trying to avoid leaflet if possible. – JasonAizkalns Oct 20 '14 at 19:27

2 Answers2

1

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

Community
  • 1
  • 1
Gordon
  • 19,811
  • 4
  • 36
  • 74
0

Try fetching the root element with chart.root() and then attach the listener:

domCharts = d3.selectAll(".chart")
  .data(charts)
  .each(function(chart) {
    chart.root().on(event, updateMarkers)
});

Though I'm not yet aware if this approach is optimal or causes any side effects.

Viktor
  • 257
  • 1
  • 5