Merge branch 'master' into patch-4
This commit is contained in:
@@ -4,10 +4,10 @@ title: Drag-and-Drop Image Vector
|
||||
shortdesc: Example of using the drag-and-drop interaction with image vector rendering.
|
||||
docs: >
|
||||
Example of using the drag-and-drop interaction with an `ol/layer/VectorImage` layer. Drag and drop GPX, GeoJSON, IGC, KML, or TopoJSON files on to the map. Each file is rendered to an image on the client.
|
||||
tags: "drag-and-drop-image-vector, gpx, geojson, igc, kml, topojson, vector, image"
|
||||
tags: "drag-and-drop-image-vector, gpx, geojson, igc, kml, topojson, maptiler, vector, image"
|
||||
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>
|
||||
<div id="info"> </div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import View from '../src/ol/View.js';
|
||||
import {GPX, GeoJSON, IGC, KML, TopoJSON} from '../src/ol/format.js';
|
||||
import {defaults as defaultInteractions, DragAndDrop} from '../src/ol/interaction.js';
|
||||
import {VectorImage as VectorImageLayer, Tile as TileLayer} from '../src/ol/layer.js';
|
||||
import {BingMaps, Vector as VectorSource} from '../src/ol/source.js';
|
||||
import {XYZ, Vector as VectorSource} from '../src/ol/source.js';
|
||||
|
||||
const dragAndDropInteraction = new DragAndDrop({
|
||||
formatConstructors: [
|
||||
@@ -15,13 +15,18 @@ const dragAndDropInteraction = new DragAndDrop({
|
||||
]
|
||||
});
|
||||
|
||||
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 map = new Map({
|
||||
interactions: defaultInteractions().extend([dragAndDropInteraction]),
|
||||
layers: [
|
||||
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
|
||||
})
|
||||
})
|
||||
],
|
||||
|
||||
@@ -4,10 +4,10 @@ title: Drag-and-Drop
|
||||
shortdesc: Example of using the drag-and-drop interaction.
|
||||
docs: >
|
||||
Example of using the drag-and-drop interaction. Drag and drop GPX, GeoJSON, IGC, KML, or TopoJSON files on to the map. There is no projection transform support, so this will only work with data in EPSG:4326 and EPSG:3857.
|
||||
tags: "drag-and-drop, gpx, geojson, igc, kml, topojson"
|
||||
tags: "drag-and-drop, gpx, geojson, igc, kml, topojson, 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>
|
||||
<div id="info"> </div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import View from '../src/ol/View.js';
|
||||
import {GPX, GeoJSON, IGC, KML, TopoJSON} from '../src/ol/format.js';
|
||||
import {defaults as defaultInteractions, DragAndDrop} from '../src/ol/interaction.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import {BingMaps, Vector as VectorSource} from '../src/ol/source.js';
|
||||
import {XYZ, Vector as VectorSource} from '../src/ol/source.js';
|
||||
|
||||
const dragAndDropInteraction = new DragAndDrop({
|
||||
formatConstructors: [
|
||||
@@ -15,13 +15,18 @@ const dragAndDropInteraction = new DragAndDrop({
|
||||
]
|
||||
});
|
||||
|
||||
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 map = new Map({
|
||||
interactions: defaultInteractions().extend([dragAndDropInteraction]),
|
||||
layers: [
|
||||
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
|
||||
})
|
||||
})
|
||||
],
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Custom map element
|
||||
shortdesc: Example of a custom element with a map.
|
||||
docs: >
|
||||
The example creates and registers a custom element, `ol-map`, which contains a simple map. **Note:** Only works in browsers that supports `ShadowRoot`.
|
||||
tags: "es2015, web-component, custom-element, shadow-dom"
|
||||
---
|
||||
<ol-map id="map" class="map"></ol-map>
|
||||
@@ -0,0 +1,43 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import TileLayer from '../src/ol/layer/Tile.js';
|
||||
import OSM from '../src/ol/source/OSM.js';
|
||||
|
||||
class OLComponent extends HTMLElement {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.shadow = this.attachShadow({mode: 'open'});
|
||||
const link = document.createElement('link');
|
||||
link.setAttribute('rel', 'stylesheet');
|
||||
link.setAttribute('href', 'css/ol.css');
|
||||
this.shadow.appendChild(link);
|
||||
const style = document.createElement('style');
|
||||
style.innerText = `
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
this.shadow.appendChild(style);
|
||||
const div = document.createElement('div');
|
||||
div.style.width = '100%';
|
||||
div.style.height = '100%';
|
||||
this.shadow.appendChild(div);
|
||||
|
||||
this.map = new Map({
|
||||
target: div,
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new OSM()
|
||||
})
|
||||
],
|
||||
view: new View({
|
||||
center: [0, 0],
|
||||
zoom: 2
|
||||
})
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('ol-map', OLComponent);
|
||||
@@ -1,6 +0,0 @@
|
||||
.overlay {
|
||||
background-color: yellow;
|
||||
border-radius: 6px;
|
||||
padding: 4px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -3,13 +3,9 @@ layout: example.html
|
||||
title: Map Export
|
||||
shortdesc: Example of exporting a map as a PNG image.
|
||||
docs: >
|
||||
Example of exporting a map as a PNG image. This example use the <a href="https://www.npmjs.com/package/html-to-image">html-to-image</a>
|
||||
library.
|
||||
Example of exporting a map as a PNG image.
|
||||
tags: "export, png, openstreetmap"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
<div style="display: none;">
|
||||
<div class="overlay" id="null">Null Island</div>
|
||||
</div>
|
||||
<a id="export-png" class="btn btn-default"><i class="fa fa-download"></i> Download PNG</a>
|
||||
<a id="image-download" download="map.png"></a>
|
||||
|
||||
+27
-24
@@ -1,12 +1,9 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import Overlay from '../src/ol/Overlay.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
||||
|
||||
import {toPng} from 'html-to-image';
|
||||
|
||||
const map = new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
@@ -16,7 +13,8 @@ const map = new Map({
|
||||
source: new VectorSource({
|
||||
url: 'data/geojson/countries.geojson',
|
||||
format: new GeoJSON()
|
||||
})
|
||||
}),
|
||||
opacity: 0.5
|
||||
})
|
||||
],
|
||||
target: 'map',
|
||||
@@ -26,28 +24,33 @@ const map = new Map({
|
||||
})
|
||||
});
|
||||
|
||||
map.addOverlay(new Overlay({
|
||||
position: [0, 0],
|
||||
element: document.getElementById('null')
|
||||
}));
|
||||
|
||||
|
||||
// export options for html-to-image.
|
||||
// See: https://github.com/bubkoo/html-to-image#options
|
||||
const exportOptions = {
|
||||
filter: function(element) {
|
||||
return element.className ? element.className.indexOf('ol-control') === -1 : true;
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById('export-png').addEventListener('click', function() {
|
||||
map.once('rendercomplete', function() {
|
||||
toPng(map.getTargetElement(), exportOptions)
|
||||
.then(function(dataURL) {
|
||||
const link = document.getElementById('image-download');
|
||||
link.href = dataURL;
|
||||
link.click();
|
||||
});
|
||||
const mapCanvas = document.createElement('canvas');
|
||||
const size = map.getSize();
|
||||
mapCanvas.width = size[0];
|
||||
mapCanvas.height = size[1];
|
||||
const mapContext = mapCanvas.getContext('2d');
|
||||
Array.prototype.forEach.call(document.querySelectorAll('.ol-layer canvas'), function(canvas) {
|
||||
if (canvas.width > 0) {
|
||||
const opacity = canvas.parentNode.style.opacity;
|
||||
mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
|
||||
const transform = canvas.style.transform;
|
||||
// Get the transform parameters from the style's transform matrix
|
||||
const matrix = transform.match(/^matrix\(([^\(]*)\)$/)[1].split(',').map(Number);
|
||||
// Apply the transform to the export map context
|
||||
CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix);
|
||||
mapContext.drawImage(canvas, 0, 0);
|
||||
}
|
||||
});
|
||||
if (navigator.msSaveBlob) {
|
||||
// link download attribuute does not work on MS browsers
|
||||
navigator.msSaveBlob(mapCanvas.msToBlob(), 'map.png');
|
||||
} else {
|
||||
const link = document.getElementById('image-download');
|
||||
link.href = mapCanvas.toDataURL();
|
||||
link.click();
|
||||
}
|
||||
});
|
||||
map.renderSync();
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ docs: >
|
||||
Example of exporting a map as a PDF using the <a href="https://github.com/MrRio/jsPDF" target="_blank">jsPDF</a> library.
|
||||
tags: "export, pdf, openstreetmap"
|
||||
resources:
|
||||
- https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.2.61/jspdf.min.js
|
||||
- https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js
|
||||
---
|
||||
<div class="row-fluid">
|
||||
<div class="span12">
|
||||
|
||||
+25
-22
@@ -4,8 +4,6 @@ import WKT from '../src/ol/format/WKT.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
||||
|
||||
import {toJpeg} from 'html-to-image';
|
||||
|
||||
const raster = new TileLayer({
|
||||
source: new OSM()
|
||||
});
|
||||
@@ -20,7 +18,8 @@ feature.getGeometry().transform('EPSG:4326', 'EPSG:3857');
|
||||
const vector = new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: [feature]
|
||||
})
|
||||
}),
|
||||
opacity: 0.5
|
||||
});
|
||||
|
||||
|
||||
@@ -44,14 +43,6 @@ const dims = {
|
||||
};
|
||||
|
||||
|
||||
// export options for html-to-image.
|
||||
// See: https://github.com/bubkoo/html-to-image#options
|
||||
const exportOptions = {
|
||||
filter: function(element) {
|
||||
return element.className.indexOf('ol-control') === -1;
|
||||
}
|
||||
};
|
||||
|
||||
const exportButton = document.getElementById('export-pdf');
|
||||
|
||||
exportButton.addEventListener('click', function() {
|
||||
@@ -68,18 +59,30 @@ exportButton.addEventListener('click', function() {
|
||||
const viewResolution = map.getView().getResolution();
|
||||
|
||||
map.once('rendercomplete', function() {
|
||||
exportOptions.width = width;
|
||||
exportOptions.height = height;
|
||||
toJpeg(map.getViewport(), exportOptions).then(function(dataUrl) {
|
||||
const pdf = new jsPDF('landscape', undefined, format);
|
||||
pdf.addImage(dataUrl, 'JPEG', 0, 0, dim[0], dim[1]);
|
||||
pdf.save('map.pdf');
|
||||
// Reset original map size
|
||||
map.setSize(size);
|
||||
map.getView().setResolution(viewResolution);
|
||||
exportButton.disabled = false;
|
||||
document.body.style.cursor = 'auto';
|
||||
const mapCanvas = document.createElement('canvas');
|
||||
mapCanvas.width = width;
|
||||
mapCanvas.height = height;
|
||||
const mapContext = mapCanvas.getContext('2d');
|
||||
Array.prototype.forEach.call(document.querySelectorAll('.ol-layer canvas'), function(canvas) {
|
||||
if (canvas.width > 0) {
|
||||
const opacity = canvas.parentNode.style.opacity;
|
||||
mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
|
||||
const transform = canvas.style.transform;
|
||||
// Get the transform parameters from the style's transform matrix
|
||||
const matrix = transform.match(/^matrix\(([^\(]*)\)$/)[1].split(',').map(Number);
|
||||
// Apply the transform to the export map context
|
||||
CanvasRenderingContext2D.prototype.setTransform.apply(mapContext, matrix);
|
||||
mapContext.drawImage(canvas, 0, 0);
|
||||
}
|
||||
});
|
||||
const pdf = new jsPDF('landscape', undefined, format);
|
||||
pdf.addImage(mapCanvas.toDataURL('image/jpeg'), 'JPEG', 0, 0, dim[0], dim[1]);
|
||||
pdf.save('map.pdf');
|
||||
// Reset original map size
|
||||
map.setSize(size);
|
||||
map.getView().setResolution(viewResolution);
|
||||
exportButton.disabled = false;
|
||||
document.body.style.cursor = 'auto';
|
||||
});
|
||||
|
||||
// Set print size
|
||||
|
||||
@@ -6,10 +6,10 @@ docs: >
|
||||
<p>Layer rendering can be manipulated in <code>prerender</code> and <code>postrender</code> event listeners.
|
||||
These listeners get an event with a reference to the Canvas rendering context.
|
||||
In this example, the <code>postrender</code> listener applies a filter to the image data.</p>
|
||||
tags: "filter, image manipulation"
|
||||
tags: "filter, image manipulation, 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>
|
||||
<select id="kernel" name="kernel">
|
||||
|
||||
@@ -2,12 +2,19 @@ import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import TileLayer from '../src/ol/layer/Tile.js';
|
||||
import {fromLonLat} from '../src/ol/proj.js';
|
||||
import BingMaps from '../src/ol/source/BingMaps.js';
|
||||
import XYZ from '../src/ol/source/XYZ.js';
|
||||
|
||||
const key = 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5';
|
||||
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 imagery = new TileLayer({
|
||||
source: new BingMaps({key: key, imagerySet: 'Aerial'})
|
||||
source: new XYZ({
|
||||
attributions: attributions,
|
||||
url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key,
|
||||
maxZoom: 20,
|
||||
crossOrigin: ''
|
||||
})
|
||||
});
|
||||
|
||||
const map = new Map({
|
||||
|
||||
+3
-3
@@ -4,10 +4,10 @@ title: KML
|
||||
shortdesc: Rendering KML with a vector source.
|
||||
docs: >
|
||||
This example uses the <code>ol/format/KML</code> to parse KML for rendering with a vector source.
|
||||
tags: "KML"
|
||||
tags: "KML, 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>
|
||||
<div id="info"> </div>
|
||||
|
||||
+9
-4
@@ -2,13 +2,18 @@ import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import KML from '../src/ol/format/KML.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.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';
|
||||
|
||||
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
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ cloak:
|
||||
<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;
|
||||
|
||||
@@ -5,7 +5,9 @@ shortdesc: Example of some Regular Shape styles.
|
||||
docs: >
|
||||
This example shows how several regular shapes
|
||||
or symbols (representing `x`, `cross`, `star`,
|
||||
`triangle` and `square`) can be created.
|
||||
`triangle`, `square` and `stacked`) can be created.
|
||||
|
||||
Style `stacked` represents possility to stack multiple shapes with offset
|
||||
tags: "vector, symbol, regularshape, style, square, cross, star, triangle, x"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -59,18 +59,39 @@ const styles = {
|
||||
radius2: 0,
|
||||
angle: Math.PI / 4
|
||||
})
|
||||
})
|
||||
}),
|
||||
'stacked': [
|
||||
new Style({
|
||||
image: new RegularShape({
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
points: 4,
|
||||
radius: 5,
|
||||
angle: Math.PI / 4,
|
||||
displacement: [0, 10]
|
||||
})
|
||||
}),
|
||||
new Style({
|
||||
image: new RegularShape({
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
points: 4,
|
||||
radius: 10,
|
||||
angle: Math.PI / 4
|
||||
})
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
const styleKeys = ['x', 'cross', 'star', 'triangle', 'square'];
|
||||
const styleKeys = ['x', 'cross', 'star', 'triangle', 'square', 'stacked'];
|
||||
const count = 250;
|
||||
const features = new Array(count);
|
||||
const e = 4500000;
|
||||
for (let i = 0; i < count; ++i) {
|
||||
const coordinates = [2 * e * Math.random() - e, 2 * e * Math.random() - e];
|
||||
features[i] = new Feature(new Point(coordinates));
|
||||
features[i].setStyle(styles[styleKeys[Math.floor(Math.random() * 5)]]);
|
||||
features[i].setStyle(styles[styleKeys[Math.floor(Math.random() * 6)]]);
|
||||
}
|
||||
|
||||
const source = new VectorSource({
|
||||
|
||||
@@ -8,6 +8,11 @@ docs: >
|
||||
<a href="https://www.mapbox.com/blog/terrain-rgb/">Mapbox Terrain-RGB tiles</a>
|
||||
to "flood" areas below the elevation shown on the sea level slider.
|
||||
</p>
|
||||
<p>
|
||||
<code>ol/source/Raster</code> can take either a tile source or layer.
|
||||
In this case a layer is used to allow disabling at the <code>prerender</code> event
|
||||
of image smoothing which would change the precise elevation values set in the pixels.
|
||||
</p>
|
||||
tags: "raster, pixel operation, flood"
|
||||
cloak:
|
||||
- key: pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg
|
||||
|
||||
@@ -22,9 +22,15 @@ function flood(pixels, data) {
|
||||
}
|
||||
|
||||
const key = 'pk.eyJ1IjoidHNjaGF1YiIsImEiOiJjaW5zYW5lNHkxMTNmdWttM3JyOHZtMmNtIn0.CDIBD8H-G2Gf-cPkIuWtRg';
|
||||
const elevation = new XYZ({
|
||||
url: 'https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=' + key,
|
||||
crossOrigin: 'anonymous'
|
||||
const elevation = new TileLayer({
|
||||
source: new XYZ({
|
||||
url: 'https://api.mapbox.com/v4/mapbox.terrain-rgb/{z}/{x}/{y}.pngraw?access_token=' + key,
|
||||
crossOrigin: 'anonymous'
|
||||
})
|
||||
});
|
||||
elevation.on('prerender', function(evt) {
|
||||
evt.context.imageSmoothingEnabled = false;
|
||||
evt.context.msImageSmoothingEnabled = false;
|
||||
});
|
||||
|
||||
const raster = new RasterSource({
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ docs: >
|
||||
tags: "draw, edit, modify, vector, snap"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
<form id="options-form" automplete="off">
|
||||
<form id="options-form" autocomplete="off">
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="interaction" value="draw" id="draw" checked>
|
||||
|
||||
@@ -67,9 +67,9 @@
|
||||
<link rel="stylesheet" href="./resources/prism/prism.css" type="text/css">
|
||||
<link rel="stylesheet" href="./css/ol.css" type="text/css">
|
||||
<link rel="stylesheet" href="./resources/layout.css" type="text/css">
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,URL"></script>
|
||||
{{{ extraHead.local }}}
|
||||
{{{ css.tag }}}
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,URL"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>
|
||||
<title>{{ title }}</title>
|
||||
</head>
|
||||
@@ -139,7 +139,7 @@
|
||||
<head>
|
||||
<title>{{ title }}</title>
|
||||
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>{{#if extraHead.remote}}
|
||||
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=fetch,requestAnimationFrame,Element.prototype.classList,URL"></script>{{#if extraHead.remote}}
|
||||
{{ indent extraHead.remote spaces=4 }}{{/if}}
|
||||
<style>
|
||||
.map {
|
||||
|
||||
@@ -1,19 +1,5 @@
|
||||
This folder contains example templates. These templates are used to build the examples in the `examples/` folder. The resulting examples are written to the `build/examples` folder.
|
||||
|
||||
Although the main purpose of these examples is to demonstrate how to use the API, they also serve other purposes in the development cycle, and so are not exactly as they would be in normal application code:
|
||||
|
||||
* every time the library changes, they are compiled together with the library as a basic check that they remain in sync with the library
|
||||
|
||||
* they use a special loader script to enable defining at run time which build mode (raw/debug/advanced) to use
|
||||
|
||||
To enable this, examples have the following, not needed in application code:
|
||||
|
||||
* each html file loads `loader.js`; application code would not need this, but would instead load the appropriate library build file, either a hosted version or a custom build
|
||||
|
||||
* each js file starts with `goog.require` functions, used by the compiler; application code would only have these if the code is to be compiled together with the library and/or Closure library
|
||||
|
||||
* some js files use type definitions (comments with @type tags); these are also used by the compiler, and are only needed if the code is to be compiled together with the library
|
||||
|
||||
* html files load `resources/common.js` and some scripts use `common.getRendererFromQueryString()` to set the map renderer; application code would not need these
|
||||
The examples are transpiled to es5. If the name of an example starts with `es2015-`, transpilation will be bypassed. This allows for showing es2015+ features in examples.
|
||||
|
||||
At the bottom of each example generated in the `build/examples` folder, a modified version of its source code is shown. That modified version can be run standalone and is usually used as starting point for users to extend examples into their own application.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Tracing around a polygon
|
||||
shortdesc: Example of setting up a draw interaction to easily snap to an existing feature.
|
||||
docs: >
|
||||
This example showcases how the draw interaction API can be set up to make snapping along
|
||||
an existing geometry easier while preserving topology, which is sometimes called "tracing".
|
||||
When the user clicks on two different points on the Idaho state border,
|
||||
the part of the border comprised between these two points is added to
|
||||
the currently drawn feature.
|
||||
This leverages the `appendCoordinates` method of the `ol/interaction/Draw` interaction.
|
||||
tags: "draw, trace, snap, vector, topology"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
<form class="form-inline">
|
||||
<label>Geometry type </label>
|
||||
<select id="type">
|
||||
<option value="Polygon">Polygon</option>
|
||||
<option value="LineString">LineString</option>
|
||||
<option value="None">None</option>
|
||||
</select>
|
||||
</form>
|
||||
@@ -0,0 +1,253 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import Draw from '../src/ol/interaction/Draw.js';
|
||||
import Snap from '../src/ol/interaction/Snap.js';
|
||||
import Style from '../src/ol/style/Style.js';
|
||||
import Stroke from '../src/ol/style/Stroke.js';
|
||||
import Fill from '../src/ol/style/Fill.js';
|
||||
import GeoJSON from '../src/ol/format/GeoJSON.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
||||
import LineString from '../src/ol/geom/LineString.js';
|
||||
import Feature from '../src/ol/Feature.js';
|
||||
|
||||
// math utilities
|
||||
|
||||
// coordinates; will return the length of the [a, b] segment
|
||||
function length(a, b) {
|
||||
return Math.sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]));
|
||||
}
|
||||
|
||||
// coordinates; will return true if c is on the [a, b] segment
|
||||
function isOnSegment(c, a, b) {
|
||||
const lengthAc = length(a, c);
|
||||
const lengthAb = length(a, b);
|
||||
const dot = ((c[0] - a[0]) * (b[0] - a[0]) + (c[1] - a[1]) * (b[1] - a[1])) / lengthAb;
|
||||
return Math.abs(lengthAc - dot) < 1e-6 && lengthAc < lengthAb;
|
||||
}
|
||||
|
||||
// modulo for negative values, eg: mod(-1, 4) returns 3
|
||||
function mod(a, b) {
|
||||
return ((a % b) + b) % b;
|
||||
}
|
||||
|
||||
// returns a coordinates array which contains the segments of the feature's
|
||||
// outer ring between the start and end points
|
||||
// Note: this assumes the base feature is a single polygon
|
||||
function getPartialRingCoords(feature, startPoint, endPoint) {
|
||||
let polygon = feature.getGeometry();
|
||||
if (polygon.getType() === 'MultiPolygon') {
|
||||
polygon = polygon.getPolygon(0);
|
||||
}
|
||||
const ringCoords = polygon.getLinearRing().getCoordinates();
|
||||
|
||||
let i, pointA, pointB, startSegmentIndex = -1;
|
||||
for (i = 0; i < ringCoords.length; i++) {
|
||||
pointA = ringCoords[i];
|
||||
pointB = ringCoords[mod(i + 1, ringCoords.length)];
|
||||
|
||||
// check if this is the start segment dot product
|
||||
if (isOnSegment(startPoint, pointA, pointB)) {
|
||||
startSegmentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const cwCoordinates = [];
|
||||
let cwLength = 0;
|
||||
const ccwCoordinates = [];
|
||||
let ccwLength = 0;
|
||||
|
||||
// build clockwise coordinates
|
||||
for (i = 0; i < ringCoords.length; i++) {
|
||||
pointA = i === 0 ? startPoint : ringCoords[mod(i + startSegmentIndex, ringCoords.length)];
|
||||
pointB = ringCoords[mod(i + startSegmentIndex + 1, ringCoords.length)];
|
||||
cwCoordinates.push(pointA);
|
||||
|
||||
if (isOnSegment(endPoint, pointA, pointB)) {
|
||||
cwCoordinates.push(endPoint);
|
||||
cwLength += length(pointA, endPoint);
|
||||
break;
|
||||
} else {
|
||||
cwLength += length(pointA, pointB);
|
||||
}
|
||||
}
|
||||
|
||||
// build counter-clockwise coordinates
|
||||
for (i = 0; i < ringCoords.length; i++) {
|
||||
pointA = ringCoords[mod(startSegmentIndex - i, ringCoords.length)];
|
||||
pointB = i === 0 ? startPoint : ringCoords[mod(startSegmentIndex - i + 1, ringCoords.length)];
|
||||
ccwCoordinates.push(pointB);
|
||||
|
||||
if (isOnSegment(endPoint, pointA, pointB)) {
|
||||
ccwCoordinates.push(endPoint);
|
||||
ccwLength += length(endPoint, pointB);
|
||||
break;
|
||||
} else {
|
||||
ccwLength += length(pointA, pointB);
|
||||
}
|
||||
}
|
||||
|
||||
// keep the shortest path
|
||||
return ccwLength < cwLength ? ccwCoordinates : cwCoordinates;
|
||||
}
|
||||
|
||||
|
||||
// layers definition
|
||||
|
||||
const raster = new TileLayer({
|
||||
source: new OSM()
|
||||
});
|
||||
|
||||
// features in this layer will be snapped to
|
||||
const baseVector = new VectorLayer({
|
||||
source: new VectorSource({
|
||||
format: new GeoJSON(),
|
||||
url: 'https://ahocevar.com/geoserver/wfs?service=wfs&request=getfeature&typename=topp:states&cql_filter=STATE_NAME=\'Idaho\'&outputformat=application/json'
|
||||
})
|
||||
});
|
||||
|
||||
// this is were the drawn features go
|
||||
const drawVector = new VectorLayer({
|
||||
source: new VectorSource(),
|
||||
style: new Style({
|
||||
stroke: new Stroke({
|
||||
color: 'rgba(100, 255, 0, 1)',
|
||||
width: 2
|
||||
}),
|
||||
fill: new Fill({
|
||||
color: 'rgba(100, 255, 0, 0.3)'
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
// this line only appears when we're tracing a feature outer ring
|
||||
const previewLine = new Feature({
|
||||
geometry: new LineString([])
|
||||
});
|
||||
const previewVector = new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: [previewLine]
|
||||
}),
|
||||
style: new Style({
|
||||
stroke: new Stroke({
|
||||
color: 'rgba(255, 0, 0, 1)',
|
||||
width: 2
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
const map = new Map({
|
||||
layers: [raster, baseVector, drawVector, previewVector],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: [-12986427, 5678422],
|
||||
zoom: 5
|
||||
})
|
||||
});
|
||||
|
||||
let drawInteraction, tracingFeature, startPoint, endPoint;
|
||||
let drawing = false;
|
||||
|
||||
const getFeatureOptions = {
|
||||
hitTolerance: 10,
|
||||
layerFilter: (layer) => {
|
||||
return layer === baseVector;
|
||||
}
|
||||
};
|
||||
|
||||
// the click event is used to start/end tracing around a feature
|
||||
map.on('click', (event) => {
|
||||
if (!drawing) {
|
||||
return;
|
||||
}
|
||||
|
||||
let hit = false;
|
||||
map.forEachFeatureAtPixel(
|
||||
event.pixel,
|
||||
(feature) => {
|
||||
if (tracingFeature && feature !== tracingFeature) {
|
||||
return;
|
||||
}
|
||||
|
||||
hit = true;
|
||||
const coord = map.getCoordinateFromPixel(event.pixel);
|
||||
|
||||
// second click on the tracing feature: append the ring coordinates
|
||||
if (feature === tracingFeature) {
|
||||
endPoint = tracingFeature.getGeometry().getClosestPoint(coord);
|
||||
const appendCoords = getPartialRingCoords(tracingFeature, startPoint, endPoint);
|
||||
drawInteraction.removeLastPoint();
|
||||
drawInteraction.appendCoordinates(appendCoords);
|
||||
tracingFeature = null;
|
||||
}
|
||||
|
||||
// start tracing on the feature ring
|
||||
tracingFeature = feature;
|
||||
startPoint = tracingFeature.getGeometry().getClosestPoint(coord);
|
||||
},
|
||||
getFeatureOptions
|
||||
);
|
||||
|
||||
if (!hit) {
|
||||
// clear current tracing feature & preview
|
||||
previewLine.getGeometry().setCoordinates([]);
|
||||
tracingFeature = null;
|
||||
}
|
||||
});
|
||||
|
||||
// the pointermove event is used to show a preview of the result of the tracing
|
||||
map.on('pointermove', (event) => {
|
||||
if (tracingFeature && drawing) {
|
||||
let coord = null;
|
||||
map.forEachFeatureAtPixel(
|
||||
event.pixel,
|
||||
(feature) => {
|
||||
if (tracingFeature === feature) {
|
||||
coord = map.getCoordinateFromPixel(event.pixel);
|
||||
}
|
||||
},
|
||||
getFeatureOptions
|
||||
);
|
||||
|
||||
let previewCoords = [];
|
||||
if (coord) {
|
||||
endPoint = tracingFeature.getGeometry().getClosestPoint(coord);
|
||||
previewCoords = getPartialRingCoords(tracingFeature, startPoint, endPoint);
|
||||
}
|
||||
previewLine.getGeometry().setCoordinates(previewCoords);
|
||||
}
|
||||
});
|
||||
|
||||
const snapInteraction = new Snap({
|
||||
source: baseVector.getSource()
|
||||
});
|
||||
|
||||
const typeSelect = document.getElementById('type');
|
||||
|
||||
function addInteraction() {
|
||||
const value = typeSelect.value;
|
||||
if (value !== 'None') {
|
||||
drawInteraction = new Draw({
|
||||
source: drawVector.getSource(),
|
||||
type: typeSelect.value
|
||||
});
|
||||
drawInteraction.on('drawstart', () => {
|
||||
drawing = true;
|
||||
});
|
||||
drawInteraction.on('drawend', () => {
|
||||
drawing = false;
|
||||
previewLine.getGeometry().setCoordinates([]);
|
||||
tracingFeature = null;
|
||||
});
|
||||
map.addInteraction(drawInteraction);
|
||||
map.addInteraction(snapInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
typeSelect.onchange = function() {
|
||||
map.removeInteraction(drawInteraction);
|
||||
map.removeInteraction(snapInteraction);
|
||||
addInteraction();
|
||||
};
|
||||
addInteraction();
|
||||
@@ -6,6 +6,8 @@ docs: >
|
||||
Example showing vector tiles in EPSG:4326 (styled using `ol-mapbox-style`) loaded from maptiler.com.
|
||||
**Note**: Make sure to get your own API key at https://www.maptiler.com/cloud/ when using this example. No map will be visible when the API key has expired.
|
||||
tags: "vector tiles, epsg4326, mapbox style, ol-mapbox-style, maptiler"
|
||||
resources:
|
||||
- https://cdn.polyfill.io/v2/polyfill.min.js?features=String.prototype.startsWith,Object.assign"
|
||||
cloak:
|
||||
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||
|
||||
@@ -4,7 +4,7 @@ import VectorTileSource from '../src/ol/source/VectorTile.js';
|
||||
import TileGrid from '../src/ol/tilegrid/TileGrid.js';
|
||||
|
||||
import olms from 'ol-mapbox-style';
|
||||
import {defaultResolutions} from 'ol-mapbox-style/util.js';
|
||||
import {defaultResolutions} from 'ol-mapbox-style/dist/util.js';
|
||||
|
||||
const key = 'get_your_own_D6rA4zTHduk6KOKTXzGB';
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ docs: >
|
||||
Note: those will be taken from the attributes provided to the renderer
|
||||
* `['var', 'varName']` fetches a value from the style variables, or 0 if undefined
|
||||
* `['time']` returns the time in seconds since the creation of the layer
|
||||
* `['zoom']` returns the current zoom level
|
||||
* `['resolution']` returns the current resolution
|
||||
|
||||
* Math operators:
|
||||
* `['*', value1, value2]` multiplies `value1` by `value2`
|
||||
@@ -57,7 +59,6 @@ docs: >
|
||||
* `['color', red, green, blue, alpha]` creates a `color` value from `number` values; the `alpha` parameter is
|
||||
optional; if not specified, it will be set to 1.
|
||||
Note: `red`, `green` and `blue` components must be values between 0 and 255; `alpha` between 0 and 1.
|
||||
|
||||
Values can either be literals or another operator, as they will be evaluated recursively.
|
||||
Literal values can be of the following types:
|
||||
* `boolean`
|
||||
@@ -76,6 +77,7 @@ experimental: true
|
||||
<option value="triangles-latitude">Triangles, color related to latitude</option>
|
||||
<option value="circles">Circles, size related to population</option>
|
||||
<option value="circles-zoom">Circles, size related to zoom</option>
|
||||
<option value="rotating-bars">Rotating bars</option>
|
||||
</select>
|
||||
<textarea style="width: 100%; height: 20rem; font-family: monospace; font-size: small;" id="style-editor"></textarea>
|
||||
<small>
|
||||
|
||||
@@ -95,6 +95,35 @@ const predefinedStyles = {
|
||||
offset: [0, 0],
|
||||
opacity: 0.95
|
||||
}
|
||||
},
|
||||
'rotating-bars': {
|
||||
symbol: {
|
||||
symbolType: 'square',
|
||||
rotation: ['*', [
|
||||
'time'
|
||||
], 0.1],
|
||||
size: ['array', 4, [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
20000, 4,
|
||||
300000, 28]
|
||||
],
|
||||
color: [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
20000, '#ffdc00',
|
||||
300000, '#ff5b19'
|
||||
],
|
||||
offset: ['array', 0, [
|
||||
'interpolate',
|
||||
['linear'],
|
||||
['get', 'population'],
|
||||
20000, 2,
|
||||
300000, 14]
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -167,3 +196,10 @@ function onSelectChange() {
|
||||
}
|
||||
onSelectChange();
|
||||
select.addEventListener('change', onSelectChange);
|
||||
|
||||
// animate the map
|
||||
function animate() {
|
||||
map.render();
|
||||
window.requestAnimationFrame(animate);
|
||||
}
|
||||
animate();
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = {
|
||||
stats: 'minimal',
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.js$/,
|
||||
test: /^((?!es2015-)[\s\S])*\.js$/,
|
||||
use: {
|
||||
loader: 'buble-loader'
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ layout: example.html
|
||||
title: ArcGIS REST with 512x512 Tiles
|
||||
shortdesc: Example of a XYZ source in EPSG:4326 using Esri 512x512 tiles.
|
||||
docs: >
|
||||
ArcGIS REST tile services with custom tile sizes (here: 512x512 pixels) and projection (here: EPSG:4326) are supported by `ol/source/XYZ`. A custom tile url function is used to handle zoom level offsets.
|
||||
ArcGIS REST tile services with custom tile sizes (here: 512x512 pixels) and projection (here: EPSG:4326) are supported by `ol/source/XYZ`.
|
||||
tags: "xyz, esri, tilesize, custom projection"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
|
||||
@@ -3,26 +3,18 @@ import View from '../src/ol/View.js';
|
||||
import TileLayer from '../src/ol/layer/Tile.js';
|
||||
import XYZ from '../src/ol/source/XYZ.js';
|
||||
|
||||
// The tile size supported by the ArcGIS tile service.
|
||||
const tileSize = 512;
|
||||
|
||||
const urlTemplate = 'https://services.arcgisonline.com/arcgis/rest/services/' +
|
||||
'ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}';
|
||||
|
||||
const map = new Map({
|
||||
target: 'map',
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new XYZ({
|
||||
attributions: 'Copyright:© 2013 ESRI, i-cubed, GeoEye',
|
||||
maxZoom: 16,
|
||||
url: 'https://services.arcgisonline.com/arcgis/rest/services/' +
|
||||
'ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}',
|
||||
maxZoom: 15,
|
||||
projection: 'EPSG:4326',
|
||||
tileSize: tileSize,
|
||||
tileUrlFunction: function(tileCoord) {
|
||||
return urlTemplate.replace('{z}', (tileCoord[0] - 1).toString())
|
||||
.replace('{x}', tileCoord[1].toString())
|
||||
.replace('{y}', tileCoord[2].toString());
|
||||
},
|
||||
tileSize: 512, // the tile size supported by the ArcGIS tile service
|
||||
maxResolution: 180 / 512, // Esri's tile grid fits 180 degrees on one 512 px tile
|
||||
wrapX: true
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,7 +10,6 @@ tags: "zoomify, deep zoom, IIP, pixel, projection"
|
||||
<div class="controls">
|
||||
<select id="zoomifyProtocol">
|
||||
<option value="zoomify">Zoomify</option>
|
||||
<option value="iip">IIP</option>
|
||||
<option value="zoomifyretina">Zoomify Retina</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
+30
-87
@@ -3,36 +3,42 @@ import View from '../src/ol/View.js';
|
||||
import TileLayer from '../src/ol/layer/Tile.js';
|
||||
import Zoomify from '../src/ol/source/Zoomify.js';
|
||||
|
||||
const imgWidth = 9911;
|
||||
const imgHeight = 6100;
|
||||
const imgWidth = 4000;
|
||||
const imgHeight = 3000;
|
||||
|
||||
const zoomifyUrl = 'http://vips.vtech.fr/cgi-bin/iipsrv.fcgi?zoomify=' +
|
||||
'/mnt/MD1/AD00/plan_CHU-4HD-01/FOND.TIF/';
|
||||
const iipUrl = 'http://vips.vtech.fr/cgi-bin/iipsrv.fcgi?FIF=' + '/mnt/MD1/AD00/plan_CHU-4HD-01/FOND.TIF' + '&JTL={z},{tileIndex}';
|
||||
const zoomifyUrl = 'https://ol-zoomify.surge.sh/zoomify/';
|
||||
|
||||
const layer = new TileLayer({
|
||||
source: new Zoomify({
|
||||
tileSize: 256,
|
||||
tilePixelRatio: 1,
|
||||
url: zoomifyUrl,
|
||||
size: [imgWidth, imgHeight],
|
||||
crossOrigin: 'anonymous'
|
||||
})
|
||||
const source = new Zoomify({
|
||||
url: zoomifyUrl,
|
||||
size: [imgWidth, imgHeight],
|
||||
crossOrigin: 'anonymous',
|
||||
zDirection: -1 // Ensure we get a tile with the screen resolution or higher
|
||||
});
|
||||
const extent = source.getTileGrid().getExtent();
|
||||
|
||||
const retinaPixelRatio = 2;
|
||||
const retinaSource = new Zoomify({
|
||||
url: zoomifyUrl,
|
||||
size: [imgWidth, imgHeight],
|
||||
crossOrigin: 'anonymous',
|
||||
zDirection: -1, // Ensure we get a tile with the screen resolution or higher
|
||||
tilePixelRatio: retinaPixelRatio, // Display retina tiles
|
||||
tileSize: 256 / retinaPixelRatio // from a higher zoom level
|
||||
});
|
||||
|
||||
const extent = [0, -imgHeight, imgWidth, 0];
|
||||
|
||||
const resolutions = layer.getSource().getTileGrid().getResolutions();
|
||||
const layer = new TileLayer({
|
||||
source: source
|
||||
});
|
||||
|
||||
const map = new Map({
|
||||
layers: [layer],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
// adjust zoom levels to those provided by the source
|
||||
minResolution: resolutions[resolutions.length - 1],
|
||||
maxResolution: resolutions[0],
|
||||
resolutions: layer.getSource().getTileGrid().getResolutions(),
|
||||
// constrain the center: center cannot be set outside this extent
|
||||
extent: extent
|
||||
extent: extent,
|
||||
constrainOnlyCenter: true
|
||||
})
|
||||
});
|
||||
map.getView().fit(extent);
|
||||
@@ -40,74 +46,11 @@ map.getView().fit(extent);
|
||||
const control = document.getElementById('zoomifyProtocol');
|
||||
control.addEventListener('change', function(event) {
|
||||
const value = event.currentTarget.value;
|
||||
if (value === 'iip') {
|
||||
const extent = [0, -imgHeight, imgWidth, 0];
|
||||
layer.setSource(
|
||||
new Zoomify({
|
||||
tileSize: 256,
|
||||
tilePixelRatio: 1,
|
||||
url: iipUrl,
|
||||
size: [imgWidth, imgHeight],
|
||||
crossOrigin: 'anonymous'
|
||||
})
|
||||
);
|
||||
const resolutions = layer.getSource().getTileGrid().getResolutions();
|
||||
map.setView(
|
||||
new View({
|
||||
// adjust zoom levels to those provided by the source
|
||||
minResolution: resolutions[resolutions.length - 1],
|
||||
maxResolution: resolutions[0],
|
||||
// constrain the center: center cannot be set outside this extent
|
||||
extent: extent
|
||||
})
|
||||
);
|
||||
map.getView().fit(extent);
|
||||
} else if (value === 'zoomify') {
|
||||
const extent = [0, -imgHeight, imgWidth, 0];
|
||||
layer.setSource(
|
||||
new Zoomify({
|
||||
tileSize: 256,
|
||||
tilePixelRatio: 1,
|
||||
url: zoomifyUrl,
|
||||
size: [imgWidth, imgHeight],
|
||||
crossOrigin: 'anonymous'
|
||||
})
|
||||
);
|
||||
const resolutions = layer.getSource().getTileGrid().getResolutions();
|
||||
map.setView(
|
||||
new View({
|
||||
// adjust zoom levels to those provided by the source
|
||||
minResolution: resolutions[resolutions.length - 1],
|
||||
maxResolution: resolutions[0],
|
||||
// constrain the center: center cannot be set outside this extent
|
||||
extent: extent
|
||||
})
|
||||
);
|
||||
map.getView().fit(extent);
|
||||
if (value === 'zoomify') {
|
||||
layer.setSource(source);
|
||||
} else if (value === 'zoomifyretina') {
|
||||
const pixelRatio = 4;
|
||||
// Be careful! Image extent will be modified by pixel ratio
|
||||
const extent = [0, -imgHeight / pixelRatio, imgWidth / pixelRatio, 0];
|
||||
layer.setSource(
|
||||
new Zoomify({
|
||||
tileSize: 256 / pixelRatio,
|
||||
tilePixelRatio: pixelRatio,
|
||||
url: zoomifyUrl,
|
||||
size: [imgWidth / pixelRatio, imgHeight / pixelRatio],
|
||||
crossOrigin: 'anonymous'
|
||||
})
|
||||
);
|
||||
const resolutions = layer.getSource().getTileGrid().getResolutions();
|
||||
map.setView(
|
||||
new View({
|
||||
// adjust zoom levels to those provided by the source
|
||||
minResolution: resolutions[resolutions.length - 1] / pixelRatio,
|
||||
maxResolution: resolutions[0],
|
||||
// constrain the center: center cannot be set outside this extent
|
||||
extent: extent
|
||||
})
|
||||
);
|
||||
map.getView().fit(extent);
|
||||
layer.setSource(retinaSource);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user