// Return with commas in between var numberWithCommas = function (x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }; var helpers = Chart.helpers; Chart.HeatMapPlugin = Chart.PluginBase.extend({ beforeInit: function (chart) { if (chart.config.type === 'heatmap') { // Keep the y-axis in sync with the datasets chart.data.yLabels = chart.data.datasets.map(function (ds) { return ds.label; }); } }, beforeUpdate: function (chart) { if (chart.config.type === 'heatmap') { // Keep the y-axis in sync with the datasets chart.data.yLabels = chart.data.datasets.map(function (ds) { return ds.label; }); } }, }); Chart.plugins.register(new Chart.HeatMapPlugin()); Chart.defaults.heatmap = { radiusScale: 0, paddingScale: 0, colorFunction: function (value, minVal, maxVal, colorScheme) { return getColorForPercentage(value, minVal, maxVal, colorScheme); }, colorGradiant: 'YellowToRed', hover: { mode: 'single' }, legend: { display: false, displayCustom: true, position: 'right', }, scales: { xAxes: [{ type: 'category', position: 'bottom', gridLines: { display: false, offsetGridLines: true, drawBorder: false, drawTicks: false } }], yAxes: [{ type: 'category', position: 'left', gridLines: { display: false, offsetGridLines: true, drawBorder: false, drawTicks: false } }] } }; Chart.controllers.heatmap = Chart.DatasetController.extend({ dataElementType: Chart.elements.Rectangle, minDataSetValue: function (){ var returnValue = 0; var tmpValue = 0; var dataset = this.chart.data.datasets; for (var xx = 0; xx < dataset.length; xx++){ if(xx == 0){ returnValue = Math.min.apply(Math, dataset[xx].data); } else{ tmpValue = Math.min.apply(Math, dataset[xx].data); if (tmpValue < returnValue) { returnValue = tmpValue; } } } return returnValue; }, maxDataSetValue: function () { var returnValue = 0; var tmpValue = 0; var dataset = this.chart.data.datasets; for (var xx = 0; xx < dataset.length; xx++) { if (xx == 0) { returnValue = Math.max.apply(Math, dataset[xx].data); } else { tmpValue = Math.max.apply(Math, dataset[xx].data); if (tmpValue > returnValue) { returnValue = tmpValue; } } } return returnValue; }, update: function (reset) { var me = this; var meta = me.getMeta(); var boxes = meta.data; // Update Boxes helpers.each(boxes, function (box, index) { me.updateElement(box, index, reset); }); }, updateElement: function (box, index) { var me = this; var meta = me.getMeta(); var xScale = me.getScaleForId(meta.xAxisID); var yScale = me.getScaleForId(meta.yAxisID); var dataset = me.getDataset(); var data = dataset.data[index]; var datasetIndex = me.index; var radiusScale = me.chart.options.radiusScale; var paddingScale = me.chart.options.paddingScale; var x = xScale.getPixelForValue(data, index, datasetIndex); var y = yScale.getPixelForValue(data, datasetIndex, datasetIndex); var boxWidth = 0; if (dataset.data.length > 1) { var x0 = xScale.getPixelForValue(dataset.data[0], 0, datasetIndex); var x1 = xScale.getPixelForValue(dataset.data[1], 1, datasetIndex); boxWidth = x1 - x0; } else { boxWidth = xScale.width; } var boxHeight = 0; if (me.chart.data.datasets.length > 1) { // We only support 'category' scales on the y-axis for now boxHeight = yScale.getPixelForValue(null, 1, 1) - yScale.getPixelForValue(null, 0, 0); } else { boxHeight = yScale.height; } // Apply padding var horizontalPadding = paddingScale * boxWidth; var verticalPadding = paddingScale * boxHeight; boxWidth = boxWidth - horizontalPadding; boxHeight = boxHeight - verticalPadding; y = y + verticalPadding / 2; x = x + horizontalPadding / 2; var color = me.chart.options.colorFunction(data, me.minDataSetValue(), me.maxDataSetValue(), me.chart.options.colorGradiant); var cornerRadius = boxWidth * radiusScale; helpers.extend(box, { // Utility _xScale: xScale, _yScale: yScale, _datasetIndex: datasetIndex, _index: index, _data: data, // Desired view properties _model: { // Position x: x + boxWidth / 2, y: y, // Appearance base: y + boxHeight, height: boxHeight, width: boxWidth, backgroundColor: color, cornerRadius: cornerRadius, // Tooltip label: me.chart.data.labels[index], datasetLabel: dataset.label, }, // Override to draw rounded rectangles without any borders draw: function () { var ctx = this._chart.ctx; var vm = this._view; var leftX = vm.x - (vm.width) / 2; ctx.fillStyle = vm.backgroundColor; helpers.drawRoundedRectangle(ctx, leftX, vm.y, vm.width, vm.height, vm.cornerRadius); ctx.fill(); }, // Override to position the tooltip in the center of the box tooltipPosition: function () { var vm = this._view; return { x: vm.x, y: vm.y + vm.height / 2 }; } }); box.pivot(); }, setHoverStyle: function () { // TODO: Implement this }, removeHoverStyle: function () { // TODO: Implement this } }); function getYellowToRedColor(colorSelectionCount, value) { var incroment = 100 / colorSelectionCount; var colorIncroment = 255 / colorSelectionCount; for (var ii = 1; ii <= colorSelectionCount; ii++) { if ((ii * incroment) >= value) { return "rgb(255, " + Math.ceil(255 - (ii * colorIncroment)) + ", 0)"; } } return "rgb(255, 255, 0)"; } function getGreenToBlueColor(colorSelectionCount, value) { var incroment = 100 / colorSelectionCount; var colorIncroment = 255 / colorSelectionCount; for (var ii = 1; ii <= colorSelectionCount; ii++) { if ((ii * incroment) >= value) { return "rgb(0, " + Math.ceil(255 - (ii * colorIncroment)) + ", 255)"; } } return "rgb(0, 255, 255)"; } //sets the chart background to white Chart.plugins.register({ beforeDraw: function (chartInstance) { var ctx = chartInstance.chart.ctx; ctx.fillStyle = "white"; ctx.fillRect(0, 0, chartInstance.chart.width, chartInstance.chart.height); } });