From 51aace033316bf31da12d49f8d0f55f9070f026a Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 15 Nov 2017 16:31:38 -0800 Subject: [PATCH] Fix heatmap layer performance regression --- src/style/properties.js | 26 ++++--------------- src/style/style_layer/heatmap_style_layer.js | 27 +++++++++++++++++--- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/style/properties.js b/src/style/properties.js index a1ce3bab347..4caa6b4eac5 100644 --- a/src/style/properties.js +++ b/src/style/properties.js @@ -3,7 +3,6 @@ const assert = require('assert'); const {extend, easeCubicInOut} = require('../util/util'); const interpolate = require('../style-spec/util/interpolate'); -const {RGBAImage} = require('../util/image'); const {normalizePropertyExpression} = require('../style-spec/expression'); const Color = require('../style-spec/util/color'); @@ -616,35 +615,20 @@ class CrossFadedProperty implements Property> { } /** - * An implementation of `Property` for `heatmap-color`, which has unique evaluation requirements. + * An implementation of `Property` for `heatmap-color`. Evaluation and interpolation are no-ops: the real + * evaluation happens in HeatmapStyleLayer. * * @private */ -class HeatmapColorProperty implements Property { +class HeatmapColorProperty implements Property { specification: StylePropertySpecification; constructor(specification: StylePropertySpecification) { this.specification = specification; } - possiblyEvaluate(value: PropertyValue, parameters: EvaluationParameters): RGBAImage { - const colorRampData = new Uint8Array(256 * 4); - const len = colorRampData.length; - for (let i = 4; i < len; i += 4) { - const pxColor = value.expression.evaluate(extend({heatmapDensity: i / len}, parameters)); - // the colors are being unpremultiplied because Color uses - // premultiplied values, and the Texture class expects unpremultiplied ones - colorRampData[i + 0] = Math.floor(pxColor.r * 255 / pxColor.a); - colorRampData[i + 1] = Math.floor(pxColor.g * 255 / pxColor.a); - colorRampData[i + 2] = Math.floor(pxColor.b * 255 / pxColor.a); - colorRampData[i + 3] = Math.floor(pxColor.a * 255); - } - return RGBAImage.create({width: 256, height: 1}, colorRampData); - } - - interpolate(a: RGBAImage): RGBAImage { - return a; - } + possiblyEvaluate() {} + interpolate() {} } module.exports = { diff --git a/src/style/style_layer/heatmap_style_layer.js b/src/style/style_layer/heatmap_style_layer.js index 7449c2e913b..77a27bcd13b 100644 --- a/src/style/style_layer/heatmap_style_layer.js +++ b/src/style/style_layer/heatmap_style_layer.js @@ -31,11 +31,32 @@ class HeatmapStyleLayer extends StyleLayer { constructor(layer: LayerSpecification) { super(layer, properties); + + // make sure color ramp texture is generated for default heatmap color too + this._updateColorRamp(); } - updatePaintTransitions(options: {transition?: boolean}, transition: TransitionSpecification) { - super.updatePaintTransitions(options, transition); - this.colorRamp = this._transitioningPaint._values['heatmap-color'].possiblyEvaluate(({zoom: 0}: any)); + setPaintProperty(name: string, value: mixed, options: {validate: boolean}) { + super.setPaintProperty(name, value, options); + if (name === 'heatmap-color') { + this._updateColorRamp(); + } + } + + _updateColorRamp() { + const expression = this._transitionablePaint._values['heatmap-color'].value.expression; + const colorRampData = new Uint8Array(256 * 4); + const len = colorRampData.length; + for (let i = 4; i < len; i += 4) { + const pxColor = expression.evaluate(({heatmapDensity: i / len}: any)); + // the colors are being unpremultiplied because Color uses + // premultiplied values, and the Texture class expects unpremultiplied ones + colorRampData[i + 0] = Math.floor(pxColor.r * 255 / pxColor.a); + colorRampData[i + 1] = Math.floor(pxColor.g * 255 / pxColor.a); + colorRampData[i + 2] = Math.floor(pxColor.b * 255 / pxColor.a); + colorRampData[i + 3] = Math.floor(pxColor.a * 255); + } + this.colorRamp = RGBAImage.create({width: 256, height: 1}, colorRampData); this.colorRampTexture = null; }