mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 10:51:07 +00:00
improve openlayers snippets; read header min/maxzoom [#3]
This commit is contained in:
@@ -2,8 +2,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>PMTiles OpenLayers Vector Example</title>
|
<title>PMTiles OpenLayers Vector Example</title>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/ol@v7.1.0/dist/ol.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/ol@v7.3.0/dist/ol.js"></script>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.1.0/ol.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.3.0/ol.css">
|
||||||
<script src="https://unpkg.com/pmtiles@2.7.2/dist/index.js"></script>
|
<script src="https://unpkg.com/pmtiles@2.7.2/dist/index.js"></script>
|
||||||
<style>
|
<style>
|
||||||
body, #map {
|
body, #map {
|
||||||
@@ -15,79 +15,80 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
class OLPMTilesSource {
|
class VectorPMTilesSource extends ol.source.VectorTile {
|
||||||
constructor(url) {
|
tileLoadFunction = (tile,url) => {
|
||||||
this._url = url;
|
// the URL construction is done internally by OL, so we need to parse it
|
||||||
this._p = new pmtiles.PMTiles(url)
|
// back out here using a hacky regex
|
||||||
}
|
const re = new RegExp(/pmtiles:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/);
|
||||||
|
const result = url.match(re);
|
||||||
|
const z = +result[2];
|
||||||
|
const x = +result[3];
|
||||||
|
const y = +result[4];
|
||||||
|
|
||||||
url = () => {
|
tile.setLoader((extent, resolution, projection) => {
|
||||||
return "pmtiles://" + this._url + "/{z}/{x}/{y}";
|
tile.setState(1); // LOADING
|
||||||
}
|
this._p.getZxy(z,x,y).then((tile_result) => {
|
||||||
|
if (tile_result) {
|
||||||
vectorTileLoadFunction = (tile,url) => {
|
const format = tile.getFormat();
|
||||||
// the URL construction is done internally by OL, so we need to parse it
|
const features = format.readFeatures(tile_result.data.buffer, {
|
||||||
// back out here using a hacky regex
|
extent: extent,
|
||||||
const re = new RegExp(/pmtiles:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/);
|
featureProjection: projection
|
||||||
const result = url.match(re);
|
});
|
||||||
const z = +result[2];
|
tile.setFeatures(features);
|
||||||
const x = +result[3];
|
tile.setState(2); // LOADED
|
||||||
const y = +result[4];
|
} else {
|
||||||
|
tile.setFeatures([]);
|
||||||
tile.setLoader((extent, resolution, projection) => {
|
tile.setState(4); // EMPTY
|
||||||
tile.setState(1); // LOADING
|
}
|
||||||
this._p.getZxy(z,x,y).then((tile_result) => {
|
|
||||||
if (tile_result) {
|
|
||||||
const format = tile.getFormat();
|
|
||||||
const features = format.readFeatures(tile_result.data.buffer, {
|
|
||||||
extent: extent,
|
|
||||||
featureProjection: projection
|
|
||||||
});
|
|
||||||
tile.setFeatures(features);
|
|
||||||
tile.setState(2); // LOADED
|
|
||||||
} else {
|
|
||||||
tile.setFeatures([]);
|
|
||||||
tile.setState(4); // EMPTY
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = new OLPMTilesSource("https://r2-public.protomaps.com/protomaps-sample-datasets/nz-buildings-v3.pmtiles");
|
constructor(options) {
|
||||||
|
super({
|
||||||
|
state:"loading",
|
||||||
|
url: "pmtiles://" + options.url + "/{z}/{x}/{y}",
|
||||||
|
format: new ol.format.MVT(),
|
||||||
|
attributions: options.attributions
|
||||||
|
});
|
||||||
|
|
||||||
const style = new ol.style.Style({
|
this._p = new pmtiles.PMTiles(options.url);
|
||||||
|
this._p.getHeader().then(h => {
|
||||||
|
// TODO: set extent based on header
|
||||||
|
this.tileGrid.minZoom = h.minZoom;
|
||||||
|
this.tileGrid.maxZoom = h.maxZoom;
|
||||||
|
this.setTileLoadFunction(this.tileLoadFunction);
|
||||||
|
this.setState("ready");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const vectorLayer = new ol.layer.VectorTile({
|
||||||
|
declutter: true,
|
||||||
|
source: new VectorPMTilesSource({
|
||||||
|
url: "https://r2-public.protomaps.com/protomaps-sample-datasets/nz-buildings-v3.pmtiles",
|
||||||
|
attributions: ["© Land Information New Zealand"]
|
||||||
|
}),
|
||||||
|
style: new ol.style.Style({
|
||||||
stroke: new ol.style.Stroke({
|
stroke: new ol.style.Stroke({
|
||||||
color: 'gray',
|
color: 'gray',
|
||||||
width: 1,
|
width: 1,
|
||||||
}),
|
}),
|
||||||
fill: new ol.style.Fill({
|
fill: new ol.style.Fill({
|
||||||
color: 'rgba(20,20,20,0.9)',
|
color: 'rgba(20,20,20,0.9)',
|
||||||
}),
|
})
|
||||||
});
|
})
|
||||||
|
});
|
||||||
|
|
||||||
const vtLayer = new ol.layer.VectorTile({
|
ol.proj.useGeographic();
|
||||||
declutter: true,
|
const map = new ol.Map({
|
||||||
source: new ol.source.VectorTile({
|
layers: [vectorLayer],
|
||||||
attributions:["© Land Information New Zealand"],
|
target: 'map',
|
||||||
maxZoom: 14, // this could come from the PMTiles header (async)
|
view: new ol.View({
|
||||||
format: new ol.format.MVT(), // this could come from the PMTiles header (async)
|
center: [172.606201,-43.556510],
|
||||||
url:source.url(),
|
zoom: 7
|
||||||
tileLoadFunction: source.vectorTileLoadFunction
|
}),
|
||||||
}),
|
});
|
||||||
style: style,
|
|
||||||
});
|
|
||||||
|
|
||||||
ol.proj.useGeographic();
|
|
||||||
const map = new ol.Map({
|
|
||||||
layers: [vtLayer],
|
|
||||||
target: 'map',
|
|
||||||
view: new ol.View({
|
|
||||||
center: [172.606201,-43.556510],
|
|
||||||
zoom: 7,
|
|
||||||
multiWorld: true,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>PMTiles OpenLayers Raster Example</title>
|
<title>PMTiles OpenLayers Raster Example</title>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/ol@v7.1.0/dist/ol.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/ol@v7.3.0/dist/ol.js"></script>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.1.0/ol.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v7.3.0/ol.css">
|
||||||
<script src="https://unpkg.com/pmtiles@2.7.2/dist/index.js"></script>
|
<script src="https://unpkg.com/pmtiles@2.7.2/dist/index.js"></script>
|
||||||
<style>
|
<style>
|
||||||
body, #map {
|
body, #map {
|
||||||
@@ -15,61 +15,59 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
class OLPMTilesSource {
|
class RasterPMTilesSource extends ol.source.DataTile {
|
||||||
constructor(url) {
|
loadImage = (src) => {
|
||||||
this._url = url;
|
return new Promise((resolve, reject) => {
|
||||||
this._p = new pmtiles.PMTiles(url)
|
const img = new Image();
|
||||||
}
|
img.addEventListener('load', () => resolve(img));
|
||||||
|
img.addEventListener('error', () => reject(new Error('load failed')));
|
||||||
url = () => {
|
img.src = src;
|
||||||
return "pmtiles://" + this._url + "/{z}/{x}/{y}";
|
});
|
||||||
}
|
|
||||||
|
|
||||||
rasterTileLoadFunction = (tile,url) => {
|
|
||||||
tile.setState(1); // LOADING
|
|
||||||
// the URL construction is done internally by OL, so we need to parse it
|
|
||||||
// back out here using a hacky regex
|
|
||||||
const re = new RegExp(/pmtiles:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/);
|
|
||||||
const result = url.match(re);
|
|
||||||
const z = +result[2];
|
|
||||||
const x = +result[3];
|
|
||||||
const y = +result[4];
|
|
||||||
|
|
||||||
this._p.getZxy(z,x,y).then((tile_result) => {
|
|
||||||
if (tile_result) {
|
|
||||||
const blob = new Blob([tile_result.data]);
|
|
||||||
const imageUrl = window.URL.createObjectURL(blob);
|
|
||||||
tile.getImage().src = imageUrl;
|
|
||||||
tile.setState(2); // LOADED
|
|
||||||
} else {
|
|
||||||
tile.setState(4); // EMPTY
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = new OLPMTilesSource("https://r2-public.protomaps.com/protomaps-sample-datasets/terrarium_z9.pmtiles");
|
constructor(options) {
|
||||||
|
super({
|
||||||
|
state: "loading",
|
||||||
|
attributions: options.attributions
|
||||||
|
});
|
||||||
|
|
||||||
const rasterLayer = new ol.layer.Tile({
|
const p = new pmtiles.PMTiles(options.url);
|
||||||
source: new ol.source.XYZ({
|
p.getHeader().then(h => {
|
||||||
attributions:["https://github.com/tilezen/joerd/blob/master/docs/attribution.md"],
|
// TODO: set extent based on header
|
||||||
url:source.url(),
|
this.tileGrid.minZoom = h.minZoom;
|
||||||
tileLoadFunction: source.rasterTileLoadFunction,
|
this.tileGrid.maxZoom = h.maxZoom;
|
||||||
tileSize:[512,512],
|
this.setLoader(async (z,x,y) => {
|
||||||
maxZoom:9 // this could come from the PMTiles header (async)
|
const response = await p.getZxy(z, x, y);
|
||||||
|
const blob = new Blob([response.data]);
|
||||||
|
const src = URL.createObjectURL(blob);
|
||||||
|
const image = await this.loadImage(src);
|
||||||
|
image.width = 512;
|
||||||
|
URL.revokeObjectURL(src);
|
||||||
|
return image;
|
||||||
|
});
|
||||||
|
this.setState("ready");
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ol.proj.useGeographic();
|
// TODO: tile size 512,512
|
||||||
const map = new ol.Map({
|
const rasterLayer = new ol.layer.WebGLTile({
|
||||||
layers: [rasterLayer],
|
source: new RasterPMTilesSource({
|
||||||
target: 'map',
|
url:"https://r2-public.protomaps.com/protomaps-sample-datasets/terrarium_z9.pmtiles",
|
||||||
view: new ol.View({
|
attributions:["https://github.com/tilezen/joerd/blob/master/docs/attribution.md"]
|
||||||
center: [0,0],
|
})
|
||||||
zoom: 0,
|
});
|
||||||
multiWorld: true,
|
|
||||||
}),
|
ol.proj.useGeographic();
|
||||||
});
|
const map = new ol.Map({
|
||||||
|
layers: [rasterLayer],
|
||||||
|
target: 'map',
|
||||||
|
view: new ol.View({
|
||||||
|
center: [0,0],
|
||||||
|
zoom: 0,
|
||||||
|
multiWorld: true
|
||||||
|
}),
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user