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 StyleSelectControl element #206

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

spwoodcock
Copy link

@spwoodcock spwoodcock commented Oct 17, 2024

Issue

  • I thought it would be nice to have a style selection component built into this library.
  • This way users can pass multiple styles into MapLibre and easily toggle between them using an optional control.

Solution

  • Made a StyleSelectControl component that can be rendered in any corner of the map (configurable):

    image

  • Hovering over the control expands the options available & hovering over each element shows a tooltip of the style name:

    image

  • Selecting a style updates the map style:

    image

  • The direction the elements expand is also configurable:

    image

  • Each item is a ControlButton component with a thumbnail preview displayed.

Note

Currently the thumbnail is only rendered for raster basemaps of XYZ format.

  • The component accepts a prop extraStyles, which is a list of either maplibregl.StyleSpecification or a URL to a maplibre style JSON.
  • I also added a docs page entry.

Caveat 1

  • As mentioned, the thumbnail rendering is currently a bit naive.
  • It only works for raster styles, for example https://a.tile.openstreetmap.org/{z}/{x}/{y}.png.
  • Given more time I would explore the option of an alternative method (mentioned in the component docstring):
    • Perhaps we could render a non-interactive minimap MapLibre instance for each style, inside the ControlButton:
      map = new Map({
        container: div,
        style: STYLEHERE,
        attributionControl: false,
        interactive: false
      });
    • This offloads the burden of detecting the style type and rendering the style to MapLibre.
    • There may be a small performance penalty for doing this, especially if many styles are rendered at once.
    • It would be very nice if we could somehow extract the rendered tile from the instance at the lowest zoom level, then simply render the image inside the ControlButton.
  • There is a basic svg fallback that is displayed for other style types, for now.

Caveat 2

  • For now I made this a separate control, as I'm not sure if it's desirable / certain to be accepted.

  • The flexibility allows for me (or anyone else) to take this code and use it as a component alongside an existing svelte-maplibre install.

  • However, I realise that a prop like extraStyles is a bit clunky, and think the ideal implementation would simply be accepting either a single style or multiple styles on the MapLibre element:

    <MapLibre
      style="URL"
      ...
    >

    or

    <MapLibre
      style="{[style1, style2, style3]}"
      ...
    >

Copy link

changeset-bot bot commented Oct 17, 2024

🦋 Changeset detected

Latest commit: c39d642

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
svelte-maplibre Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

vercel bot commented Oct 17, 2024

@spwoodcock is attempting to deploy a commit to the Daniel Imfeld's projects Team on Vercel.

A member of the Team first needs to authorize it.

@@ -0,0 +1,239 @@
<!-- A component to render a style selection prompt, including a thumbnail

Choose a reason for hiding this comment

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

Can we move the JS script in this file to a .js file instead of a .sveltefile?

It will be much easier to integrate into other frontend frameworks (e.g. React) if the MapLibre lifecycle management were done in pure JS.

Copy link
Author

Choose a reason for hiding this comment

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

Sounds like a good idea!

Do you mean to move this logic perhaps into styles.ts & export the functions for use in this component:

https://github.com/dimfeld/svelte-maplibre/blob/c39d6422cf2b68f5c198c579fde3bbfecac140a3/src/lib/StyleSelectControl.svelte#L46C4-L123C4

Then the component will basically just accept props and pass data to these functions - is that right?

@spwoodcock
Copy link
Author

Other feedback is that the bubble sizes are probably a bit too bit - will reduce them slightly 😄

Copy link

vercel bot commented Oct 22, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
svelte-maplibre ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 22, 2024 6:32pm

Copy link
Owner

@dimfeld dimfeld left a comment

Choose a reason for hiding this comment

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

Thanks this is pretty cool! I agree moving the processing code out to another file is a good idea, so that people can more easily create their own style switcher controls. Will do a full review once that's done. :)

@@ -9,7 +9,7 @@
export { classNames as class };
</script>

<button type="button" {title} on:click>
<button type="button" {title} on:click {...$$props}>
Copy link
Owner

Choose a reason for hiding this comment

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

Let's use ...$$restProps here instead. Also did it not work to just pass rounded-full in the class property?


function selectStyle(style: MapLibreStylePlusMetadata) {
selectedStyleUrl = style.metadata.thumbnail;
$map?.setStyle(style);
Copy link
Author

Choose a reason for hiding this comment

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

This is a bug, as it would actually remove any additional layers added to the map.

If styles is used to load say a vector layer and a vector tile layer on top of the basemap raster layers. We would override the vector styles with only the basemap style.

Needs a fix before merge!

@spwoodcock spwoodcock marked this pull request as draft November 5, 2024 20:30
@spwoodcock
Copy link
Author

I got a bit sidetracked, but will try to come back to this soon!

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

Successfully merging this pull request may close these issues.

3 participants