public render()

in src/UXClient/Components/HeatmapCanvas/HeatmapCanvas.ts [139:258]


    public render (data, chartOptions, aggKey, highlightedSplitBy: string = null, highlightedTime: Date = null, onCellFocus, aggI: number, isOnlyAgg: boolean) {
        this.chartOptions.setOptions(chartOptions);
        this.aggKey = aggKey;
        this.data = data;
        this.isOnlyAgg = isOnlyAgg;

        if (aggI != null) {
            this.aggI = aggI;
        }

        this.heatmapData = new HeatmapData(data, aggKey);
        var container = d3.select(this.renderTarget).classed("tsi-heatmapCanvasWrapper", true);
        super.themify(container, this.chartOptions.theme);

        if (highlightedSplitBy != null) 
            this.highlightedSplitBy = highlightedSplitBy; 
        this.highlightedTime = highlightedTime;
    
        if (this.highlightedSplitBy != null && this.highlightedTime) {
            if (this.heatmapData.timeValues[this.highlightedTime.toISOString()][this.highlightedSplitBy] != null) {
                this.highlightedValue = this.heatmapData.timeValues[this.highlightedTime.toISOString()][this.highlightedSplitBy].value;
            }
        }

        if (onCellFocus)
            this.onCellFocus = onCellFocus;

        if (!container.select("canvas").empty()) 
            this.canvas = container.select("canvas");
        else 
            this.canvas = container.append("canvas").attr("class", "tsi-heatmapCanvas");   

        this.width = Math.floor(container.node().getBoundingClientRect().width - this.legendWidth - 10);
        this.height = Math.floor(container.node().getBoundingClientRect().height);
        this.canvas.attr("width", this.width);
        this.canvas.attr("height", this.height);

        this.ctx = this.canvas.node().getContext("2d");
        this.ctx.clearRect(0,0, this.width, this.height);
        
        container.selectAll("svg").remove();
        var self = this;
        this.canvas.on("mousemove", function () {
            var mouseCoords = d3.mouse(this);
            var indexesChanged = false;
            var newXIndex = self.calcCellXIndex(mouseCoords[0]);
            var newYIndex = self.calcCellYIndex(mouseCoords[1]);
            var visibleSplitBys = Object.keys(self.data.displayState[aggKey].splitBys).filter((splitBy) => {
                return self.data.isSplitByVisible(self.aggKey, splitBy);
            });
            if (newXIndex != self.focusedXIndex) {
                self.focusedXIndex = newXIndex;
                indexesChanged = true;
            }
            if (newYIndex != self.focusedYIndex) {
                self.focusedYIndex = newYIndex;
                indexesChanged = true;
            }
            var highlightedSplitBy = visibleSplitBys[self.focusedYIndex];
            if (indexesChanged && self.focusedXIndex >= 0 && self.focusedYIndex >= 0) {
                var cellX = self.calcCellX(self.focusedXIndex);
                var sortedDates = Object.keys(self.heatmapData.timeValues)
                    .sort((a: string, b: string): number => {
                        return ((new Date(a)).valueOf() < (new Date(b)).valueOf()) ? -1 : 1;
                    });
                var startDate = new Date(sortedDates[self.focusedXIndex]);
                this.highlightedTime = startDate;
                self.onCellFocus(startDate, new Date(startDate.valueOf() + self.heatmapData.bucketSize), 
                                 Math.max(0, cellX), cellX + self.calcCellWidth(self.focusedXIndex), 
                                 self.calcCellY(self.focusedYIndex), highlightedSplitBy);
            }
            self.render(self.data, self.chartOptions, self.aggKey, highlightedSplitBy, this.highlightedTime, self.onCellFocus, null, self.isOnlyAgg);
        }).on("mouseout", function () {
            self.focusedXIndex = -1;
            self.focusedYIndex = -1;
            self.render(self.data, self.chartOptions, self.aggKey, null, null, self.onCellFocus, null, self.isOnlyAgg);
        })
        this.aggKey = aggKey;

        this.rawCellHeight = Math.floor(this.height / this.heatmapData.numRows);
        this.cellHeightMod = this.height % this.heatmapData.numRows;
        this.rawCellWidth = this.width / this.heatmapData.numCols;
        this.cellWidthMod = this.width % this.heatmapData.numCols;

        
        this.colorLegend = container.append("svg").attr("class", "tsi-heatmapColorLegend")     
        this.colorLegend.attr("width", this.legendWidth)
            .attr("height", this.height)
            .style("left", (this.width) + "px");

        var aggColor = data.displayState[aggKey].color;

        if (isOnlyAgg) {
            this.colorScale = d3.scaleSequential(d3.interpolateViridis).domain(this.getExtent());
        } else {
            this.colorScale = d3.scaleLinear().domain(this.getExtent())
                .range([<any>d3.hcl(aggColor).brighter(), <any>d3.hcl(aggColor).darker()]);
        }

        this.renderScale();

        var sortedTimes = Object.keys(this.heatmapData.timeValues).sort((a: string, b: string): number => {
            return ((new Date(a)).valueOf() < (new Date(b)).valueOf()) ? -1 : 1;
        });

        sortedTimes.forEach((ts, tsI) => {
            Object.keys(this.heatmapData.timeValues[ts]).forEach((splitBy, sBI) => {
                var cellData = this.heatmapData.timeValues[ts][splitBy];
                if (cellData != null) {
                    if (highlightedSplitBy && highlightedSplitBy != splitBy) {
                        this.drawCell(cellData.rowI, cellData.colI, cellData.value, true);
                    } else {
                        this.drawCell(cellData.rowI, cellData.colI, cellData.value);
                    }
                } 
            });
        });

        
    }