Merge branch 'master' into patch-4
This commit is contained in:
@@ -6,7 +6,7 @@ docs: >
|
||||
<p>When the Bing Maps tile service doesn't have tiles for a given resolution and region it returns "placeholder" tiles indicating that. Zoom the map beyond level 19 to see the "placeholder" tiles. If you want OpenLayers to display stretched tiles in place of "placeholder" tiles beyond zoom level 19 then set <code>maxZoom</code> to <code>19</code> in the options passed to <code>ol/source/BingMaps</code>.</p>
|
||||
tags: "bing, bing-maps"
|
||||
cloak:
|
||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
||||
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
|
||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -18,7 +18,7 @@ for (i = 0, ii = styles.length; i < ii; ++i) {
|
||||
visible: false,
|
||||
preload: Infinity,
|
||||
source: new BingMaps({
|
||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
||||
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
|
||||
imagerySet: styles[i]
|
||||
// use maxZoom 19 to see stretched tiles instead of the BingMaps
|
||||
// "no photos at this zoom level" tiles
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<rect width="20" height="20" style="fill:#fff" />
|
||||
<rect width="20" height="20" style="fill:#fff; stroke-width:4px; stroke:#000" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 194 B After Width: | Height: | Size: 225 B |
@@ -1,7 +1,7 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Earthquakes with custom symbols
|
||||
shortdesc: Demonstrates the use of `toCanvas` to create custom icon symbols.
|
||||
shortdesc: Demonstrates the use of `toContext` to create custom icon symbols.
|
||||
docs: >
|
||||
This example parses a KML file and renders the features as a vector layer. The layer is given a <code>style</code> that renders earthquake locations with a custom lightning symbol and a size relative to their magnitude.
|
||||
tags: "KML, vector, style, canvas, symbol"
|
||||
|
||||
@@ -25,6 +25,7 @@ rome.setStyle(new Style({
|
||||
image: new Icon({
|
||||
color: '#8959A8',
|
||||
crossOrigin: 'anonymous',
|
||||
imgSize: [20, 20],
|
||||
src: 'data/square.svg'
|
||||
})
|
||||
}));
|
||||
|
||||
3
examples/layer-clipping-vector.css
Normal file
3
examples/layer-clipping-vector.css
Normal file
@@ -0,0 +1,3 @@
|
||||
#map {
|
||||
background: transparent;
|
||||
}
|
||||
9
examples/layer-clipping-vector.html
Normal file
9
examples/layer-clipping-vector.html
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Vector Clipping Layer
|
||||
shortdesc: Vector Clipping Layer example
|
||||
docs: >
|
||||
Example of a clipping layer based on a vector source
|
||||
tags: "clipping, openstreetmap, vector"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
46
examples/layer-clipping-vector.js
Normal file
46
examples/layer-clipping-vector.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import VectorSource from '../src/ol/source/Vector.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
import OSM from '../src/ol/source/OSM.js';
|
||||
import {Fill, Style} from '../src/ol/style.js';
|
||||
import {getVectorContext} from '../src/ol/render.js';
|
||||
import {fromLonLat} from '../src/ol/proj.js';
|
||||
|
||||
const base = new TileLayer({
|
||||
source: new OSM()
|
||||
});
|
||||
|
||||
const clipLayer = new VectorLayer({
|
||||
style: null,
|
||||
source: new VectorSource({
|
||||
url:
|
||||
'./data/geojson/switzerland.geojson',
|
||||
format: new GeoJSON()
|
||||
})
|
||||
});
|
||||
|
||||
const style = new Style({
|
||||
fill: new Fill({
|
||||
color: 'black'
|
||||
})
|
||||
});
|
||||
|
||||
base.on('postrender', function(e) {
|
||||
e.context.globalCompositeOperation = 'destination-in';
|
||||
const vectorContext = getVectorContext(e);
|
||||
clipLayer.getSource().forEachFeature(function(feature) {
|
||||
vectorContext.drawFeature(feature, style);
|
||||
});
|
||||
e.context.globalCompositeOperation = 'source-over';
|
||||
});
|
||||
|
||||
const map = new Map({
|
||||
layers: [base, clipLayer],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: fromLonLat([8.23, 46.86]),
|
||||
zoom: 7
|
||||
})
|
||||
});
|
||||
6
examples/mapbox-style.css
Normal file
6
examples/mapbox-style.css
Normal file
@@ -0,0 +1,6 @@
|
||||
.ol-rotate {
|
||||
left: .5em;
|
||||
bottom: .5em;
|
||||
top: unset;
|
||||
right: unset;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
layout: example-verbatim.html
|
||||
layout: example.html
|
||||
title: Vector tiles created from a Mapbox Style object
|
||||
shortdesc: Example of using ol-mapbox-style with tiles from maptiler.com.
|
||||
docs: >
|
||||
@@ -10,27 +10,4 @@ cloak:
|
||||
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||
---
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
|
||||
<title>Mapbox Style objects with ol-mapbox-style</title>
|
||||
<link rel="stylesheet" href="../css/ol.css" type="text/css">
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch,String.prototype.startsWith,Object.assign"></script>
|
||||
<style type="text/css">
|
||||
html, body, .map {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map" class="map"></div>
|
||||
<script src="common.js"></script>
|
||||
<script src="mapbox-style.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import apply from 'ol-mapbox-style';
|
||||
import FullScreen from '../src/ol/control/FullScreen.js';
|
||||
|
||||
apply('map', 'https://api.maptiler.com/maps/topo/style.json?key=get_your_own_D6rA4zTHduk6KOKTXzGB');
|
||||
apply('map', 'https://api.maptiler.com/maps/topo/style.json?key=get_your_own_D6rA4zTHduk6KOKTXzGB').then(function(map) {
|
||||
map.addControl(new FullScreen());
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ title: Full-Screen Mobile
|
||||
shortdesc: Example of a full screen map.
|
||||
tags: "fullscreen, geolocation, mobile"
|
||||
cloak:
|
||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
||||
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
|
||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
||||
---
|
||||
<!doctype html>
|
||||
|
||||
@@ -14,7 +14,7 @@ const map = new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new BingMaps({
|
||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
||||
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
|
||||
imagerySet: 'RoadOnDemand'
|
||||
})
|
||||
})
|
||||
|
||||
9
examples/offscreen-canvas.css
Normal file
9
examples/offscreen-canvas.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.map {
|
||||
background: rgba(232, 230, 223, 1);
|
||||
}
|
||||
.ol-rotate {
|
||||
left: .5em;
|
||||
bottom: .5em;
|
||||
top: unset;
|
||||
right: unset;
|
||||
}
|
||||
10
examples/offscreen-canvas.html
Normal file
10
examples/offscreen-canvas.html
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Vector tiles rendered in an offscreen canvas
|
||||
shortdesc: Example of a map that delegates rendering to a worker.
|
||||
docs: >
|
||||
The map in this example is rendered in a web worker, using `OffscreenCanvas`. **Note:** This is currently only supported in Chrome and Edge.
|
||||
tags: "worker, offscreencanvas, vector-tiles"
|
||||
experimental: true
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
125
examples/offscreen-canvas.js
Normal file
125
examples/offscreen-canvas.js
Normal file
@@ -0,0 +1,125 @@
|
||||
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';
|
||||
import Source from '../src/ol/source/Source.js';
|
||||
|
||||
const worker = new Worker();
|
||||
|
||||
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
|
||||
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();
|
||||
if (!rendering) {
|
||||
rendering = true;
|
||||
worker.postMessage({
|
||||
action: 'render',
|
||||
frameState: JSON.parse(stringify(frameState))
|
||||
});
|
||||
} else {
|
||||
frameState.animate = true;
|
||||
}
|
||||
return container;
|
||||
},
|
||||
source: new Source({
|
||||
attributions: [
|
||||
'<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a>',
|
||||
'<a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>'
|
||||
]
|
||||
})
|
||||
})
|
||||
],
|
||||
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 === 'requestRender') {
|
||||
// Worker requested a new render frame
|
||||
map.render();
|
||||
} else if (canvas && message.data.action === 'rendered') {
|
||||
// Worker provies a new render frame
|
||||
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;
|
||||
}
|
||||
});
|
||||
136
examples/offscreen-canvas.worker.js
Normal file
136
examples/offscreen-canvas.worker.js
Normal file
@@ -0,0 +1,136 @@
|
||||
import VectorTileLayer from '../src/ol/layer/VectorTile.js';
|
||||
import VectorTileSource from '../src/ol/source/VectorTile.js';
|
||||
import MVT from '../src/ol/format/MVT.js';
|
||||
import {Projection} from '../src/ol/proj.js';
|
||||
import TileQueue from '../src/ol/TileQueue.js';
|
||||
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, 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({
|
||||
maxZoom: 9,
|
||||
format: new MVT(),
|
||||
url: 'https://api.maptiler.com/tiles/landcover/{z}/{x}/{y}.pbf?key=get_your_own_D6rA4zTHduk6KOKTXzGB'
|
||||
}),
|
||||
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'
|
||||
}),
|
||||
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 = [];
|
||||
|
||||
// Font replacement so we do not need to load web fonts in the worker
|
||||
function getFont(font) {
|
||||
return font[0]
|
||||
.replace('Noto Sans', 'serif')
|
||||
.replace('Roboto', 'sans-serif');
|
||||
}
|
||||
|
||||
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 => {
|
||||
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];
|
||||
this.canvas = canvas;
|
||||
this.context = context;
|
||||
this.container = {
|
||||
firstElementChild: canvas
|
||||
};
|
||||
rendererTransform = transform;
|
||||
};
|
||||
styleFunction(layer, styleJson, bucket.layers, undefined, spriteJson, spriteImageUrl, getFont);
|
||||
layers.push(layer);
|
||||
});
|
||||
worker.postMessage({action: 'requestRender'});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Minimal map-like functionality for rendering
|
||||
|
||||
const tileQueue = new TileQueue(
|
||||
(tile, tileSourceKey, tileCenter, tileResolution) => tilePriorityFunction(frameState, tile, tileSourceKey, tileCenter, tileResolution),
|
||||
() => worker.postMessage({action: 'requestRender'}));
|
||||
|
||||
const maxTotalLoading = 8;
|
||||
const maxNewLoads = 2;
|
||||
|
||||
worker.addEventListener('message', event => {
|
||||
if (event.data.action !== 'render') {
|
||||
return;
|
||||
}
|
||||
frameState = event.data.frameState;
|
||||
if (!pixelRatio) {
|
||||
pixelRatio = frameState.pixelRatio;
|
||||
loadStyles();
|
||||
}
|
||||
frameState.tileQueue = tileQueue;
|
||||
frameState.viewState.projection.__proto__ = Projection.prototype;
|
||||
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]);
|
||||
});
|
||||
@@ -6,7 +6,7 @@ docs: >
|
||||
<p>The map on the top preloads low resolution tiles. The map on the bottom does not use any preloading. Try zooming out and panning to see the difference.</p>
|
||||
tags: "preload, bing"
|
||||
cloak:
|
||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
||||
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
|
||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
||||
---
|
||||
<div id="map1" class="map"></div>
|
||||
|
||||
@@ -14,7 +14,7 @@ const map1 = new Map({
|
||||
new TileLayer({
|
||||
preload: Infinity,
|
||||
source: new BingMaps({
|
||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
||||
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
|
||||
imagerySet: 'Aerial'
|
||||
})
|
||||
})
|
||||
@@ -28,7 +28,7 @@ const map2 = new Map({
|
||||
new TileLayer({
|
||||
preload: 0, // default value
|
||||
source: new BingMaps({
|
||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5',
|
||||
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
|
||||
imagerySet: 'AerialWithLabelsOnDemand'
|
||||
})
|
||||
})
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
event.preventDefault();
|
||||
const html = document.getElementById('example-html-source').innerText;
|
||||
const js = document.getElementById('example-js-source').innerText;
|
||||
const workerContainer = document.getElementById('example-worker-source');
|
||||
const worker = workerContainer ? workerContainer.innerText : undefined;
|
||||
const pkgJson = document.getElementById('example-pkg-source').innerText;
|
||||
const form = document.getElementById('codepen-form');
|
||||
|
||||
@@ -68,22 +70,28 @@
|
||||
|
||||
Promise.all(promises)
|
||||
.then(results => {
|
||||
const data = {
|
||||
files: {
|
||||
'index.html': {
|
||||
content: html
|
||||
},
|
||||
'index.js': {
|
||||
content: js
|
||||
},
|
||||
"package.json": {
|
||||
content: pkgJson
|
||||
},
|
||||
'sandbox.config.json': {
|
||||
content: '{"template": "parcel"}'
|
||||
}
|
||||
const files = {
|
||||
'index.html': {
|
||||
content: html
|
||||
},
|
||||
'index.js': {
|
||||
content: js
|
||||
},
|
||||
"package.json": {
|
||||
content: pkgJson
|
||||
},
|
||||
'sandbox.config.json': {
|
||||
content: '{"template": "parcel"}'
|
||||
}
|
||||
};
|
||||
if (worker) {
|
||||
files['worker.js'] = {
|
||||
content: worker
|
||||
}
|
||||
}
|
||||
const data = {
|
||||
files: files
|
||||
};
|
||||
|
||||
for (let i = 0; i < localResources.length; i++) {
|
||||
data.files[localResources[i]] = results[i];
|
||||
|
||||
@@ -309,4 +309,4 @@ function createMapboxStreetsV6Style(Style, Fill, Stroke, Icon, Text) {
|
||||
styles.length = length;
|
||||
return styles;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -160,6 +160,14 @@
|
||||
<pre><legend>index.js</legend><code id="example-js-source" class="language-js">import 'ol/ol.css';
|
||||
{{ js.source }}</code></pre>
|
||||
</div>
|
||||
{{#if worker.source}}
|
||||
<div class="row-fluid">
|
||||
<div class="source-controls">
|
||||
<a class="copy-button" id="copy-worker-button" data-clipboard-target="#example-worker-source"><i class="fa fa-clipboard"></i> Copy</a>
|
||||
</div>
|
||||
<pre><legend>worker.js</legend><code id="example-worker-source" class="language-js">{{ worker.source }}</code></pre>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="row-fluid">
|
||||
<div class="source-controls">
|
||||
<a class="copy-button" id="copy-pkg-button" data-clipboard-target="#example-pkg-source"><i class="fa fa-clipboard"></i> Copy</a>
|
||||
@@ -167,7 +175,6 @@
|
||||
<pre><legend>package.json</legend><code id="example-pkg-source" class="language-js">{{ pkgJson }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="./resources/common.js"></script>
|
||||
<script src="./resources/prism/prism.min.js"></script>
|
||||
{{{ js.tag }}}
|
||||
|
||||
@@ -4,9 +4,9 @@ title: OSM XML
|
||||
shortdesc: Example of using the OSM XML source.
|
||||
docs: >
|
||||
OSM XML vector data is loaded dynamically from a the [Overpass API](http://overpass-api.de) using a bbox strategy. Note that panning and zooming will eventually lead to "Too many requests" errors from the Overpass API.
|
||||
tags: "vector, osmxml, loading, server, strategy, bbox"
|
||||
tags: "vector, osmxml, loading, server, strategy, bbox, maptiler"
|
||||
cloak:
|
||||
- key: As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5
|
||||
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
|
||||
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -4,7 +4,7 @@ import OSMXML from '../src/ol/format/OSMXML.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import {bbox as bboxStrategy} from '../src/ol/loadingstrategy.js';
|
||||
import {transformExtent} from '../src/ol/proj.js';
|
||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
||||
import XYZ from '../src/ol/source/XYZ.js';
|
||||
import VectorSource from '../src/ol/source/Vector.js';
|
||||
import {Circle as CircleStyle, Fill, Stroke, Style} from '../src/ol/style.js';
|
||||
|
||||
@@ -85,8 +85,8 @@ const vectorSource = new VectorSource({
|
||||
vectorSource.addFeatures(features);
|
||||
});
|
||||
const query = '(node(' +
|
||||
epsg4326Extent[1] + ',' + epsg4326Extent[0] + ',' +
|
||||
epsg4326Extent[3] + ',' + epsg4326Extent[2] +
|
||||
epsg4326Extent[1] + ',' + Math.max(epsg4326Extent[0], -180) + ',' +
|
||||
epsg4326Extent[3] + ',' + Math.min(epsg4326Extent[2], 180) +
|
||||
');rel(bn)->.foo;way(bn);node(w)->.foo;rel(bw););out meta;';
|
||||
client.send(query);
|
||||
},
|
||||
@@ -110,10 +110,15 @@ const vector = new VectorLayer({
|
||||
}
|
||||
});
|
||||
|
||||
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||
const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> ' +
|
||||
'<a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>';
|
||||
|
||||
const raster = new TileLayer({
|
||||
source: new BingMaps({
|
||||
imagerySet: 'Aerial',
|
||||
key: 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5'
|
||||
source: new XYZ({
|
||||
attributions: attributions,
|
||||
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||
maxZoom: 20
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -208,6 +208,10 @@ ExampleBuilder.prototype.render = async function(dir, chunk) {
|
||||
jsSource = jsSource.replace(new RegExp(entry.key, 'g'), entry.value);
|
||||
}
|
||||
}
|
||||
// Remove worker loader import and modify `new Worker()` to add source
|
||||
jsSource = jsSource.replace(/import Worker from 'worker-loader![^\n]*\n/g, '');
|
||||
jsSource = jsSource.replace('new Worker()', 'new Worker(\'./worker.js\')');
|
||||
|
||||
data.js = {
|
||||
tag: `<script src="${this.common}.js"></script><script src="${jsName}"></script>`,
|
||||
source: jsSource
|
||||
@@ -218,9 +222,33 @@ ExampleBuilder.prototype.render = async function(dir, chunk) {
|
||||
data.js.tag = prelude + data.js.tag;
|
||||
}
|
||||
|
||||
// check for worker js
|
||||
const workerName = `${name}.worker.js`;
|
||||
const workerPath = path.join(dir, workerName);
|
||||
let workerSource;
|
||||
try {
|
||||
workerSource = await readFile(workerPath, readOptions);
|
||||
} catch (err) {
|
||||
// pass
|
||||
}
|
||||
if (workerSource) {
|
||||
// remove "../src/" prefix and ".js" to have the same import syntax as the documentation
|
||||
workerSource = workerSource.replace(/'\.\.\/src\//g, '\'');
|
||||
workerSource = workerSource.replace(/\.js';/g, '\';');
|
||||
if (data.cloak) {
|
||||
for (const entry of data.cloak) {
|
||||
workerSource = workerSource.replace(new RegExp(entry.key, 'g'), entry.value);
|
||||
}
|
||||
}
|
||||
data.worker = {
|
||||
source: workerSource
|
||||
};
|
||||
assets[workerName] = workerSource;
|
||||
}
|
||||
|
||||
data.pkgJson = JSON.stringify({
|
||||
name: name,
|
||||
dependencies: getDependencies(jsSource),
|
||||
dependencies: getDependencies(jsSource + workerSource ? `\n${workerSource}` : ''),
|
||||
devDependencies: {
|
||||
parcel: '1.11.0'
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user