Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maplibre adapter should pass along attribution #247

Closed
jleedev opened this issue Sep 4, 2023 · 14 comments
Closed

Maplibre adapter should pass along attribution #247

jleedev opened this issue Sep 4, 2023 · 14 comments
Assignees

Comments

@jleedev
Copy link

jleedev commented Sep 4, 2023

PMTiles/js/adapters.ts

Lines 129 to 134 in 17583ae

const tilejson = {
tiles: [params.url + "/{z}/{x}/{y}"],
minzoom: h.minZoom,
maxzoom: h.maxZoom,
bounds: [h.minLon, h.minLat, h.maxLon, h.maxLat],
};

Should also include: attribution: m.attribution,, where m is the result of instance.getMetadata(). Or the TileJSON could be the entire metadata verbatim, plus the fields from the header.

Maplibre would then be able to show the attribution automatically.

@bdon
Copy link
Member

bdon commented Sep 6, 2023

I'm a bit torn on this because the size of metadata is unbounded. This is not a theoretical concern - tippecanoe automatically produces a tilestats key with info on column values, which can easily be 30 kb compressed - making the map load block on that to load a single sentence, by default, seems bad.

@jleedev
Copy link
Author

jleedev commented Sep 9, 2023

Yes, that's unfortunate.

For some numbers:

  • The planet at tile.ourmap.us contains (approximately) 39,359 bytes of json, or 2,893 gzipped, which I expect should be typical of any users of the OpenMapTiles schema.
  • The pmtiles from alltheplaces.xyz contains 37,636 bytes of gzipped json, which decompresses to 141,885 bytes. (Since this is produced by throwing a huge amount of nonsense at tippecanoe without care for how big the tilejson becomes.)

On the one hand, fetching the first 64 KiB should therefore allow reading the complete metadata in many situations. On the other hand, the current spec and implementation only fetch the first 16 KiB in order to read the header and root. So this could be achieved by increasing the length of this initial read.

(The metadata could also be treated as a potentially-truncated JSON document to find the attribution, but that seems foolhardy.)

@jleedev
Copy link
Author

jleedev commented Sep 9, 2023

Manipulating the attribution of the maplibre source after it has loaded is … sort of possible but feels hacky. If maplibre had native pmtiles support it would be more plausible for the source to quickly read the root to determine the extents and format, and then lazily fetch the metadata.

@bdon
Copy link
Member

bdon commented Sep 10, 2023

@jleedev the 16kb was intentionally chosen to be conservative - we can expand this to 32kb or 64kb if we discover that's a better default, while remaining backwards compatible with old archives for "free". The reverse is not true (if we started with a 32kb fetch, and later changed it to be 16kb, we'd have to add logic and extra requests to deal with old archives)

However, I don't think making predictions on metadata size to include them in the first 64kb is reliable. @acalcutt needs the vector_layers key to power maplibre-gl-inspect - I suggested we can add a ?metadata=true to the URL that would block on fetching metadata before returning the TileJSON to maplibre.

That would give you automatic attribution in the case you pass ?metadata=true (default false).

@jleedev
Copy link
Author

jleedev commented Oct 2, 2023

Regarding the API design, a hash parameter would be better than a query parameter (#metadata=true), since this is not being passed to the server.

Or we could add options to the Protocol constructor, e.g. protocol = new pmtiles.Protocol({ metadata: true }).

@bdon
Copy link
Member

bdon commented Oct 3, 2023

Is your goal to make attribution appear automatically for all archives within a given application, or for a specific one?

The Protocol constructor would work globally, the hash parameter would be specific to one (but could support all if it's a URL template)

@jleedev
Copy link
Author

jleedev commented Oct 3, 2023

That's the question, isn't it.

I think anyone who is loading some sort of dynamic data, or implementing an inspect control, would prefer to see the metadata. In alltheplaces we've encoded the build date into the attribution string; Americana has the planetiler replication timestamp in the metadata (at least in principle); an inspect control would like to get at the vector_layers array.

Anyone who is using this protocol as a basemap for something else probably does not require it. For instance, they would hardcode the attribution string alongside the URL to their tiles, in their map style.

This adapter currently has no options. Being able to specify options both globally and on a per-source basis sounds reasonable to me and would meet unanticipated use cases.

It appears that passing along the vector_layers also allows maplibre-gl-js to validate that each style layer refers to something that exists.

@bdon
Copy link
Member

bdon commented Oct 4, 2023

Here's what it would look like for #metadata=true as a URL option

8127188

Adding a API surface to addProtocol seems worse than extending an "API"(URLs) that we're already using.

@bdon
Copy link
Member

bdon commented Oct 4, 2023

Also related to #239

@jleedev
Copy link
Author

jleedev commented Oct 4, 2023

Nice, I think that looks pretty sensible.

@acalcutt
Copy link

acalcutt commented Oct 4, 2023

Looks nice, can't wait to try it :-)

I honestly hadn't even thought of the attribution. I include a datastamp in my generated files too, since it helps to just look and see a new map generated that day.

@bdon
Copy link
Member

bdon commented Oct 6, 2023

TODO: confirm that the above works with non-remote URL sources, like a local FileSource.

@bdon bdon self-assigned this Sep 18, 2024
bdon added a commit that referenced this issue Sep 18, 2024
* add getTileJson method to PMTiles class [#239, #247]
* update docs related to FetchSource and headers [#397]
bdon added a commit that referenced this issue Sep 22, 2024
* pass metadata: true to new Protocol() to make an extra request and populate attribution + vector_layers
@bdon
Copy link
Member

bdon commented Sep 22, 2024

I changed my mind and will make it a protocol level option: #461

This means you cannot control the loading of metadata/attribution per source. That required using a #metadata=true in the URL which can break a lot of other things because internally the source is keyed via its URL.

It seems like the applications that are "inspectors" like https://github.com/maplibre/maplibre-gl-inspect will want to use metadata: true, as well as if you want the automatic attribution on your map, but the default is to avoid the extra metadata request.

Required for maplibre/maputnik#807

bdon added a commit that referenced this issue Sep 22, 2024
* simplify examples
* update leaflet and maplibre versions
* add maplibre_headers.html example for custom headers [#397]
bdon added a commit that referenced this issue Sep 22, 2024
* Option to load metadata in MapLibre adapter [#247]

* pass metadata: true to new Protocol() to make an extra request and populate attribution + vector_layers
* js 3.2.0 [#247]
* simplify examples
* update leaflet and maplibre versions
* add maplibre_headers.html example for custom headers [#397]
@bdon
Copy link
Member

bdon commented Sep 22, 2024

Released in 3.2.0. See example: https://github.com/protomaps/PMTiles/blob/main/js/examples/maplibre.html#L23

@bdon bdon closed this as completed Sep 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants