maplibre / maputnik

An open source visual editor for the 'MapLibre Style Specification'
https://www.maplibre.org/maputnik
MIT License
2.05k stars 388 forks source link

Add ability to create a style with multiple themes #909

Open amousavi opened 1 month ago

amousavi commented 1 month ago

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 commented 1 month ago

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

Maputnik UI changes

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

"variables": {
  "$water": {
    "_": "#001122",    // default color for all styles
    "dark": "#ffffff"  // override for the dark theme
  },
  "$river_width": {
    "_": 4,
    "light": 6,
  }
}
alasram commented 1 month ago

This isn't doable with variables and case?

nyurik commented 1 month ago

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 commented 1 month ago

From @klokan:

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