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