openlayers / ol-mapbox-style

Use Mapbox Style objects with OpenLayers
https://unpkg.com/ol-mapbox-style/dist/examples/index.html
BSD 2-Clause "Simplified" License
348 stars 120 forks source link

Applying style to VectorTile layer #1106

Closed lukastemberga closed 7 months ago

lukastemberga commented 7 months ago

Hi,

I'm trying to use mapbox defined style on VectorTile layers in OpenLayers. The issue I am having is I can't seem to figure out if it's possible to define VectorTileSource (with url fetching data from my server) and VectorTileLayer which should only apply styling from Mapbox or Mapbox style JSON file.

Map itself and other Openlayers logic is made using React, but this is how I'm trying to do it:

        const vectorTileSource = new VectorTileSource({
            format: new MVT({ featureClass: Feature }),
            url: `${import.meta.env.VITE_TEGOLA_URL}${layer.layerInfo.url}`,
        });

        const vectorTileLayer = new VectorTileLayer({
            source: vectorTileSource,
            //style: layerStyle,         // I turned off old way of applying style to layer
            zIndex: layer.layerInfo.zIndex,
            maxZoom: layer.layerInfo.maxZoom,
            minZoom: layer.layerInfo.minZoom,
            properties: {
                name: layer.label,
                id: layer.id,
                layerType: layer.layerInfo.type,
            },
            declutter: false,
            opacity: layer.layerInfo.opacity,
        });

        applyStyle(vectorTileLayer, "mapbox://styles/devs-list/cltn0bfqg001501pj1m04allj", {
            accessToken: "pk.ey...",
            updateSource: false,
        });

        map.addLayer(vectorTileLayer);

I have included below the .json file of style definition style.json

I have also tried implementing this using stylefunction from ol-mb but as far as I can see the behavior is pretty much same. I can see that tiles are loaded on map and on move (served from tegola) and there is nothing displaying in console nor there are some errors in network tab when inspecting requests. I can confirm tiles and features are displayed when I comment out applyStyle function.

Am I missing something obvious here? Is it even possible to do apply style to a source not defined through mapbox?

ahocevar commented 7 months ago

What you're trying here is definitely possible. However, you might want to start small and then make bigger changes to make debugging easier. Questions that arise include:

lukastemberga commented 7 months ago

Does the style make sense for the data, e.g. is there a source-layer: 'test_hidro', are there polygon geometries in the test_hidro layer?

This was the issue, I was trying to adjust source property to match name of layer from tegola, while all I had to do was adjust source-layer property to that of layer name coming from tegola. I don't know if there is a way to change source-layer name in mapbox since I made a naming mistake when uploading my data initially therefore .json response always contained wrong source-layer name. In the end I decided to download style and put it into my .../public/ folder and load style from there.

Your help is much appreciated!

I'am closing this issue but here is the way I did it if it helps someone in the future:

JS:

        const vectorTileSource = new VectorTileSource({
            format: new MVT({ featureClass: Feature }),
            url: `${import.meta.env.VITE_TEGOLA_URL}${layer.layerInfo.url}`,
        });
       const vectorTileLayer = new VectorTileLayer({
            source: vectorTileSource,
            //style: layerStyle,
            zIndex: 99999,
            maxZoom: 99,
            minZoom: 0,
            properties: {
                name: layer.label,
                slice: slice ?? "",
                hasZoomConstraint: !!minZoom || !!maxZoom,
                id: layer.id,
                layerType: layer.layerInfo.type,
            },
            declutter: true,
            opacity: 1,
        });

        applyStyle(vectorTileLayer, "/style.json", {
            accessToken: "pk.ey...", // Not sure if needed since I'm loading style locally (.../public/style.json)
            updateSource: false,
        });

        map.addLayer(vectorTileLayer);

style.json

{
    ...
    "layers": [
        {
            "id": "test",
            "type": "fill",
            "source": "composite",
            "source-layer": "test-hidro", // Layer name from tegola capabilities
            "layout": {},
            "paint": {
                "fill-color": [
                    "interpolate",
                    ["linear"],
                    ["zoom"],
                    0,
                    "hsl(308, 100%, 60%)",
                    22,
                    "hsl(308, 100%, 60%)"
                ],
                "fill-outline-color": "hsl(265, 100%, 22%)"
            }
        }
    ],
    ...
}

Tegola capabilities:

{
  "version": "v0.16.0",
  "maps": [
    {
      "name": "my_dataset",
      "attribution": "",
      "bounds": [
        -180,
        -85.0511,
        180,
        85.0511
      ],
      "center": [
        16.5166646,
        43.7333304,
        12
      ],
      "tiles": [
        ".../tegola/maps/my_dataset/{z}/{x}/{y}.pbf"
      ],
      "capabilities": ".../tegola/capabilities/my_dataset.json",
      "layers": [
        {
          "name": "test_hidro",
          "tiles": [
            ".../tegola/maps/data/my_dataset/{z}/{x}/{y}.pbf"
          ],
          "minzoom": 1,
          "maxzoom": 20
        }
      ]
    }
  ]
}