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

Add support for multi-sprites in styles #1232

Merged
merged 22 commits into from
Apr 23, 2024
Merged

Conversation

acalcutt
Copy link
Collaborator

@acalcutt acalcutt commented Apr 20, 2024

maplibre-gl-native node-v5.4.0 adds support for multi-sprites ( https://maplibre.org/maplibre-style-spec/sprite/#multiple-sprite-sources ).

This PR allows tileserver-gl to handle an array of local sprites, in a format like

  "sprite": [
    {
      "id": "colored",
      "url": "{styleJsonFolder}/colored_sprites"
    },
    {
      "id": "default",
      "url": "{styleJsonFolder}/sprite"
    }
  ],

you can also specify urls, like shown in the style spec

  "sprite": [
    {
      "id": "colored",
      "url": "https://tiles.wifidb.net/styles/WDB_GPSTRAILS/sprite/colored_sprites"
    },
    {
      "id": "default",
      "url": "https://tiles.wifidb.net/styles/WDB_GPSTRAILS/sprite"
    }
  ],

Example
I updated this ATV trail map to use two different sets of sprites, 'default' and 'colored'. You can see the default icons and colored icons show as expected
https://tiles.wifidb.net/styles/WDB_GPSTRAILS/?raster#15/45.0491/-69.8739
image

src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
@acalcutt acalcutt marked this pull request as ready for review April 21, 2024 01:21
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
src/serve_style.js Fixed Show fixed Hide fixed
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
So it doesn't conflict with style json url

Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
Signed-off-by: acalcutt <acalcutt@techidiots.net>
src/serve_style.js Fixed Show fixed Hide fixed
app.get(
'/:id/sprite(/:name)?:scale(@[23]x)?.:format([\\w]+)',
(req, res, next) => {
const name = req.params.name || 'sprite';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you wanted to you could do

const { name = 'sprite', scale = '', format, id } = req.params;

if (Array.isArray(styleJSON.sprite)) {
styleJSON.sprite.forEach((spriteItem) => {
if (!httpTester.test(spriteItem.url)) {
spriteItem.url =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have an issue with how it is here, but I wonder if it might be worth having a helper method for doing this replacement?

Another option would be to start by normalizing sprites when initially loading styles?

if (styleJSON.sprite) {
  if (!Array.isArray(styleJSON.sprite)) {
    styleJSON.sprite = [{id: 'default', url: styleJSON.sprite }]; 
  }

  for (let spriteItem of styleJSON.sprite) {
    if (!httpTester.test(spriteItem.url)) {
      spriteItem.url = ...
    }
  }
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree this looks better and is simpler. My only concern my previous way preserved the existing sprite format, so if you were not using multi-sprites it would function as before and work with older versions of mapbox/maplibre that do not support multi-sprite.

Where this way basically forces multi-sprites on the users style whether they are using them or not. So it would only work with newer maplibre-js that supports that.

Copy link
Collaborator Author

@acalcutt acalcutt Apr 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on the fence about reverting this change. I don't know if I want to break clients that doesn't support multi-sprite if the person making the style hasn't chosen to use them. it does look a lot nicer though.

src/serve_style.js Outdated Show resolved Hide resolved
src/serve_style.js Outdated Show resolved Hide resolved
Signed-off-by: acalcutt <acalcutt@techidiots.net>
src/serve_style.js Dismissed Show dismissed Hide dismissed
Signed-off-by: acalcutt <acalcutt@techidiots.net>
Signed-off-by: acalcutt <acalcutt@techidiots.net>
Signed-off-by: acalcutt <acalcutt@techidiots.net>
'/:id/sprite(/:spriteID)?:scale(@[23]x)?.:format([\\w]+)',
(req, res, next) => {
const { spriteID = 'default', id } = req.params;
const scale = allowedSpriteScales(req.params.scale) || '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super minor thing, you can move the || '' in to make it the default:

Suggested change
const scale = allowedSpriteScales(req.params.scale) || '';
const scale = allowedSpriteScales(req.params.scale, { defaultValue: '' });

Copy link
Collaborator Author

@acalcutt acalcutt Apr 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I try this, scale ends up 'undefined' if no scale is set, so it ends up putting that into the file name. I see this at the console

Sprite load error: C:\Users\andrew.EIRI\Desktop\test_data\styles\klokantech-basic\spriteundefined.png

Signed-off-by: acalcutt <acalcutt@techidiots.net>
Signed-off-by: acalcutt <acalcutt@techidiots.net>
Signed-off-by: acalcutt <acalcutt@techidiots.net>
@acalcutt acalcutt merged commit 66445e8 into maptiler:master Apr 23, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants