Fix rendercomplete for WebGLPoints layer and subclasses

This commit is contained in:
Andreas Hocevar
2022-02-01 14:23:57 +01:00
parent 10b97d3993
commit 7c3c1ac354
5 changed files with 89 additions and 4 deletions

View File

@@ -943,10 +943,13 @@ class PluggableMap extends BaseObject {
/** /**
* @return {boolean} Layers have sources that are still loading. * @return {boolean} Layers have sources that are still loading.
*/ */
getLoading() { getLoadingOrNotReady() {
const layerStatesArray = this.getLayerGroup().getLayerStatesArray(); const layerStatesArray = this.getLayerGroup().getLayerStatesArray();
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) { for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
const layer = layerStatesArray[i].layer; const layer = layerStatesArray[i].layer;
if (!layer.getRenderer().ready) {
return true;
}
const source = /** @type {import("./layer/Layer.js").default} */ ( const source = /** @type {import("./layer/Layer.js").default} */ (
layer layer
).getSource(); ).getSource();
@@ -1561,7 +1564,7 @@ class PluggableMap extends BaseObject {
this.renderComplete_ = this.renderComplete_ =
!this.tileQueue_.getTilesLoading() && !this.tileQueue_.getTilesLoading() &&
!this.tileQueue_.getCount() && !this.tileQueue_.getCount() &&
!this.getLoading(); !this.getLoadingOrNotReady();
if (!this.postRenderTimeoutHandle_) { if (!this.postRenderTimeoutHandle_) {
this.postRenderTimeoutHandle_ = setTimeout(() => { this.postRenderTimeoutHandle_ = setTimeout(() => {

View File

@@ -17,6 +17,11 @@ class LayerRenderer extends Observable {
constructor(layer) { constructor(layer) {
super(); super();
/**
* @type {boolean} The renderer is initialized and ready to render.
*/
this.ready = true;
/** @private */ /** @private */
this.boundHandleImageChange_ = this.handleImageChange_.bind(this); this.boundHandleImageChange_ = this.handleImageChange_.bind(this);

View File

@@ -137,6 +137,8 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
postProcesses: options.postProcesses, postProcesses: options.postProcesses,
}); });
this.ready = false;
this.sourceRevision_ = -1; this.sourceRevision_ = -1;
this.verticesBuffer_ = new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW); this.verticesBuffer_ = new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW);
@@ -320,7 +322,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
event.data.renderInstructions event.data.renderInstructions
); );
} }
this.ready = true;
this.getLayer().changed(); this.getLayer().changed();
} }
}.bind(this) }.bind(this)
@@ -610,6 +612,7 @@ class WebGLPointsLayerRenderer extends WebGLLayerRenderer {
}; };
// additional properties will be sent back as-is by the worker // additional properties will be sent back as-is by the worker
message['projectionTransform'] = projectionTransform; message['projectionTransform'] = projectionTransform;
this.ready = false;
this.worker_.postMessage(message, [this.renderInstructions_.buffer]); this.worker_.postMessage(message, [this.renderInstructions_.buffer]);
this.renderInstructions_ = null; this.renderInstructions_ = null;

View File

