UNPKG

@antv/g2plot

Version:

G2 Plot, a market of plots built with the Grammar of Graphics'

201 lines 7.96 kB
import { __assign, __extends } from "tslib"; import { registerElement, Element } from '@antv/g2'; import * as _ from '@antv/util'; import * as colorUtil from '../../util/color'; var GAUSS_COEF = 0.3989422804014327; var ZERO = 1.0 / 255.0 / 16.0; var ORIGIN_FIELD = '_origin'; var SHADOW_CANVAS = 'shadowCanvas'; var VALUE_RANGE = 'valueRange'; var IMAGE_SHAPE = 'imageShape'; var MAPPED_DATA = 'mappedData'; var GRAY_SCALE_BLURRED_CANVAS = 'grayScaleBlurredCanvas'; var HEATMAP_SIZE = 'heatmapSize'; var LinearHeatmap = /** @class */ (function (_super) { __extends(LinearHeatmap, _super); function LinearHeatmap(cfg) { return _super.call(this, __assign({ type: 'linearHeatmap', shapeType: 'point', paletteCache: {} }, cfg)) || this; } LinearHeatmap.prototype._prepareRange = function () { var data = this.get(MAPPED_DATA); var colorAttr = this.getAttr('color'); var colorField = colorAttr.scales[0].field; var min = Infinity; var max = -Infinity; data.forEach(function (row) { var value = row[ORIGIN_FIELD][colorField]; if (value > max) { max = value; } if (value < min) { min = value; } }); if (min === max) { min = max - 1; } var range = [min, max]; this.set(VALUE_RANGE, range); }; LinearHeatmap.prototype._prepareSize = function () { var radius; if (this.get('radius')) { radius = this.get('radius'); } else { radius = this.getDefaultValue('size'); if (!_.isNumber(radius)) { radius = this.getDefaultSize(); } } var styleOptions = this.get('styleOptions'); var blur = styleOptions && _.isObject(styleOptions.cfg) ? styleOptions.cfg.blur : null; if (!_.isFinite(blur) || blur === null) { blur = radius / 2; } this.set(HEATMAP_SIZE, { blur: blur, radius: radius, }); }; LinearHeatmap.prototype.getDefaultSize = function () { var position = this.getAttr('position'); var coord = this.get('coord'); var radius = Math.min(coord.width / (position.scales[0].ticks.length * 4), coord.height / (position.scales[1].ticks.length * 4)); return radius; }; LinearHeatmap.prototype._colorize = function (img) { var colorAttr = this.getAttr('color'); var pixels = img.data; var paletteCache = this.get('paletteCache'); for (var i = 3; i < pixels.length; i += 4) { var alpha = pixels[i]; // get gradient color from opacity value if (alpha) { var palette = void 0; if (paletteCache[alpha]) { palette = paletteCache[alpha]; } else { palette = colorUtil.rgb2arr(colorAttr.gradient(alpha / 256)); paletteCache[alpha] = palette; } // const palette = colorUtil.rgb2arr(colorAttr.gradient(alpha / 256)); pixels[i - 3] = palette[0]; pixels[i - 2] = palette[1]; pixels[i - 1] = palette[2]; pixels[i] = alpha; } } }; LinearHeatmap.prototype._prepareGreyScaleBlurredCircle = function (r) { var circleCanvas = this.get(GRAY_SCALE_BLURRED_CANVAS); if (!circleCanvas) { circleCanvas = document.createElement('canvas'); this.set(GRAY_SCALE_BLURRED_CANVAS, circleCanvas); } var intensity = this.get('intensity') ? this.get('intensity') : 2; var circleRadius = (Math.sqrt(-2.0 * Math.log(ZERO / r / intensity / GAUSS_COEF)) / 3.0) * r; var blur = circleRadius - r; var r2 = circleRadius + blur; var ctx = circleCanvas.getContext('2d'); circleCanvas.width = circleCanvas.height = r2 * 2; ctx.clearRect(0, 0, circleCanvas.width, circleCanvas.height); ctx.shadowOffsetX = ctx.shadowOffsetY = r2 * 2; ctx.shadowBlur = blur; ctx.shadowColor = 'black'; ctx.beginPath(); ctx.arc(-r2, -r2, r, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); }; LinearHeatmap.prototype._drawGrayScaleBlurredCircle = function (x, y, r, alpha, ctx) { var circleCanvas = this.get(GRAY_SCALE_BLURRED_CANVAS); ctx.globalAlpha = alpha; ctx.drawImage(circleCanvas, x - r, y - r); }; LinearHeatmap.prototype._getShadowCanvasCtx = function () { var canvas = this.get(SHADOW_CANVAS); if (!canvas) { canvas = document.createElement('canvas'); this.set(SHADOW_CANVAS, canvas); } var viewRange = this.get('view').get('panelRange'); canvas.width = viewRange.width; canvas.height = viewRange.height; var context = canvas.getContext('2d'); context.globalCompositeOperation = 'lighter'; return context; }; LinearHeatmap.prototype._clearShadowCanvasCtx = function () { var ctx = this._getShadowCanvasCtx(); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); }; LinearHeatmap.prototype._getImageShape = function () { var imageShape = this.get(IMAGE_SHAPE); if (imageShape) { return imageShape; } var container = this.get('container'); imageShape = container.addShape('Image', {}); this.set(IMAGE_SHAPE, imageShape); return imageShape; }; LinearHeatmap.prototype.clear = function () { this._clearShadowCanvasCtx(); _super.prototype.clear.call(this); }; LinearHeatmap.prototype.drawWithRange = function (range) { // canvas size var _a = this.get('coord'), start = _a.start, end = _a.end, width = _a.width, height = _a.height; // value, range, etc // const valueField = this.getAttr('color').field; var valueField = this.getAttr('color').scales[0].field; var size = this.get(HEATMAP_SIZE); // prepare shadow canvas context this._clearShadowCanvasCtx(); var ctx = this._getShadowCanvasCtx(); // filter data var data = this.get(MAPPED_DATA); if (range) { data = data.filter(function (row) { return row[ORIGIN_FIELD][valueField] <= range[1] && row[ORIGIN_FIELD][valueField] >= range[0]; }); } // step1. draw points with shadow var scale = this.get('scales')[valueField]; for (var i = 0; i < data.length; i++) { var obj = data[i]; var cfg = this.getDrawCfg(obj); var alpha = scale.scale(obj[ORIGIN_FIELD][valueField]); // @ts-ignore this._drawGrayScaleBlurredCircle(cfg.x - start.x, cfg.y - end.y, size.radius + size.blur, alpha, ctx); } // step2. convert pixels var colored = ctx.getImageData(0, 0, width, height); this._clearShadowCanvasCtx(); this._colorize(colored); ctx.putImageData(colored, 0, 0); var image = new Image(); image.src = ctx.canvas.toDataURL('image/png'); var imageShape = this._getImageShape(); imageShape.attr({ x: start.x, y: end.y, width: width, height: height, img: image, }); }; LinearHeatmap.prototype.draw = function (data) { this.set(MAPPED_DATA, data); this._prepareRange(); this._prepareSize(); var size = this.get(HEATMAP_SIZE); this._prepareGreyScaleBlurredCircle(size.radius); var range = this.get(VALUE_RANGE); this.drawWithRange(range); }; return LinearHeatmap; }(Element)); registerElement('linearHeatmap', LinearHeatmap); //# sourceMappingURL=linear.js.map