Keep track of when a layer is unrendered
This commit is contained in:
+18
-1
@@ -146,6 +146,12 @@ class Layer extends BaseLayer {
|
|||||||
*/
|
*/
|
||||||
this.renderer_ = null;
|
this.renderer_ = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @protected
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
this.rendered = false;
|
||||||
|
|
||||||
// Overwrite default render method with a custom one
|
// Overwrite default render method with a custom one
|
||||||
if (options.render) {
|
if (options.render) {
|
||||||
this.render = options.render;
|
this.render = options.render;
|
||||||
@@ -255,7 +261,7 @@ class Layer extends BaseLayer {
|
|||||||
* @return {Uint8ClampedArray|Uint8Array|Float32Array|DataView|null} Pixel data.
|
* @return {Uint8ClampedArray|Uint8Array|Float32Array|DataView|null} Pixel data.
|
||||||
*/
|
*/
|
||||||
getData(pixel) {
|
getData(pixel) {
|
||||||
if (!this.renderer_) {
|
if (!this.renderer_ || !this.rendered) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.renderer_.getData(pixel);
|
return this.renderer_.getData(pixel);
|
||||||
@@ -273,15 +279,26 @@ class Layer extends BaseLayer {
|
|||||||
const layerRenderer = this.getRenderer();
|
const layerRenderer = this.getRenderer();
|
||||||
|
|
||||||
if (layerRenderer.prepareFrame(frameState)) {
|
if (layerRenderer.prepareFrame(frameState)) {
|
||||||
|
this.rendered = true;
|
||||||
return layerRenderer.renderFrame(frameState, target);
|
return layerRenderer.renderFrame(frameState, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a layer is not visible during a map render.
|
||||||
|
*/
|
||||||
|
unrender() {
|
||||||
|
this.rendered = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For use inside the library only.
|
* For use inside the library only.
|
||||||
* @param {import("../PluggableMap.js").default|null} map Map.
|
* @param {import("../PluggableMap.js").default|null} map Map.
|
||||||
*/
|
*/
|
||||||
setMapInternal(map) {
|
setMapInternal(map) {
|
||||||
|
if (!map) {
|
||||||
|
this.unrender();
|
||||||
|
}
|
||||||
this.set(LayerProperty.MAP, map);
|
this.set(LayerProperty.MAP, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -440,6 +440,7 @@ class WebGLTileLayer extends BaseTileLayer {
|
|||||||
* @return {HTMLElement} The rendered element.
|
* @return {HTMLElement} The rendered element.
|
||||||
*/
|
*/
|
||||||
render(frameState, target) {
|
render(frameState, target) {
|
||||||
|
this.rendered = true;
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const sources = this.getSources(frameState.extent, viewState.resolution);
|
const sources = this.getSources(frameState.extent, viewState.resolution);
|
||||||
let ready = true;
|
let ready = true;
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
(sourceState != SourceState.READY &&
|
(sourceState != SourceState.READY &&
|
||||||
sourceState != SourceState.UNDEFINED)
|
sourceState != SourceState.UNDEFINED)
|
||||||
) {
|
) {
|
||||||
|
layer.unrender();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import Map from '../../../../../src/ol/Map.js';
|
|||||||
import Property from '../../../../../src/ol/layer/Property.js';
|
import Property from '../../../../../src/ol/layer/Property.js';
|
||||||
import RenderEvent from '../../../../../src/ol/render/Event.js';
|
import RenderEvent from '../../../../../src/ol/render/Event.js';
|
||||||
import Source from '../../../../../src/ol/source/Source.js';
|
import Source from '../../../../../src/ol/source/Source.js';
|
||||||
|
import TileLayer from '../../../../../src/ol/layer/Tile.js';
|
||||||
|
import View from '../../../../../src/ol/View.js';
|
||||||
|
import XYZ from '../../../../../src/ol/source/XYZ.js';
|
||||||
import {get as getProjection} from '../../../../../src/ol/proj.js';
|
import {get as getProjection} from '../../../../../src/ol/proj.js';
|
||||||
|
|
||||||
describe('ol/layer/Layer', function () {
|
describe('ol/layer/Layer', function () {
|
||||||
@@ -619,6 +622,77 @@ describe('ol/layer/Layer', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('unrender()', () => {
|
||||||
|
/** @type {Map} */
|
||||||
|
let map;
|
||||||
|
|
||||||
|
/** @type {TileLayer} */
|
||||||
|
let layer;
|
||||||
|
|
||||||
|
/** HTMLDivElement */
|
||||||
|
let target;
|
||||||
|
|
||||||
|
beforeEach((done) => {
|
||||||
|
target = document.createElement('div');
|
||||||
|
target.style.width = '100px';
|
||||||
|
target.style.height = '100px';
|
||||||
|
document.body.appendChild(target);
|
||||||
|
|
||||||
|
layer = new TileLayer({
|
||||||
|
source: new XYZ({
|
||||||
|
url: 'spec/ol/data/osm-0-0-0.png',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
map = new Map({
|
||||||
|
target: target,
|
||||||
|
layers: [layer],
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 0,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
map.once('rendercomplete', () => done());
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
map.setTarget(null);
|
||||||
|
document.body.removeChild(target);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is called when a layer goes from visible to not visible', () => {
|
||||||
|
const spy = sinon.spy(layer, 'unrender');
|
||||||
|
map.renderSync();
|
||||||
|
expect(spy.callCount).to.be(0);
|
||||||
|
|
||||||
|
layer.setVisible(false);
|
||||||
|
map.renderSync();
|
||||||
|
expect(spy.callCount).to.be(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is called when a layer is removed from the map', () => {
|
||||||
|
const spy = sinon.spy(layer, 'unrender');
|
||||||
|
map.renderSync();
|
||||||
|
expect(spy.callCount).to.be(0);
|
||||||
|
|
||||||
|
map.removeLayer(layer);
|
||||||
|
map.renderSync();
|
||||||
|
expect(spy.callCount).to.be(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is called when a layer goes out of range', () => {
|
||||||
|
const spy = sinon.spy(layer, 'unrender');
|
||||||
|
map.renderSync();
|
||||||
|
expect(spy.callCount).to.be(0);
|
||||||
|
|
||||||
|
layer.setMaxZoom(3);
|
||||||
|
map.getView().setZoom(4);
|
||||||
|
map.renderSync();
|
||||||
|
expect(spy.callCount).to.be(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('map property', () => {
|
describe('map property', () => {
|
||||||
it('is set when a layer is added to a map', () => {
|
it('is set when a layer is added to a map', () => {
|
||||||
const map = new Map({});
|
const map = new Map({});
|
||||||
|
|||||||
@@ -69,6 +69,13 @@ describe('ol/layer/Tile', function () {
|
|||||||
expect(data[2]).to.be(208);
|
expect(data[2]).to.be(208);
|
||||||
expect(data[3]).to.be(255);
|
expect(data[3]).to.be(255);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('gets pixel data', () => {
|
||||||
|
layer.setVisible(false);
|
||||||
|
map.renderSync();
|
||||||
|
const data = layer.getData([50, 50]);
|
||||||
|
expect(data).to.be(null);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('frameState.animate after tile transition with layer opacity', function () {
|
describe('frameState.animate after tile transition with layer opacity', function () {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import DataTileSource from '../../../../../src/ol/source/DataTile.js';
|
import DataTileSource from '../../../../../src/ol/source/DataTile.js';
|
||||||
import GeoTIFF from '../../../../../src/ol/source/GeoTIFF.js';
|
|
||||||
import Map from '../../../../../src/ol/Map.js';
|
import Map from '../../../../../src/ol/Map.js';
|
||||||
import View from '../../../../../src/ol/View.js';
|
import View from '../../../../../src/ol/View.js';
|
||||||
import WebGLHelper from '../../../../../src/ol/webgl/Helper.js';
|
import WebGLHelper from '../../../../../src/ol/webgl/Helper.js';
|
||||||
@@ -66,6 +65,10 @@ describe('ol/layer/WebGLTile', function () {
|
|||||||
document.body.appendChild(target);
|
document.body.appendChild(target);
|
||||||
map = new Map({
|
map = new Map({
|
||||||
target: target,
|
target: target,
|
||||||
|
view: new View({
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 0,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -75,23 +78,26 @@ describe('ol/layer/WebGLTile', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('retrieves pixel data', (done) => {
|
it('retrieves pixel data', (done) => {
|
||||||
const source = new GeoTIFF({
|
const layer = new WebGLTileLayer({
|
||||||
sources: [{url: 'spec/ol/source/images/0-0-0.tif'}],
|
source: new DataTileSource({
|
||||||
|
tilePixelRatio: 1 / 256,
|
||||||
|
loader(z, x, y) {
|
||||||
|
return new Uint8Array([5, 4, 3, 2, 1]);
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const layer = new WebGLTileLayer({source: source});
|
|
||||||
|
|
||||||
map.addLayer(layer);
|
map.addLayer(layer);
|
||||||
map.setView(source.getView());
|
|
||||||
|
|
||||||
map.once('rendercomplete', () => {
|
map.once('rendercomplete', () => {
|
||||||
const data = layer.getData([50, 25]);
|
const data = layer.getData([50, 25]);
|
||||||
expect(data).to.be.a(Uint8Array);
|
expect(data).to.be.a(Uint8Array);
|
||||||
expect(data.length).to.be(4);
|
expect(data.length).to.be(5);
|
||||||
expect(data[0]).to.be(255);
|
expect(data[0]).to.be(5);
|
||||||
expect(data[1]).to.be(189);
|
expect(data[1]).to.be(4);
|
||||||
expect(data[2]).to.be(103);
|
expect(data[2]).to.be(3);
|
||||||
expect(data[3]).to.be(255);
|
expect(data[3]).to.be(2);
|
||||||
|
expect(data[4]).to.be(1);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -107,12 +113,6 @@ describe('ol/layer/WebGLTile', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
map.addLayer(layer);
|
map.addLayer(layer);
|
||||||
map.setView(
|
|
||||||
new View({
|
|
||||||
center: [0, 0],
|
|
||||||
zoom: 0,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
map.once('rendercomplete', () => {
|
map.once('rendercomplete', () => {
|
||||||
const data = layer.getData([50, 25]);
|
const data = layer.getData([50, 25]);
|
||||||
|
|||||||
Reference in New Issue
Block a user