@@ -23,6 +23,7 @@ import TileLayerRenderer from '../../../../src/ol/renderer/canvas/TileLayer.js';
import VectorLayer from '../../../../src/ol/layer/Vector.js'; import VectorLayer from '../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../src/ol/source/Vector.js'; import VectorSource from '../../../../src/ol/source/Vector.js';
import View from '../../../../src/ol/View.js'; import View from '../../../../src/ol/View.js';
import WebGLPointsLayer from '../../../../src/ol/layer/WebGLPoints.js';
import XYZ from '../../../../src/ol/source/XYZ.js'; import XYZ from '../../../../src/ol/source/XYZ.js';
import {LineString, Point, Polygon} from '../../../../src/ol/geom.js'; import {LineString, Point, Polygon} from '../../../../src/ol/geom.js';
import {TRUE} from '../../../../src/ol/functions.js'; import {TRUE} from '../../../../src/ol/functions.js';
@@ -449,6 +450,17 @@ describe('ol/Map', function () {
}, },
}), }),
}), }),
new WebGLPointsLayer({
source: new VectorSource({
features: [new Feature(new Point([0, 0]))],
}),
style: {
symbol: {
color: 'red',
symbolType: 'circle',
},
},
}),
], ],
}); });
}); });
@@ -460,13 +472,15 @@ describe('ol/Map', function () {
}); });
it('triggers when all tiles and sources are loaded and faded in', function (done) { it('triggers when all tiles and sources are loaded and faded in', function (done) {
const layers = map.getLayers().getArray();
expect(layers[6].getRenderer().ready).to.be(false);
map.once('rendercomplete', function () { map.once('rendercomplete', function () {
const layers = map.getLayers().getArray();
expect(map.tileQueue_.getTilesLoading()).to.be(0); expect(map.tileQueue_.getTilesLoading()).to.be(0);
expect(layers[1].getSource().image_.getState()).to.be( expect(layers[1].getSource().image_.getState()).to.be(
ImageState.LOADED ImageState.LOADED
); );
expect(layers[2].getSource().getFeatures().length).to.be(1); expect(layers[2].getSource().getFeatures().length).to.be(1);
expect(layers[6].getRenderer().ready).to.be(true);
done(); done();
}); });
map.setView( map.setView(

View File

@@ -1,8 +1,10 @@
import Feature from '../../../../../../src/ol/Feature.js'; import Feature from '../../../../../../src/ol/Feature.js';
import GeoJSON from '../../../../../../src/ol/format/GeoJSON.js'; import GeoJSON from '../../../../../../src/ol/format/GeoJSON.js';
import Map from '../../../../../../src/ol/Map.js';
import Point from '../../../../../../src/ol/geom/Point.js'; import Point from '../../../../../../src/ol/geom/Point.js';
import VectorLayer from '../../../../../../src/ol/layer/Vector.js'; import VectorLayer from '../../../../../../src/ol/layer/Vector.js';
import VectorSource from '../../../../../../src/ol/source/Vector.js'; import VectorSource from '../../../../../../src/ol/source/Vector.js';
import View from '../../../../../../src/ol/View.js';
import ViewHint from '../../../../../../src/ol/ViewHint.js'; import ViewHint from '../../../../../../src/ol/ViewHint.js';
import WebGLPointsLayer from '../../../../../../src/ol/layer/WebGLPoints.js'; import WebGLPointsLayer from '../../../../../../src/ol/layer/WebGLPoints.js';
import WebGLPointsLayerRenderer from '../../../../../../src/ol/renderer/webgl/PointsLayer.js'; import WebGLPointsLayerRenderer from '../../../../../../src/ol/renderer/webgl/PointsLayer.js';
@@ -11,6 +13,7 @@ import {
compose as composeTransform, compose as composeTransform,
create as createTransform, create as createTransform,
} from '../../../../../../src/ol/transform.js'; } from '../../../../../../src/ol/transform.js';
import {createCanvasContext2D} from '../../../../../../src/ol/dom.js';
import {get as getProjection} from '../../../../../../src/ol/proj.js'; import {get as getProjection} from '../../../../../../src/ol/proj.js';
import {getUid} from '../../../../../../src/ol/util.js'; import {getUid} from '../../../../../../src/ol/util.js';
@@ -688,4 +691,61 @@ describe('ol/renderer/webgl/PointsLayer', function () {
renderer.renderFrame(frameState); renderer.renderFrame(frameState);
}); });
}); });
describe('rendercomplete', function () {
let map, layer;
beforeEach(function () {
layer = new WebGLPointsLayer({
source: new VectorSource({
features: [new Feature(new Point([0, 0]))],
}),
style: {
symbol: {
symbolType: 'circle',
size: 14,
color: 'red',
},
},
});
map = new Map({
pixelRatio: 1,
target: createMapDiv(100, 100),
layers: [layer],
view: new View({
center: [0, 0],
zoom: 2,
}),
});
});
afterEach(function () {
disposeMap(map);
});
it('is completely rendered on rendercomplete', function (done) {
map.once('rendercomplete', function () {
const targetContext = createCanvasContext2D(1, 1);
const canvas = document.querySelector('.ol-layer');
targetContext.drawImage(canvas, 50, 50, 1, 1, 0, 0, 1, 1);
expect(Array.from(targetContext.getImageData(0, 0, 1, 1).data)).to.eql([
255, 0, 0, 255,
]);
layer
.getSource()
.addFeature(new Feature(new Point([1900000, 1900000])));
layer.once('postrender', function () {
expect(layer.getRenderer().ready).to.be(false);
});
map.once('rendercomplete', function () {
const targetContext = createCanvasContext2D(1, 1);
const canvas = document.querySelector('.ol-layer');
targetContext.drawImage(canvas, 99, 0, 1, 1, 0, 0, 1, 1);
expect(
Array.from(targetContext.getImageData(0, 0, 1, 1).data)
).to.eql([255, 0, 0, 255]);
done();
});
});
});
});
}); });