diff --git a/src/ol/layer/WebGLTile.js b/src/ol/layer/WebGLTile.js index d801be00a6..9e404bc266 100644 --- a/src/ol/layer/WebGLTile.js +++ b/src/ol/layer/WebGLTile.js @@ -2,6 +2,7 @@ * @module ol/layer/WebGLTile */ import BaseTileLayer from './BaseTile.js'; +import LayerProperty from '../layer/Property.js'; import WebGLTileLayerRenderer, { Attributes, Uniforms, @@ -298,14 +299,28 @@ class WebGLTileLayer extends BaseTileLayer { * @private */ this.styleVariables_ = this.style_.variables || {}; + + this.addChangeListener(LayerProperty.SOURCE, this.handleSourceUpdate_); + } + + /** + * @private + */ + handleSourceUpdate_() { + this.setStyle(this.style_); + } + + /** + * @private + * @return {number} The number of source bands. + */ + getSourceBandCount_() { + const source = this.getSource(); + return source && 'bandCount' in source ? source.bandCount : 4; } createRenderer() { - const source = this.getSource(); - const parsedStyle = parseStyle( - this.style_, - 'bandCount' in source ? source.bandCount : 4 - ); + const parsedStyle = parseStyle(this.style_, this.getSourceBandCount_()); return new WebGLTileLayerRenderer(this, { vertexShader: parsedStyle.vertexShader, @@ -323,11 +338,7 @@ class WebGLTileLayer extends BaseTileLayer { */ setStyle(style) { this.style_ = style; - const source = this.getSource(); - const parsedStyle = parseStyle( - this.style_, - 'bandCount' in source ? source.bandCount : 4 - ); + const parsedStyle = parseStyle(this.style_, this.getSourceBandCount_()); const renderer = this.getRenderer(); renderer.reset({ vertexShader: parsedStyle.vertexShader, diff --git a/test/browser/spec/ol/layer/WebGLTile.test.js b/test/browser/spec/ol/layer/WebGLTile.test.js index f590af4c26..cd90407c0f 100644 --- a/test/browser/spec/ol/layer/WebGLTile.test.js +++ b/test/browser/spec/ol/layer/WebGLTile.test.js @@ -339,4 +339,38 @@ describe('ol/layer/WebGLTile', function () { } expect(incorrectStyle).to.throwException(); // missing 'blue' in styleVariables }); + + it('works if the layer is constructed without a source', (done) => { + const sourceless = new WebGLTileLayer({ + className: 'testlayer', + style: { + variables: { + r: 0, + g: 255, + b: 0, + }, + color: ['color', ['var', 'r'], ['var', 'g'], ['var', 'b']], + }, + }); + + map.addLayer(sourceless); + + sourceless.setSource( + new DataTileSource({ + loader(z, x, y) { + return new ImageData(256, 256); + }, + }) + ); + + let called = false; + layer.on('postrender', (event) => { + called = true; + }); + + map.once('rendercomplete', () => { + expect(called).to.be(true); + done(); + }); + }); });