import Map from '../src/ol/Map.js'; import View from '../src/ol/View.js'; import Layer from '../src/ol/layer/Layer.js'; import Worker from 'worker-loader!./offscreen-canvas.worker.js'; //eslint-disable-line import {compose, create} from '../src/ol/transform.js'; import {createTransformString} from '../src/ol/render/canvas.js'; import {createXYZ} from '../src/ol/tilegrid.js'; import {FullScreen} from '../src/ol/control.js'; import stringify from 'json-stringify-safe'; const worker = new Worker(); let container, transformContainer, canvas, workerFrameState, mainThreadFrameState; // Transform the container to account for the differnece between the (newer) // main thread frameState and the (older) worker frameState function updateContainerTransform() { if (workerFrameState) { const viewState = mainThreadFrameState.viewState; const renderedViewState = workerFrameState.viewState; const center = viewState.center; const resolution = viewState.resolution; const rotation = viewState.rotation; const renderedCenter = renderedViewState.center; const renderedResolution = renderedViewState.resolution; const renderedRotation = renderedViewState.rotation; const transform = create(); // Skip the extra transform for rotated views, because it will not work // correctly in that case if (!rotation) { compose(transform, (renderedCenter[0] - center[0]) / resolution, (center[1] - renderedCenter[1]) / resolution, renderedResolution / resolution, renderedResolution / resolution, rotation - renderedRotation, 0, 0); } transformContainer.style.transform = createTransformString(transform); } } const map = new Map({ layers: [ new Layer({ render: function(frameState) { if (!container) { container = document.createElement('div'); container.style.position = 'absolute'; container.style.width = '100%'; container.style.height = '100%'; transformContainer = document.createElement('div'); transformContainer.style.position = 'absolute'; transformContainer.style.width = '100%'; transformContainer.style.height = '100%'; container.appendChild(transformContainer); canvas = document.createElement('canvas'); canvas.style.position = 'absolute'; canvas.style.left = '0'; canvas.style.transformOrigin = 'top left'; transformContainer.appendChild(canvas); } mainThreadFrameState = frameState; updateContainerTransform(); worker.postMessage({ action: 'render', frameState: JSON.parse(stringify(frameState)) }); return container; } }) ], target: 'map', view: new View({ resolutions: createXYZ({tileSize: 512}).getResolutions89, center: [0, 0], zoom: 2 }) }); map.addControl(new FullScreen()); // Worker messaging and actions worker.addEventListener('message', message => { if (message.data.action === 'loadImage') { // Image loader for ol-mapbox-style const image = new Image(); image.crossOrigin = 'anonymous'; image.addEventListener('load', function() { createImageBitmap(image, 0, 0, image.width, image.height).then(imageBitmap => { worker.postMessage({ action: 'imageLoaded', image: imageBitmap, src: message.data.src }, [imageBitmap]); }); }); image.src = event.data.src; } else if (message.data.action === 'request-render') { // 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(); } });