maplibre / maplibre-style-spec

MapLibre Style Specification & Utilities
https://maplibre.org/maplibre-style-spec/
Other
92 stars 65 forks source link

Bug: literal expression cannot parse ["get", ..] #545

Open IKondor opened 9 months ago

IKondor commented 9 months ago

Describe the bug

Trying to move text like this style and have error with this expression

"text-offset": [
  "array",
  "number",
  2,
  [
    "literal",
    [
      ["number", ["get", "label_x"]],
      ["number", ["get", "label_y"]]
    ]
  ]
]

There is html example https://github.com/IKondor/temp

To Reproduce

Expected behavior No console errors

Additional context So I looked at the sources and discovered the intended location which have some errors

src/expression/definitions/assertion.ts line 88, checkSubtype call && typeOf call checkSubtype from src/expression/types.ts typeOf from src/expression/values.ts

The bug is

typeOf([
      ["number", ["get", "label_x"]],
      ["number", ["get", "label_y"]]
    ])

have itemType array<value, 2> type, but I have never way to cast it to <number, 2>

Even if I add the numbers cast as in the example above, its won't work

May be there is another way?

Screenshots Снимок экрана от 2024-02-19 19-00-54 Снимок экрана от 2024-02-19 19-01-03 Снимок экрана от 2024-02-19 19-03-24 Снимок экрана от 2024-02-19 19-03-32

Desktop (please complete the following information):

HarelM commented 9 months ago

I think this is the same as: https://github.com/mapbox/mapbox-gl-js/issues/6155 It's probably just not implemented, or not implemented correctly.

The following is working, but according to the linked thread I think it only works for geojson and not vector tiles, but you can try and test that out: The difference is that I created a propery to hold an array of two points instead of two different properties. This is also somewhat relevant: https://stackoverflow.com/questions/52715411/mapbox-gl-data-driven-styling-for-text-offset

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Test</title>
    <meta property="og:description" content="Use extrusions to display buildings' height in 3D." />
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.0.1/dist/maplibre-gl.css" />
    <script src="https://unpkg.com/maplibre-gl@4.0.1/dist/maplibre-gl.js"></script>
    <style>
      body {
        margin: 0;
        padding: 0;
      }

      #map {
        position: absolute;
        height: 100vh;
        width: 100%;
        background: #202020;
      }
    </style>
  </head>

  <body>
    <div id="map"></div>
    <script>
      const map = new maplibregl.Map({
        style: {
          version: 8,
          name: "Raster Tiles",
          glyphs:
            "https://smellman.github.io/creating_tiles_with_global_map_support_files/2015/mapbox_vector_tile_demo/demosites/fonts/{fontstack}/{range}.pbf",
          sprite:
            "https://smellman.github.io/creating_tiles_with_global_map_support_files/2015/mapbox_vector_tile_demo/demosites/maki-sprites/sprite",
          sources: {
            osm: {
              type: "raster",
              tiles: [
                "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
                "https://b.tile.openstreetmap.org/{z}/{x}/{y}.png",
                "https://c.tile.openstreetmap.org/{z}/{x}/{y}.png"
              ],
              tileSize: 256
            },
            power_stations: {
              type: "geojson",
              data: {
                type: "FeatureCollection",
                features: [
                  {
                    type: "Feature",
                    geometry: {
                      type: "Point",
                      coordinates: [20, 35]
                    },
                    properties: {
                      label_x: 5,
                      label_y: 5,
                      description: "test",
                      label_x_y: [5, 5]
                    }
                  }
                ]
              }
            }
          },
          layers: [
            {
              id: "osm",
              type: "raster",
              source: "osm",
              paint: {
                "raster-fade-duration": 100
              }
            },
            {
              id: "point",
              type: "circle",
              source: "power_stations",
              paint: {
                "circle-radius": 10,
                "circle-color": "#3887be"
              }
            },
            {
              id: "poi-labels",
              type: "symbol",
              source: "power_stations",
              layout: {
                "text-offset": ["get", "label_x_y"],
                "text-field": ["concat", "x=", ["get", "label_x"], ", ", "y=", ["get", "label_y"]]
              }
            }
          ]
        },
        zoom: 5,
        center: [20, 35],
        container: "map",
        antialias: true,
        hash: true
      });

      map.on("load", () => {
        console.log(map);
      });
    </script>
  </body>
</html>
IKondor commented 9 months ago

Thanks! That solved my issue

Maybe I misunderstand this line in specs

If an expression accepts an array argument and the user supplies an array literal, that array must be wrapped in a literal expression

https://maplibre.org/maplibre-style-spec/expressions/#type-system

Also this expression is also incorrectly parsed, I think in same reason

[
  "literal",
  [
    ["+", 10, 10],
    ["+", 10, 10]
  ]
]