Move catch-up logic to main thread
This avoids requestAnimationFrame in the worker.
This commit is contained in:
@@ -11,7 +11,7 @@ import Source from '../src/ol/source/Source.js';
|
||||
|
||||
const worker = new Worker();
|
||||
|
||||
let container, transformContainer, canvas, workerFrameState, mainThreadFrameState;
|
||||
let container, transformContainer, canvas, rendering, workerFrameState, mainThreadFrameState;
|
||||
|
||||
// Transform the container to account for the differnece between the (newer)
|
||||
// main thread frameState and the (older) worker frameState
|
||||
@@ -62,10 +62,15 @@ const map = new Map({
|
||||
}
|
||||
mainThreadFrameState = frameState;
|
||||
updateContainerTransform();
|
||||
worker.postMessage({
|
||||
action: 'render',
|
||||
frameState: JSON.parse(stringify(frameState))
|
||||
});
|
||||
if (!rendering) {
|
||||
rendering = true;
|
||||
worker.postMessage({
|
||||
action: 'render',
|
||||
frameState: JSON.parse(stringify(frameState))
|
||||
});
|
||||
} else {
|
||||
frameState.animate = true;
|
||||
}
|
||||
return container;
|
||||
},
|
||||
source: new Source({
|
||||
@@ -101,18 +106,20 @@ worker.addEventListener('message', message => {
|
||||
});
|
||||
});
|
||||
image.src = event.data.src;
|
||||
} else if (message.data.action === 'request-render') {
|
||||
} else if (message.data.action === 'requestRender') {
|
||||
// Worker requested a new render frame
|
||||
map.render();
|
||||
} else if (canvas && message.data.action === 'rendered') {
|
||||
// Worker provies a new render frame
|
||||
transformContainer.style.transform = '';
|
||||
const imageData = message.data.imageData;
|
||||
canvas.width = imageData.width;
|
||||
canvas.height = imageData.height;
|
||||
canvas.getContext('2d').drawImage(imageData, 0, 0);
|
||||
canvas.style.transform = message.data.transform;
|
||||
workerFrameState = message.data.frameState;
|
||||
updateContainerTransform();
|
||||
requestAnimationFrame(function() {
|
||||
const imageData = message.data.imageData;
|
||||
canvas.width = imageData.width;
|
||||
canvas.height = imageData.height;
|
||||
canvas.getContext('2d').drawImage(imageData, 0, 0);
|
||||
canvas.style.transform = message.data.transform;
|
||||
workerFrameState = message.data.frameState;
|
||||
updateContainerTransform();
|
||||
});
|
||||
rendering = false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -14,6 +14,9 @@ const worker = self;
|
||||
|
||||
let frameState, pixelRatio, rendererTransform;
|
||||
const canvas = new OffscreenCanvas(1, 1);
|
||||
// OffscreenCanvas does not have a style, so we mock it
|
||||
canvas.style = {};
|
||||
const context = canvas.getContext('2d');
|
||||
|
||||
const sources = {
|
||||
landcover: new VectorTileSource({
|
||||
@@ -77,18 +80,17 @@ function loadStyles() {
|
||||
});
|
||||
layer.getRenderer().useContainer = function(target, transform) {
|
||||
this.containerReused = this.getLayer() !== layers[0];
|
||||
target.style = {};
|
||||
this.canvas = target;
|
||||
this.context = target.getContext('2d');
|
||||
this.canvas = canvas;
|
||||
this.context = context;
|
||||
this.container = {
|
||||
firstElementChild: target
|
||||
firstElementChild: canvas
|
||||
};
|
||||
rendererTransform = transform;
|
||||
};
|
||||
styleFunction(layer, styleJson, bucket.layers, undefined, spriteJson, spriteImageUrl, getFont);
|
||||
layers.push(layer);
|
||||
});
|
||||
worker.postMessage({action: 'request-render'});
|
||||
worker.postMessage({action: 'requestRender'});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -97,11 +99,10 @@ function loadStyles() {
|
||||
|
||||
const tileQueue = new TileQueue(
|
||||
(tile, tileSourceKey, tileCenter, tileResolution) => tilePriorityFunction(frameState, tile, tileSourceKey, tileCenter, tileResolution),
|
||||
() => worker.postMessage({action: 'request-render'}));
|
||||
() => worker.postMessage({action: 'requestRender'}));
|
||||
|
||||
const maxTotalLoading = 8;
|
||||
const maxNewLoads = 2;
|
||||
let rendering = false;
|
||||
|
||||
worker.addEventListener('message', event => {
|
||||
if (event.data.action !== 'render') {
|
||||
@@ -114,34 +115,22 @@ worker.addEventListener('message', event => {
|
||||
}
|
||||
frameState.tileQueue = tileQueue;
|
||||
frameState.viewState.projection.__proto__ = Projection.prototype;
|
||||
if (rendering) {
|
||||
return;
|
||||
}
|
||||
rendering = true;
|
||||
requestAnimationFrame(() => {
|
||||
let rendered = false;
|
||||
layers.forEach(layer => {
|
||||
if (inView(layer.getLayerState(), frameState.viewState)) {
|
||||
rendered = true;
|
||||
const renderer = layer.getRenderer();
|
||||
renderer.renderFrame(frameState, canvas);
|
||||
}
|
||||
});
|
||||
rendering = false;
|
||||
if (!rendered) {
|
||||
return;
|
||||
layers.forEach(layer => {
|
||||
if (inView(layer.getLayerState(), frameState.viewState)) {
|
||||
const renderer = layer.getRenderer();
|
||||
renderer.renderFrame(frameState, canvas);
|
||||
}
|
||||
renderDeclutterItems(frameState, null);
|
||||
if (tileQueue.getTilesLoading() < maxTotalLoading) {
|
||||
tileQueue.reprioritize();
|
||||
tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);
|
||||
}
|
||||
const imageData = canvas.transferToImageBitmap();
|
||||
worker.postMessage({
|
||||
action: 'rendered',
|
||||
imageData: imageData,
|
||||
transform: rendererTransform,
|
||||
frameState: JSON.parse(stringify(frameState))
|
||||
}, [imageData]);
|
||||
});
|
||||
renderDeclutterItems(frameState, null);
|
||||
if (tileQueue.getTilesLoading() < maxTotalLoading) {
|
||||
tileQueue.reprioritize();
|
||||
tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);
|
||||
}
|
||||
const imageData = canvas.transferToImageBitmap();
|
||||
worker.postMessage({
|
||||
action: 'rendered',
|
||||
imageData: imageData,
|
||||
transform: rendererTransform,
|
||||
frameState: JSON.parse(stringify(frameState))
|
||||
}, [imageData]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user