diff --git a/examples/heatmap-earthquakes.js b/examples/heatmap-earthquakes.js index 05d28aeb31..93256ab1a8 100644 --- a/examples/heatmap-earthquakes.js +++ b/examples/heatmap-earthquakes.js @@ -16,16 +16,15 @@ const vector = new HeatmapLayer({ }) }), blur: parseInt(blur.value, 10), - radius: parseInt(radius.value, 10) -}); - -vector.getSource().on('addfeature', function(event) { - // 2012_Earthquakes_Mag5.kml stores the magnitude of each earthquake in a - // standards-violating tag in each Placemark. We extract it from - // the Placemark's name instead. - const name = event.feature.get('name'); - const magnitude = parseFloat(name.substr(2)); - event.feature.set('weight', magnitude - 5); + radius: parseInt(radius.value, 10), + weight: function(feature) { + // 2012_Earthquakes_Mag5.kml stores the magnitude of each earthquake in a + // standards-violating tag in each Placemark. We extract it from + // the Placemark's name instead. + const name = feature.get('name'); + const magnitude = parseFloat(name.substr(2)); + return magnitude - 5; + } }); const raster = new TileLayer({ @@ -34,7 +33,7 @@ const raster = new TileLayer({ }) }); -const map = new Map({ +new Map({ layers: [raster, vector], target: 'map', view: new View({ diff --git a/src/ol/renderer/webgl/PointsLayer.js b/src/ol/renderer/webgl/PointsLayer.js index 45eb8e30b0..d0ae7f1140 100644 --- a/src/ol/renderer/webgl/PointsLayer.js +++ b/src/ol/renderer/webgl/PointsLayer.js @@ -7,7 +7,7 @@ import {AttributeType, DefaultUniform} from '../../webgl/Helper.js'; import GeometryType from '../../geom/GeometryType.js'; import WebGLLayerRenderer, {colorDecodeId, colorEncodeId, WebGLWorkerMessageType} from './Layer.js'; import ViewHint from '../../ViewHint.js'; -import {createEmpty, equals} from '../../extent.js'; +import {buffer, createEmpty, equals} from '../../extent.js'; import { apply as applyTransform, create as createTransform, @@ -18,6 +18,7 @@ import {create as createWebGLWorker} from '../../worker/webgl.js'; import {getUid} from '../../util.js'; import WebGLRenderTarget from '../../webgl/RenderTarget.js'; import {assert} from '../../asserts.js'; +import BaseVector from '../../layer/BaseVector.js'; /** * @typedef {Object} CustomAttribute A description of a custom attribute to be passed on to the GPU, with a value different @@ -300,20 +301,22 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer { const layer = this.getLayer(); const vectorSource = layer.getSource(); const viewState = frameState.viewState; - - // the source has changed: clear the feature cache & reload features - const sourceChanged = this.sourceRevision_ < vectorSource.getRevision(); - if (sourceChanged) { - this.sourceRevision_ = vectorSource.getRevision(); - - const projection = viewState.projection; - const resolution = viewState.resolution; - vectorSource.loadFeatures([-Infinity, -Infinity, Infinity, Infinity], resolution, projection); - } - const viewNotMoving = !frameState.viewHints[ViewHint.ANIMATING] && !frameState.viewHints[ViewHint.INTERACTING]; const extentChanged = !equals(this.previousExtent_, frameState.extent); - if ((sourceChanged || extentChanged) && viewNotMoving) { + const sourceChanged = this.sourceRevision_ < vectorSource.getRevision(); + + if (sourceChanged) { + this.sourceRevision_ = vectorSource.getRevision(); + } + + if (viewNotMoving && (extentChanged || sourceChanged)) { + const projection = viewState.projection; + const resolution = viewState.resolution; + + const renderBuffer = layer instanceof BaseVector ? layer.getRenderBuffer() : 0; + const extent = buffer(frameState.extent, renderBuffer * resolution); + vectorSource.loadFeatures(extent, resolution, projection); + this.rebuildBuffers_(frameState); this.previousExtent_ = frameState.extent.slice(); } diff --git a/test/spec/ol/renderer/webgl/pointslayer.test.js b/test/spec/ol/renderer/webgl/pointslayer.test.js index bd41446491..25d6d230b9 100644 --- a/test/spec/ol/renderer/webgl/pointslayer.test.js +++ b/test/spec/ol/renderer/webgl/pointslayer.test.js @@ -104,7 +104,8 @@ describe('ol.renderer.webgl.PointsLayer', function() { beforeEach(function() { layer = new VectorLayer({ - source: new VectorSource() + source: new VectorSource(), + renderBuffer: 10 }); renderer = new WebGLPointsLayerRenderer(layer, { vertexShader: simpleVertexShader, @@ -233,6 +234,35 @@ describe('ol.renderer.webgl.PointsLayer', function() { renderer.prepareFrame(frameState); expect(spy.callCount).to.be(2); }); + + it('triggers source loading when the extent changes', function() { + const spy = sinon.spy(layer.getSource(), 'loadFeatures'); + + renderer.prepareFrame(frameState); + expect(spy.callCount).to.be(1); + + renderer.prepareFrame(frameState); + expect(spy.callCount).to.be(1); + + frameState.extent = [10, 20, 30, 40]; + renderer.prepareFrame(frameState); + expect(spy.callCount).to.be(2); + expect(spy.getCall(1).args[0]).to.eql([0, 10, 40, 50]); // renderBuffer is 10 + }); + + it('triggers source loading when the source revision changes', function() { + const spy = sinon.spy(layer.getSource(), 'loadFeatures'); + + renderer.prepareFrame(frameState); + expect(spy.callCount).to.be(1); + + renderer.prepareFrame(frameState); + expect(spy.callCount).to.be(1); + + layer.getSource().changed(); + renderer.prepareFrame(frameState); + expect(spy.callCount).to.be(2); + }); }); describe('#forEachFeatureAtCoordinate', function() {