Pass render target of previous layer to next layer
This commit is contained in:
@@ -189,13 +189,15 @@ class Layer extends BaseLayer {
|
|||||||
* In charge to manage the rendering of the layer. One layer type is
|
* In charge to manage the rendering of the layer. One layer type is
|
||||||
* bounded with one layer renderer.
|
* bounded with one layer renderer.
|
||||||
* @param {?import("../PluggableMap.js").FrameState} frameState Frame state.
|
* @param {?import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||||
|
* @param {HTMLElement} target Target which the renderer may (but need not) use
|
||||||
|
* for rendering its content.
|
||||||
* @return {HTMLElement} The rendered element.
|
* @return {HTMLElement} The rendered element.
|
||||||
*/
|
*/
|
||||||
render(frameState) {
|
render(frameState, target) {
|
||||||
const layerRenderer = this.getRenderer();
|
const layerRenderer = this.getRenderer();
|
||||||
const layerState = this.getLayerState();
|
const layerState = this.getLayerState();
|
||||||
if (layerRenderer.prepareFrame(frameState, layerState)) {
|
if (layerRenderer.prepareFrame(frameState, layerState)) {
|
||||||
return layerRenderer.renderFrame(frameState, layerState);
|
return layerRenderer.renderFrame(frameState, layerState, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
const viewResolution = frameState.viewState.resolution;
|
const viewResolution = frameState.viewState.resolution;
|
||||||
|
|
||||||
this.children_.length = 0;
|
this.children_.length = 0;
|
||||||
let element = null;
|
let previousElement = null;
|
||||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||||
const layerState = layerStatesArray[i];
|
const layerState = layerStatesArray[i];
|
||||||
if (!visibleAtResolution(layerState, viewResolution) ||
|
if (!visibleAtResolution(layerState, viewResolution) ||
|
||||||
@@ -96,9 +96,12 @@ class CompositeMapRenderer extends MapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const layer = layerState.layer;
|
const layer = layerState.layer;
|
||||||
element = layer.render(frameState);
|
const element = layer.render(frameState, previousElement);
|
||||||
if (element) {
|
if (element) {
|
||||||
this.children_.push(element);
|
previousElement = element;
|
||||||
|
if (element !== this.children_[this.children_.length - 1]) {
|
||||||
|
this.children_.push(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.renderFrame(frameState);
|
super.renderFrame(frameState);
|
||||||
|
|||||||
@@ -41,9 +41,10 @@ class LayerRenderer extends Observable {
|
|||||||
* @abstract
|
* @abstract
|
||||||
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||||
* @param {import("../layer/Layer.js").State} layerState Layer state.
|
* @param {import("../layer/Layer.js").State} layerState Layer state.
|
||||||
|
* @param {HTMLElement} target Target that may be used to render content to.
|
||||||
* @return {HTMLElement} The rendered element.
|
* @return {HTMLElement} The rendered element.
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
renderFrame(frameState, layerState, target) {
|
||||||
return abstract();
|
return abstract();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import RenderEvent from '../../render/Event.js';
|
|||||||
import RenderEventType from '../../render/EventType.js';
|
import RenderEventType from '../../render/EventType.js';
|
||||||
import {rotateAtOffset} from '../../render/canvas.js';
|
import {rotateAtOffset} from '../../render/canvas.js';
|
||||||
import LayerRenderer from '../Layer.js';
|
import LayerRenderer from '../Layer.js';
|
||||||
import {create as createTransform, apply as applyTransform, compose as composeTransform} from '../../transform.js';
|
import {create as createTransform, apply as applyTransform, compose as composeTransform, toString as transformToString} from '../../transform.js';
|
||||||
|
import ContextEventType from '../../webgl/ContextEventType.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract
|
* @abstract
|
||||||
@@ -55,12 +56,49 @@ class CanvasLayerRenderer extends LayerRenderer {
|
|||||||
* @protected
|
* @protected
|
||||||
* @type {CanvasRenderingContext2D}
|
* @type {CanvasRenderingContext2D}
|
||||||
*/
|
*/
|
||||||
this.context = createCanvasContext2D();
|
this.context = null;
|
||||||
|
|
||||||
const canvas = this.context.canvas;
|
}
|
||||||
canvas.style.position = 'absolute';
|
|
||||||
canvas.style.transformOrigin = 'top left';
|
/**
|
||||||
canvas.className = this.getLayer().getClassName();
|
* Reuse the passed canvas's context, or create a new one.
|
||||||
|
* @protected
|
||||||
|
* @param {HTMLCanvasElement} canvas Canvas.
|
||||||
|
* @return {CanvasRenderingContext2D} context Context.
|
||||||
|
*/
|
||||||
|
useContext(canvas) {
|
||||||
|
let context;
|
||||||
|
if (canvas) {
|
||||||
|
context = canvas.getContext('2d');
|
||||||
|
}
|
||||||
|
if (!context) {
|
||||||
|
context = createCanvasContext2D();
|
||||||
|
canvas = context.canvas;
|
||||||
|
canvas.style.position = 'absolute';
|
||||||
|
canvas.style.transformOrigin = 'top left';
|
||||||
|
}
|
||||||
|
canvas.classList.add(this.getLayer().getClassName());
|
||||||
|
this.context = context;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} target Potential render target.
|
||||||
|
* @param {import("../../transform").Transform} transform Transform.
|
||||||
|
* @return {HTMLCanvasElement} Canvas.
|
||||||
|
*/
|
||||||
|
getCanvas(target, transform) {
|
||||||
|
let canvas = null;
|
||||||
|
if (target) {
|
||||||
|
canvas = target.firstElementChild || target;
|
||||||
|
if (canvas && canvas instanceof HTMLCanvasElement && canvas.style.transform === transformToString(transform)) {
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
} else if (this.context) {
|
||||||
|
canvas = this.context.canvas;
|
||||||
|
this.context.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
}
|
||||||
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -137,8 +137,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
* @returns {HTMLElement} The rendered element.
|
* @returns {HTMLElement} The rendered element.
|
||||||
*/
|
*/
|
||||||
renderFrame(frameState, layerState) {
|
renderFrame(frameState, layerState, target) {
|
||||||
const context = this.context;
|
|
||||||
const viewState = frameState.viewState;
|
const viewState = frameState.viewState;
|
||||||
const projection = viewState.projection;
|
const projection = viewState.projection;
|
||||||
const viewResolution = viewState.resolution;
|
const viewResolution = viewState.resolution;
|
||||||
@@ -224,7 +223,6 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const canvas = context.canvas;
|
|
||||||
const canvasScale = tileResolution / viewResolution;
|
const canvasScale = tileResolution / viewResolution;
|
||||||
|
|
||||||
// set forward and inverse pixel transforms
|
// set forward and inverse pixel transforms
|
||||||
@@ -234,6 +232,10 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
rotation,
|
rotation,
|
||||||
-width / 2, -height / 2
|
-width / 2, -height / 2
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const context = this.useContext(this.getCanvas(target, this.pixelTransform_));
|
||||||
|
const canvas = context.canvas;
|
||||||
|
|
||||||
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
|
makeInverse(this.inversePixelTransform_, this.pixelTransform_);
|
||||||
|
|
||||||
// set scale transform for calculating tile positions on the canvas
|
// set scale transform for calculating tile positions on the canvas
|
||||||
@@ -247,8 +249,6 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
if (canvas.width != width || canvas.height != height) {
|
if (canvas.width != width || canvas.height != height) {
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
} else {
|
|
||||||
context.clearRect(0, 0, width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layerState.extent) {
|
if (layerState.extent) {
|
||||||
@@ -270,6 +270,8 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const clips = [];
|
||||||
|
let currentClip;
|
||||||
for (let i = 0, ii = zs.length; i < ii; ++i) {
|
for (let i = 0, ii = zs.length; i < ii; ++i) {
|
||||||
const currentZ = zs[i];
|
const currentZ = zs[i];
|
||||||
const currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
|
const currentTilePixelSize = tileSource.getTilePixelSize(currentZ, pixelRatio, projection);
|
||||||
@@ -299,6 +301,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
const w = nextX - x;
|
const w = nextX - x;
|
||||||
const h = nextY - y;
|
const h = nextY - y;
|
||||||
|
|
||||||
|
currentClip = [x, y, w, h];
|
||||||
this.drawTileImage(tile, frameState, x, y, w, h, tileGutter, z === currentZ);
|
this.drawTileImage(tile, frameState, x, y, w, h, tileGutter, z === currentZ);
|
||||||
this.renderedTiles.push(tile);
|
this.renderedTiles.push(tile);
|
||||||
this.updateUsedTiles(frameState.usedTiles, tileSource, tile);
|
this.updateUsedTiles(frameState.usedTiles, tileSource, tile);
|
||||||
@@ -355,7 +358,7 @@ class CanvasTileLayerRenderer extends CanvasLayerRenderer {
|
|||||||
const tileLayer = /** @type {import("../../layer/Tile.js").default} */ (this.getLayer());
|
const tileLayer = /** @type {import("../../layer/Tile.js").default} */ (this.getLayer());
|
||||||
const tileSource = tileLayer.getSource();
|
const tileSource = tileLayer.getSource();
|
||||||
if (alpha === 1 && !tileSource.getOpaque(frameState.viewState.projection)) {
|
if (alpha === 1 && !tileSource.getOpaque(frameState.viewState.projection)) {
|
||||||
this.context.clearRect(x, y, w, h);
|
//this.context.clearRect(x, y, w, h);
|
||||||
}
|
}
|
||||||
const alphaChanged = alpha !== this.context.globalAlpha;
|
const alphaChanged = alpha !== this.context.globalAlpha;
|
||||||
if (alphaChanged) {
|
if (alphaChanged) {
|
||||||
|
|||||||
Reference in New Issue
Block a user