UNPKG

@antv/g2

Version:

the Grammar of Graphics in Javascript

126 lines 4.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HeatmapRenderer = void 0; const lru_1 = require("../../../utils/lru"); const gradient_1 = require("./gradient"); function newCanvas(createCanvas, width, height) { const c = createCanvas ? createCanvas() : document.createElement('canvas'); c.width = width; c.height = height; return c; } /** * Get a point with template. * @param radius * @param blurFactor * @returns */ const getPointTemplate = (0, lru_1.lru)((radius, blurFactor, createCanvas) => { const tplCanvas = newCanvas(createCanvas, radius * 2, radius * 2); const tplCtx = tplCanvas.getContext('2d'); const x = radius; const y = radius; if (blurFactor === 1) { tplCtx.beginPath(); tplCtx.arc(x, y, radius, 0, 2 * Math.PI, false); tplCtx.fillStyle = 'rgba(0,0,0,1)'; tplCtx.fill(); } else { const gradient = tplCtx.createRadialGradient(x, y, radius * blurFactor, x, y, radius); gradient.addColorStop(0, 'rgba(0,0,0,1)'); gradient.addColorStop(1, 'rgba(0,0,0,0)'); tplCtx.fillStyle = gradient; tplCtx.fillRect(0, 0, 2 * radius, 2 * radius); } return tplCanvas; }, (radius) => `${radius}`); /** * Get a color palette with len = 256 base on gradient. * @param gradientConfig * @returns */ function getColorPalette(gradientConfig, createCanvas) { const paletteCanvas = newCanvas(createCanvas, 256, 1); const paletteCtx = paletteCanvas.getContext('2d'); const gradient = paletteCtx.createLinearGradient(0, 0, 256, 1); (0, gradient_1.parseGradient)(gradientConfig).forEach(([r, c]) => { gradient.addColorStop(r, c); }); paletteCtx.fillStyle = gradient; paletteCtx.fillRect(0, 0, 256, 1); return paletteCtx.getImageData(0, 0, 256, 1).data; } /** * Draw all circle with alpha. */ function drawAlpha(shadowCtx, min, max, data, options, createCanvas) { const { blur } = options; let len = data.length; while (len--) { const { x, y, value: v, radius } = data[len]; // Ff value is bigger than max, use max as value. const value = Math.min(v, max); const rectX = x - radius; const rectY = y - radius; const tpl = getPointTemplate(radius, 1 - blur, createCanvas); // Value from minimum / value range, => [0, 1]. const templateAlpha = (value - min) / (max - min); // Small values are not visible because globalAlpha < .001 cannot be read from imageData. shadowCtx.globalAlpha = Math.max(templateAlpha, 0.001); shadowCtx.drawImage(tpl, rectX, rectY); } return shadowCtx; } function colorize(shadowCtx, maxWidth, maxHeight, palette, options) { const { minOpacity, opacity, maxOpacity, useGradientOpacity } = options; const x = 0; const y = 0; const width = maxWidth; const height = maxHeight; const img = shadowCtx.getImageData(x, y, width, height); const imgData = img.data; const len = imgData.length; for (let i = 3; i < len; i += 4) { const alpha = imgData[i]; const offset = alpha * 4; if (!offset) { continue; } // Should be in [min, max], min >= 0. const finalAlpha = opacity || Math.max(0, Math.min(maxOpacity, Math.max(minOpacity, alpha))); // Update rgba. imgData[i - 3] = palette[offset]; imgData[i - 2] = palette[offset + 1]; imgData[i - 1] = palette[offset + 2]; imgData[i] = useGradientOpacity ? palette[offset + 3] : finalAlpha; } return img; } /** * Render a heatmap with canvas. * See [heatmap.js](https://github.com/pa7/heatmap.js/blob/master/src/renderer/canvas2d.js). */ function HeatmapRenderer(width, height, min, max, data, options, createCanvas) { const opts = Object.assign({ blur: 0.85, minOpacity: 0, opacity: 0.6, maxOpacity: 1, gradient: [ [0.25, 'rgb(0,0,255)'], [0.55, 'rgb(0,255,0)'], [0.85, 'yellow'], [1.0, 'rgb(255,0,0)'], ] }, options); opts.minOpacity *= 255; opts.opacity *= 255; opts.maxOpacity *= 255; const shadowCanvas = newCanvas(createCanvas, width, height); const shadowCtx = shadowCanvas.getContext('2d'); const palette = getColorPalette(opts.gradient, createCanvas); shadowCtx.clearRect(0, 0, width, height); drawAlpha(shadowCtx, min, max, data, opts, createCanvas); const img = colorize(shadowCtx, width, height, palette, opts); const canvas = newCanvas(createCanvas, width, height); const ctx = canvas.getContext('2d'); ctx.putImageData(img, 0, 0); return ctx; } exports.HeatmapRenderer = HeatmapRenderer; //# sourceMappingURL=index.js.map