1

I would like my heatmap to react the same way if the date on the heatmap's x asis is selected or if the date is selected from the yearSlicer (rowChart)

I've tried using these posts:

Is there a way to set a default color for the un-selected boxes in heatmap in dc.js when crossfilter is applied?

dc.js heatmap deselected colors

.colors function in barChart dc.js with only two options

Trying to Assign Color for Null values in a map D3,js v4

yearSlicer(rowChart):

var yearSlicerDimension = ndx.dimension(function (d) {
                    return "" + d.Year;
                })
                yearSlicerGroup = yearSlicerDimension.group().reduceSum(function (d) {
                    return d.FTE;
                });

                yearSlicer
                    .title("")
                    .width(300)
                    .height(480)
                    .dimension(yearSlicerDimension)
                    .group(yearSlicerGroup)
                    .valueAccessor(function (kv) {
                        return kv.value > 0 ? 1 : 0; // If funtion to detect 0's
                    })
                    .ordering(function (d) { return -d.Year })
                    .xAxis().ticks(0)

Heat Map:

 var dimension = ndx.dimension(function (d) { return [d.Year, d["Manager"]]; }),

                    FTEMonthGroup = dimension.group().reduce(

                        function reduceAdd(p, v) {
                            if (p.n === 0) {
                                p.color = 0;
                                p.toolTip = 0;
                            }
                            ++p.n;
                            p.color += v.FTE;
                            p.toolTip += v.FTE;
                            return p;
                        },

                        function reduceRemove(p, v) {
                            --p.n;
                            p.color = "null";
                            return p;
                        },

                        function reduceInitial() {
                            return { n: 0, color: 0, toolTip: 0 };
                        });

                heatMap
                    .width(900)
                    .height(800)
                    .dimension(dimension)
                    .group(FTEMonthGroup)
                    .margins({ left: 200, top: 30, right: 10, bottom: 20 })
                    .keyAccessor(function (d) { return d.key[0]; })
                    .valueAccessor(function (d) { return +d.key[1]; })
                    .colorAccessor(function (d) { return +d.value.color; })
                    .title(function (d) {
                        return "Manager:   " + d.key[1] + "\n" +
                            "FTE:  " + d.value.toolTip + "\n" +
                            "Date: " + d.key[0] + "";
                    })
                    .calculateColorDomain()
                    .on('renderlet', function (chart) {
                        chart.selectAll("g.cols.axis text")
                            .attr("transform", function () {
                                var coord = this.getBBox();
                                var x = coord.x + (coord.width / 2),
                                    y = coord.y + (coord.height / 2);
                                return "rotate(-45 " + x + " " + y + ")"

                            })
                    });

What I would like:

expectation

What I get:

reality

Gordon
  • 19,811
  • 4
  • 36
  • 74
M_M
  • 173
  • 8

1 Answers1

1

Right now it looks like your color accessor will return NaN for any bin which has anything removed from it, because

+"null" === NaN

Note that

+null === 0

but we don't necessarily want that, because we want an exceptional color for bins that had everything removed, not "the zero color".

It would be easier to try it out if you included a fiddle or something, but I think you should be able to get there with the following changes:

Properly null out your color when n goes to zero:

                    function reduceAdd(p, v) {
                        ++p.n;
                        p.color += v.FTE;
                        p.toolTip += v.FTE;
                        return p;
                    },

                    function reduceRemove(p, v) {
                        --p.n;
                        if (p.n === 0) {
                            p.color = null;
                            p.toolTip = null;
                        }
                        return p;
                    },

We only need to check on remove, not on add, because n never goes to zero on add, by definition. It's okay to pair = null with += v.FTE because if you use += on a variable that contains null, it will get automatically coerced to 0 (unlike undefined which will go to NaN).

Use a color calculator to detect null and produce gray

Use the recently un-deprecated colorCalculator to detect nulls and use the gray of our choosing for them. Otherwise we pass the color through the color scale as usual:

heatMap
    .colorCalculator(function(d, i) {
        return d.value.color === null ?
            '#ccc' : heatMap.colors()(d.value.color);
    });       

Note that internally, dc.js charts use the .selected and .deselected classes to show which items are selected by the brush and which are not, but that would be complicated here (especially if you still want the brush to work), so it's easier just to use the same color.

Again, this is all untested, but I think it's the right principle. Lmk if there are any issues and I'll be glad to fix it.

alternately... scale.unknown()?

It may also be possible to use scale.unknown() for this purpose, but it is brand-new to D3 5.8 and I haven't tried it. Something like

heatMap.colors().unknown('#ccc')
Gordon
  • 19,811
  • 4
  • 36
  • 74