Accepted answer

I couldn't get this working with animated transitions, because there is something I am missing about how to interrupt transitions, and the original dc.scatterPlot is already applying opacity transitions.

So, to start off, let's turn transitions on the original scatter plot:


We also need to add Z to the input data for the scatter plot. Although it would make more sense to add it to the value, it's easy to add it to the key (and the scatter plot will ignore extra elements in the key):

        dim1 = ndx.dimension(function (d) {
            return [d.x, d.y, d.z];

Then we can add a handler to to the scatter plot to apply opacity to the dots, based on the range of the filter in the bar chart:

    chart1.on('pretransition', function(chart) {
      var range = chart2.filter(); // 1
      console.assert(!range || range.filterType==='RangedFilter'); // 2
      var mid, div; // 3
      if(range) {
        mid = (range[0] + range[1])/2;
        div = (range[1] - range[0])/2;
      chart1.selectAll('path.symbol') // 4
        .attr('opacity', function(d) {
          if(range) { // 5
            if(d.key[2] < range[0] || range[1] < d.key[2]) 
                op = 0; // 6
                op = 1 - Math.abs(d.key[2] - mid)/div; // 7
            //console.log(mid, div, d.key[2], op);
            return op;
          else return 1;

  1. Get the current brush/filter from the bar chart
  2. It should either be null or it should be a RangedFilter
  3. Find the midpoint and the distance from the midpoint to the edges of the brush
  4. Now apply opacity to all symbols in the scatter plot
  5. If there is an active brush, apply opacity (otherwise 1)
  6. If the symbol is outside the brush, opacity is 0
  7. Otherwise the opacity is linear based on the distance from the midpoint

You could probably use d3.ease to map the distance [0,1] to opacity [0,1] using a curve instead of linearly. This might be nice so that it emphasizes the points closer to the midpoint

This demo is not all that cool because the data is purely random, but it shows the idea:

scatter with opacity based on range

EDIT: alright, it's a total abuse of dc.js, but if you really want to use it without filtering, and displaying the excluded points in grey, you can do that too.

This will disable filtering on the bar chart:

    chart2.filterHandler(function(_, filters) { return filters; });

Then apply opacity and color to the scatter plot like this instead:

        .attr('opacity', function(d) {
          if(range && range.isFiltered(d.key[2]))
                return 1 - Math.abs(d.key[2] - mid)/div;
          else return 1;
        .attr('fill', function(d) {
          if(!range || range.isFiltered(d.key[2]))
                return chart1.getColor(d);
          else return '#ccc';

With this data it's tricky to see the difference between the light blue dots and the grey dots. Maybe it will work better with non-random data, maybe not. Maybe another color will help.

no filtering just brushing Again, you might as well use straight D3, since this disables most of what dc.js and crossfilter do. But you'd have to start from scratch to ask that question.

Updated fiddle.

EDIT 2: sort the dots by filteredness like this:

        .sort(function(d) {
          return range && range.isFiltered(d.key[2]) ? 1 : 0;

with sorting

Fiddle 3

Related Query

More Query from same tag