diff --git a/src/canvas/heatmapFeature.js b/src/canvas/heatmapFeature.js index e10888f6d1..aacda52737 100644 --- a/src/canvas/heatmapFeature.js +++ b/src/canvas/heatmapFeature.js @@ -39,6 +39,7 @@ var canvas_heatmapFeature = function (arg) { m_heatMapTransform, s_init = this._init, s_update = this._update, + m_lastRenderDuration, m_renderTime = timestamp(); /** @@ -298,6 +299,7 @@ var canvas_heatmapFeature = function (arg) { this._renderOnCanvas = function (context2d, map) { if (m_renderTime.timestamp() < m_this.buildTime().timestamp()) { + let starttime = Date.now(); var data = m_this.data() || [], radius = m_this.style('radius') + m_this.style('blurRadius'), binned = m_this.binned(), @@ -350,6 +352,7 @@ var canvas_heatmapFeature = function (arg) { }; m_renderTime.modified(); layer.renderer().clearCanvas(false); + m_lastRenderDuration = Date.now() - starttime; } return m_this; @@ -440,6 +443,14 @@ var canvas_heatmapFeature = function (arg) { parseFloat((rotation - m_heatMapPosition.rotation).toFixed(4)) !== 0 || parseFloat(origin.x.toFixed(1)) !== 0 || parseFloat(origin.y.toFixed(1)) !== 0) { + let delay = m_this.updateDelay(); + if (delay < 0 && m_lastRenderDuration) { + delay = m_lastRenderDuration - Math.floor(1000 / 60 * delay); + } else if (m_lastRenderDuration) { + delay = m_lastRenderDuration * 2; + } else { + delay = 100; + } m_heatMapPosition.timeout = window.setTimeout(function () { m_heatMapPosition.timeout = undefined; m_this.buildTime().modified(); diff --git a/src/heatmapFeature.js b/src/heatmapFeature.js index 786f45a07b..49557a11a1 100644 --- a/src/heatmapFeature.js +++ b/src/heatmapFeature.js @@ -19,8 +19,11 @@ var transform = require('./transform'); * @property {number} [minIntensity=null] Minimum intensity of the data. * Minimum intensity must be a positive real number and is used to normalize * all intensities within a dataset. If `null`, it is computed. - * @property {number} [updateDelay=1000] Delay in milliseconds after a zoom, - * rotate, or pan event before recomputing the heatmap. + * @property {number} [updateDelay=-1] Delay in milliseconds after a zoom, + * rotate, or pan event before recomputing the heatmap. If 0, this is double + * the last render time. If negative, it is roughly the last render time + * plus the absolute value of the specified number of refresh intervals. + * compute a delay based on the last heatmap render time. * @property {boolean|number|'auto'} [binned='auto'] If `true` or a number, * spatially bin data as part of producing the heatmap. If falsy, each * datapoint stands on its own. If `'auto'`, bin data if there are more data @@ -76,7 +79,7 @@ var heatmapFeature = function (arg) { m_maxIntensity = arg.maxIntensity !== undefined ? arg.maxIntensity : null; m_minIntensity = arg.minIntensity !== undefined ? arg.minIntensity : null; m_binned = arg.binned !== undefined ? arg.binned : 'auto'; - m_updateDelay = arg.updateDelay ? parseInt(arg.updateDelay, 10) : 1000; + m_updateDelay = (arg.updateDelay || arg.updateDelay === 0) ? parseInt(arg.updateDelay, 10) : -1; /** * Get/Set maxIntensity. @@ -121,7 +124,9 @@ var heatmapFeature = function (arg) { * * @param {number} [val] If not specified, return the current update delay. * If specified, this is the delay in milliseconds after a zoom, rotate, - * or pan event before recomputing the heatmap. + * or pan event before recomputing the heatmap. If 0, this is double the + * last render time. If negative, it is roughly the last render time plus + * the absolute value of the specified number of refresh intervals. * @returns {number|this} */ this.updateDelay = function (val) { diff --git a/tests/cases/heatmap.js b/tests/cases/heatmap.js index 2da2ff03e1..ac5bd95c15 100644 --- a/tests/cases/heatmap.js +++ b/tests/cases/heatmap.js @@ -29,7 +29,7 @@ describe('canvas heatmap', function () { }); it('Add feature to a layer', function () { - feature1 = layer.createFeature('heatmap') + feature1 = layer.createFeature('heatmap', {updateDelay: 1000}) .data(testData) .intensity(function (d) { return d[0]; @@ -204,7 +204,7 @@ describe('canvas heatmap', function () { }); it('updateDelay', function () { var heatmap = heatmapFeature({layer: layer}); - expect(heatmap.updateDelay()).toBe(1000); + expect(heatmap.updateDelay()).toBe(-1); expect(heatmap.updateDelay(40)).toBe(heatmap); expect(heatmap.updateDelay()).toBe(40); heatmap = heatmapFeature({layer: layer, updateDelay: 50});