Various references were kept, preventing the layer and underlying renderer and webgl context to be garbage collected. Also, the Helper was simplified because it turns out deleting manually all Webgl objects is useless: these objects will be released when the context is garbage collected anyway. Note: this touches the Layer and BaseLayer classes, as the following were preventing the layer from being garbage collected: * layer reference in the `state_` object in BaseLayer * dangling listener for source change in Layer
170 lines
3.8 KiB
JavaScript
170 lines
3.8 KiB
JavaScript
import Map from '../src/ol/Map.js';
|
|
import View from '../src/ol/View.js';
|
|
import TileLayer from '../src/ol/layer/Tile.js';
|
|
import WebGLPointsLayer from '../src/ol/layer/WebGLPoints.js';
|
|
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
|
import Vector from '../src/ol/source/Vector.js';
|
|
import OSM from '../src/ol/source/OSM.js';
|
|
|
|
const vectorSource = new Vector({
|
|
url: 'data/geojson/world-cities.geojson',
|
|
format: new GeoJSON()
|
|
});
|
|
|
|
const predefinedStyles = {
|
|
'icons': {
|
|
symbol: {
|
|
symbolType: 'image',
|
|
src: 'data/icon.png',
|
|
size: [18, 28],
|
|
color: 'lightyellow',
|
|
rotateWithView: false,
|
|
offset: [0, 9]
|
|
}
|
|
},
|
|
'triangles': {
|
|
symbol: {
|
|
symbolType: 'triangle',
|
|
size: 18,
|
|
color: [
|
|
'interpolate',
|
|
['linear'],
|
|
['get', 'population'],
|
|
20000, '#5aca5b',
|
|
300000, '#ff6a19'
|
|
],
|
|
rotateWithView: true
|
|
}
|
|
},
|
|
'triangles-latitude': {
|
|
symbol: {
|
|
symbolType: 'triangle',
|
|
size: [
|
|
'interpolate',
|
|
['linear'],
|
|
['get', 'population'],
|
|
40000, 12,
|
|
2000000, 24
|
|
],
|
|
color: [
|
|
'interpolate',
|
|
['linear'],
|
|
['get', 'latitude'],
|
|
-60, '#ff14c3',
|
|
-20, '#ff621d',
|
|
20, '#ffed02',
|
|
60, '#00ff67'
|
|
],
|
|
offset: [0, 0],
|
|
opacity: 0.95
|
|
}
|
|
},
|
|
'circles': {
|
|
symbol: {
|
|
symbolType: 'circle',
|
|
size: [
|
|
'interpolate',
|
|
['linear'],
|
|
['get', 'population'],
|
|
40000, 8,
|
|
2000000, 28
|
|
],
|
|
color: '#006688',
|
|
rotateWithView: false,
|
|
offset: [0, 0],
|
|
opacity: [
|
|
'interpolate',
|
|
['linear'],
|
|
['get', 'population'],
|
|
40000, 0.6,
|
|
2000000, 0.92
|
|
]
|
|
}
|
|
},
|
|
'circles-zoom': {
|
|
symbol: {
|
|
symbolType: 'circle',
|
|
size: [
|
|
'interpolate',
|
|
['exponential', 2.5],
|
|
['zoom'],
|
|
2, 1,
|
|
14, 32
|
|
],
|
|
color: '#240572',
|
|
offset: [0, 0],
|
|
opacity: 0.95
|
|
}
|
|
}
|
|
};
|
|
|
|
const map = new Map({
|
|
layers: [
|
|
new TileLayer({
|
|
source: new OSM()
|
|
})
|
|
],
|
|
target: document.getElementById('map'),
|
|
view: new View({
|
|
center: [0, 0],
|
|
zoom: 2
|
|
})
|
|
});
|
|
|
|
let literalStyle;
|
|
let pointsLayer;
|
|
function refreshLayer(newStyle) {
|
|
const previousLayer = pointsLayer;
|
|
pointsLayer = new WebGLPointsLayer({
|
|
source: vectorSource,
|
|
style: newStyle,
|
|
disableHitDetection: true
|
|
});
|
|
map.addLayer(pointsLayer);
|
|
|
|
if (previousLayer) {
|
|
map.removeLayer(previousLayer);
|
|
previousLayer.dispose();
|
|
}
|
|
literalStyle = newStyle;
|
|
}
|
|
|
|
const spanValid = document.getElementById('style-valid');
|
|
const spanInvalid = document.getElementById('style-invalid');
|
|
function setStyleStatus(errorMsg) {
|
|
const isError = typeof errorMsg === 'string';
|
|
spanValid.style.display = errorMsg === null ? 'initial' : 'none';
|
|
spanInvalid.firstElementChild.innerText = isError ? errorMsg : '';
|
|
spanInvalid.style.display = isError ? 'initial' : 'none';
|
|
}
|
|
|
|
const editor = document.getElementById('style-editor');
|
|
editor.addEventListener('input', function() {
|
|
const textStyle = editor.value;
|
|
try {
|
|
const newLiteralStyle = JSON.parse(textStyle);
|
|
if (JSON.stringify(newLiteralStyle) !== JSON.stringify(literalStyle)) {
|
|
refreshLayer(newLiteralStyle);
|
|
}
|
|
setStyleStatus(null);
|
|
} catch (e) {
|
|
setStyleStatus(e.message);
|
|
}
|
|
});
|
|
|
|
const select = document.getElementById('style-select');
|
|
select.value = 'circles';
|
|
function onSelectChange() {
|
|
const style = select.value;
|
|
const newLiteralStyle = predefinedStyles[style];
|
|
editor.value = JSON.stringify(newLiteralStyle, null, 2);
|
|
try {
|
|
refreshLayer(newLiteralStyle);
|
|
setStyleStatus();
|
|
} catch (e) {
|
|
setStyleStatus(e.message);
|
|
}
|
|
}
|
|
onSelectChange();
|
|
select.addEventListener('change', onSelectChange);
|