Example cleanup

This commit is contained in:
Andreas Hocevar
2020-03-23 12:46:06 +01:00
parent 828becf68e
commit 0e1af6836f
4 changed files with 114 additions and 143 deletions
+61 -68
View File
@@ -7,81 +7,35 @@ import {getTilePriority as tilePriorityFunction} from '../src/ol/TileQueue.js';
import {renderDeclutterItems} from '../src/ol/render.js';
import styleFunction from 'ol-mapbox-style/dist/stylefunction.js';
import {inView} from '../src/ol/layer/Layer.js';
import stringify from 'json-stringify-safe';
/** @type {any} */
const worker = self;
let frameState, pixelRatio;
let frameState, pixelRatio, rendererTransform;
const canvas = new OffscreenCanvas(1, 1);
function getCircularReplacer() {
const seen = new WeakSet();
return function(key, value) {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return '[circular]';
}
seen.add(value);
}
return value;
};
}
function getTilePriority(tile, tileSourceKey, tileCenter, tileResolution) {
return tilePriorityFunction(frameState, tile, tileSourceKey, tileCenter, tileResolution);
}
const landcover = new VectorTileLayer({
visible: false,
declutter: true,
maxZoom: 9,
source: new VectorTileSource({
const sources = {
landcover: new VectorTileSource({
maxZoom: 9,
format: new MVT(),
url: 'https://api.maptiler.com/tiles/landcover/{z}/{x}/{y}.pbf?key=get_your_own_D6rA4zTHduk6KOKTXzGB'
})
});
const contours = new VectorTileLayer({
visible: false,
declutter: true,
minZoom: 9,
maxZoom: 14,
source: new VectorTileSource({
}),
contours: new VectorTileSource({
minZoom: 9,
maxZoom: 14,
format: new MVT(),
url: 'https://api.maptiler.com/tiles/contours/{z}/{x}/{y}.pbf?key=get_your_own_D6rA4zTHduk6KOKTXzGB'
})
});
const openmaptiles = new VectorTileLayer({
visible: false,
declutter: true,
source: new VectorTileSource({
}),
openmaptiles: new VectorTileSource({
format: new MVT(),
maxZoom: 14,
url: 'https://api.maptiler.com/tiles/v3/{z}/{x}/{y}.pbf?key=get_your_own_D6rA4zTHduk6KOKTXzGB'
})
});
const layers = [landcover, contours, openmaptiles];
let rendererTransform;
layers.forEach(layer => {
layer.once('change', () => {
layer.setVisible(true);
worker.postMessage({action: 'request-render'});
});
layer.getRenderer().useContainer = function(target, transform) {
this.containerReused = this.getLayer() !== layers[0];
target.style = {};
this.canvas = target;
this.context = target.getContext('2d');
this.container = {
firstElementChild: target
};
rendererTransform = transform;
};
});
};
const layers = [];
// Font replacement so we do not need to load web fonts in the worker
function getFont(font) {
return font[0]
.replace('Noto Sans', 'serif')
@@ -90,23 +44,63 @@ function getFont(font) {
function loadStyles() {
const styleUrl = 'https://api.maptiler.com/maps/topo/style.json?key=get_your_own_D6rA4zTHduk6KOKTXzGB';
fetch(styleUrl).then(data => data.json()).then(styleJson => {
const buckets = [];
let currentSource;
styleJson.layers.forEach(layer => {
if (!layer.source) {
return;
}
if (currentSource !== layer.source) {
currentSource = layer.source;
buckets.push({
source: layer.source,
layers: []
});
}
buckets[buckets.length - 1].layers.push(layer.id);
});
const spriteUrl = styleJson.sprite + (pixelRatio > 1 ? '@2x' : '') + '.json';
const spriteImageUrl = styleJson.sprite + (pixelRatio > 1 ? '@2x' : '') + '.png';
fetch(spriteUrl).then(data => data.json()).then(spriteJson => {
styleFunction(landcover, styleJson, 'landcover', undefined, spriteJson, spriteImageUrl, getFont);
styleFunction(contours, styleJson, 'contours', undefined, spriteJson, spriteImageUrl, getFont);
styleFunction(openmaptiles, styleJson, 'openmaptiles', undefined, spriteJson, spriteImageUrl, getFont);
buckets.forEach(bucket => {
const source = sources[bucket.source];
if (!source) {
return;
}
const layer = new VectorTileLayer({
declutter: true,
source,
minZoom: source.getTileGrid().getMinZoom()
});
layer.getRenderer().useContainer = function(target, transform) {
this.containerReused = this.getLayer() !== layers[0];
target.style = {};
this.canvas = target;
this.context = target.getContext('2d');
this.container = {
firstElementChild: target
};
rendererTransform = transform;
};
styleFunction(layer, styleJson, bucket.layers, undefined, spriteJson, spriteImageUrl, getFont);
layers.push(layer);
});
worker.postMessage({action: 'request-render'});
});
});
}
const tileQueue = new TileQueue(getTilePriority, () => {
worker.postMessage({action: 'request-render'});
});
// Minimal map-like functionality for rendering
const tileQueue = new TileQueue(
(tile, tileSourceKey, tileCenter, tileResolution) => tilePriorityFunction(frameState, tile, tileSourceKey, tileCenter, tileResolution),
() => worker.postMessage({action: 'request-render'}));
const maxTotalLoading = 8;
const maxNewLoads = 2;
let rendering = false;
worker.addEventListener('message', event => {
@@ -124,7 +118,7 @@ worker.addEventListener('message', event => {
return;
}
rendering = true;
requestAnimationFrame(function() {
requestAnimationFrame(() => {
let rendered = false;
layers.forEach(layer => {
if (inView(layer.getLayerState(), frameState.viewState)) {
@@ -139,7 +133,7 @@ worker.addEventListener('message', event => {
}
renderDeclutterItems(frameState, null);
if (tileQueue.getTilesLoading() < maxTotalLoading) {
tileQueue.reprioritize(); // FIXME only call if view has changed
tileQueue.reprioritize();
tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);
}
const imageData = canvas.transferToImageBitmap();
@@ -147,8 +141,7 @@ worker.addEventListener('message', event => {
action: 'rendered',
imageData: imageData,
transform: rendererTransform,
frameState: JSON.parse(JSON.stringify(frameState, getCircularReplacer()))
frameState: JSON.parse(stringify(frameState))
}, [imageData]);
});
});