protomaps / PMTiles

Cloud-optimized + compressed single-file tile archives for vector and raster maps
https://protomaps.com/docs/pmtiles/
BSD 3-Clause "New" or "Revised" License
2.12k stars 125 forks source link

Cannot render with magic number error #402

Closed tolidano closed 2 months ago

tolidano commented 5 months ago

I'm not even sure if this is the repo to solve this issue, but I figured I would start here.

I am using open layers and ol-pmtiles like this:

const layers = {}
   layers.base = new ol.layer.VectorTile({
     declutter: true,
     source: new olpmtiles.PMTilesVectorSource({
       url: 'https://d1b2p6fo2pi78e.cloudfront.net/us-northeast/{z}/{x}/{-y}.mvt',
       attributions: ['© OSM, MTA, & others']
     }),
     style: new ol.style.Style({
       stroke: new ol.style.Stroke({
         color: 'gray',
         width: 1,
       }),
       fill: new ol.style.Fill({
         color: 'rgba(20,20,20,0.9)',
       })
     })
   })
  const view = new ol.View({ // eslint-disable-line
     center: [-8235252, 4969073],
     minZoom: 10,
     maxZoom: 17,
     zoom: 14,
     constrainResolution: true,
     extent: [-8375000, 4795000, -8000000, 5125000]
   })
    map = new ol.Map({ // eslint-disable-line
     target: 'map',
     view,
     layers: [
       layers.base,
     ],
     interactions: ol.interaction.defaults.defaults({ zoomDuration: 0 }) // eslint-disable-line
   })

I've pulled ol 9.2.4 and olpmtiles 0.4.0 locally.

my html is simple:

<html>
<head>
   <link rel="stylesheet" href="/ol.css">
   <script src="/ol.js"></script>
   <script src="/olpmtiles.js"></script>
</head>
<body>
   <div id="map" tabindex="0"></div>
</body>
</html>

I used serverlessmaps to generate us-northeast and upload to S3 + CloudFront

It works here: https://d3gsiaxhde69bo.cloudfront.net/basemap.html#15.49/40.721384/-73.843143 and here: https://d3gsiaxhde69bo.cloudfront.net/#16/40.7206/-73.8382

I would like it to render with open layers since my existing application uses that and not, for example, maplibregl or leaflet. When I try it like this, it talks about a failed magic number, probably because it's always a bad URL

When I use the sample website, it makes calls to the tile cloud front like this: https://d1b2p6fo2pi78e.cloudfront.net/us-northeast/14/4831/6159.mvt

This uses a lambda defined here: https://github.com/serverlessmaps/serverlessmaps/blob/main/iac/functions/pmTilesProxy.ts to do a range request in the zip archive in the S3 bucket and return it.

Screenshot 2024-06-04 at 6 36 50 PM

Is there a way to set this up so that it renders with Open Layers using the same URL scheme? I'm obviously missing something, but I'm not sure how to make it call for the URLs properly.

bdon commented 5 months ago

If you are using the lambda you do not need anything PMTiles related on the client side, just use normal {z}/{x}/{y} URLs in OpenLayers.

tolidano commented 5 months ago

Could you explain a bit more?

Do I:

bdon commented 5 months ago

remove the olpmtiles.js file.

https://openlayers.org/en/latest/examples/webgl-vector-tiles.html

tolidano commented 5 months ago

Ok, so I have this as my base layer:

layers.base = new ol.layer.VectorTile({
       declutter: true,
       source: new ol.source.VectorTile({
         attributions:
           '© <a href="https://www.openstreetmap.org/copyright">' +
           'OpenStreetMap contributors</a>',
         format: new ol.format.MVT(),
         url: 'https://d1b2p6fo2pi78e.cloudfront.net/us-northeast/{z}/{x}/{y}.mvt',
       }),
       style: new ol.style.Style({
         stroke: new ol.style.Stroke({
           color: 'gray',
           width: 1,
         }),
         fill: new ol.style.Fill({
           color: 'rgba(20,20,20,0.9)',
         })
       })
     })

Thank you, I am much closer. Here is where I am at now.

On the sample basemap (you can click this), https://d3gsiaxhde69bo.cloudfront.net/#18/40.71993/-73.83873 you get this:

Screenshot 2024-06-05 at 10 34 52 PM

But when I use the code above, I get this:

Screenshot 2024-06-05 at 10 36 42 PM

So it is trying to load a lot more files, and unfortunately, all the street labels (and basically everything!) is missing.

Can you point me in the right direction? Is this because I'm using raster vs vector?

bdon commented 5 months ago

there isn't a labeled basemap implementation for OpenLayers. You can try to use ol-mapbox-style to load a MapLibre JSON but the performance isn't great generally. Your demo page is using Leaflet, not OpenLayers, and it's also using an older major version of protomaps-leaflet.

bdon commented 2 months ago

Closing as this is working as intended.