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 ability to create a style with multiple themes #909

Open
amousavi opened this issue Jul 10, 2024 · 4 comments
Open

Add ability to create a style with multiple themes #909

amousavi opened this issue Jul 10, 2024 · 4 comments

Comments

@amousavi
Copy link

amousavi commented Jul 10, 2024

There is a need for the ability to build styles with multiple themes, such as light mode and dark mode. The current process is to clone the style and change every individual color, which is cumbersome and manual when there are frequent style changes. I would like to request a solution which Maputnik could edit a style using references to colors and numbers (or any type), which can be kept in a theme style sheet. Ideally, in a field using a style reference, you would still be able to edit the field as usual. However, based on the theme which is selected, it would update the reference value instead.

Then Maputnik could generate one style per theme, with the reference values in place.

Of course, this is just one possible solution to the issue, and open to discussion.

Rough example

{
  "themes": [
    {
      "name": "light",
      "label": "Light",
      "description": "A light theme for the map style.",
      "attributes": [
        {
          "name": "background",
          "type": "color",
          "default": "#f0f0f0"
        },
        {
          "name": "water",
          "type": "color",
          "default": "#cccccc"
        },
        {
          "name": "river_width",
          "type": "number",
          "default": "4"
        }
      ]
    },
    {
      "name": "dark",
      "label": "Dark",
      "description": "A dark theme for the map style.",
      "attributes": [
        {
          "name": "background",
          "type": "color",
          "default": "#000000"
        },
        {
          "name": "water",
          "type": "color",
          "default": "#333333"
        },
        {
          "name": "river_width",
          "type": "number",
          "default": "6"
        }
      ]
    }
  ]
}

Style building in Maputnik:

[
  {
    "id": "background",
    "type": "background",
    "layout": {
      "visibility": "visible"
    },
    "paint": {
      "background-color": "$water"
    }
  },
  {
    "id": "water lines",
    "type": "line",
    "source": "tile_source_42",
    "source-layer": "water_lines",
    "paint": {
      "line-color": "$water",
      "line-width": "$river_width"
    }
  }
]
@nyurik
Copy link
Member

nyurik commented Jul 10, 2024

It does sound like a good feature to have. Thinking further on this:

  • some fields allow arbitrary string values - so substitution may ignore those unless the same variable name is defined
  • even for one style, a shared variable used by multiple styling rules may be useful - e.g. different styling elements may use the same line thickness or transparency value, modified in one place
  • all variable usage must be in a JSON string - i.e. "line-width": $river_width above wouldn't work, must be "line-width": "$river_width" -- the type conversion can happen during substitution

Maputnik UI changes

  • a new dialog box to maintain a list of profiles and a list of variables, perhaps as a table
  • a drop down at the top to quickly switch between profiles, or even have a side-by-side view of two styles
  • each entry field (like color) should allow a $var instead of a real value
  • changing color of a var field should modify the variable's value - affecting all places that use that var

JSON format

Current stylesheet format is well defined, can be validated with json schema, and would break if we use "$var" in it. For this feature, we have to introduce a new "template" json which will be similar to the regular style, but may have extra info like "profiles" and variables instead of real values.

Instead, I think we may want to add a new Maputnik "editor file format" - different from "stylesheet format". The editor file format could store all sorts of additional data (e.g. data sources, variables, editor settings), and we would use an "export" command to actually produce a stylesheet.

Editor JSON format

  • not sure we need the field type here. This is a direct "value" substitution - the entire variable's value would be substitution in-place. The editor could treat that variable as the right type.. I might be wrong here
  • not sure why we would need one default per profile. A variable could have a single default for all profiles, with the ability to override it for each - but in that case we should have a different structure:
"variables": {
  "$water": {
    "_": "#001122",    // default color for all styles
    "dark": "#ffffff"  // override for the dark theme
  },
  "$river_width": {
    "_": 4,
    "light": 6,
  }
}
  • we might allow complex JSON expressions as values too, but I am not too certain we want to go this route

@alasram
Copy link

alasram commented Jul 10, 2024

This isn't doable with variables and case?

@nyurik
Copy link
Member

nyurik commented Jul 10, 2024

Wouldn't we want to "pre-compile" the style - i.e. simplify it before giving it to maplibre to speed it up? It's not like visualization needs to change often based on the variables. The switch between night/day mode would happen just a few times while driving (e.g. when going into a dark tunnel) - so might be better to have a distinct style that uses const values.

@nyurik
Copy link
Member

nyurik commented Jul 10, 2024

From @klokan:

Maputnik specific pre-processor - unrelated to MapLibre GL JS and Spec. Check:

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