How do I interact with WMS tile layer served by GeoServer using Vuelayers?
Asked Answered
S

1

8

I'm developing a web mapping application using the Vuelayers library which is Web map Vue components with the power of OpenLayers.

I have the following code in my template:

<vl-map @singleclick="hideOverlay" @postcompose="onMapPostCompose"
 :load-tiles-while-animating="true" ref="map"
:load-tiles-while-interacting="true" data-projection="EPSG:4326"
style="height: 900px" @mounted="onMapMounted">
 ....

  <component v-for="layer in layers" :ref="layer.id" overlay
    :is="layer.cmp"
    :key="layer.id" v-bind="layer">
        <component :is="layer.source.cmp" v-if="layer.visible" v-bind="layer.source">
        </component>
    </component>
     ....
</vl-map>

And in the data object I have the following property:

     layers: [

            {
                id: 'sections',
                title: 'Sections',
                cmp: 'vl-layer-tile',
                visible: true,

                source: {
                    cmp: 'vl-source-wms',
                    url: 'http://localhost:8080/geoserver/sager/wms',
                    layers: 'sections',
                    tiled: true,
                    format: 'image/png',
                    serverType: 'geoserver',
                },
            },
     ....
    ]

So how do I get the layer properties when I click on it? Knowing that vl-tile-layer doesn't have the @click event as mentioned here.

Scat answered 26/5, 2019 at 23:32 Comment(7)
Shouldn't you avoid v-if with v-for?Burleigh
@Burleigh is not the issue, this works fine, but i don't find a way to interact with WMS layerScat
Yeah, I know, just saying. It is a tricky one.Burleigh
Have you seen this?Burleigh
@Burleigh thanks i removed it to avoid any future issueScat
@Burleigh i tried that but with no successScat
I would suggest putting together a codesandbox with the dependencies and a simple example to reproduce the issue.Dunkle
E
5

Just put the click handler on the top level map component like so:

<vl-map @click="mapClick" @singleclick="hideOverlay" @postcompose="onMapPostCompose"
 :load-tiles-while-animating="true" ref="map"
:load-tiles-while-interacting="true" data-projection="EPSG:4326"
style="height: 900px" @mounted="onMapMounted">

</vl-map>

Then in the click event use the forEachLayerAtPixel function which operates on each layer that is displaying at that screen pixel and gives you the ol.Layer.Layer object which you can call getProperties() on:

 methods: {
  mapClick: function(evt){
    evt.map.forEachLayerAtPixel(
        evt.pixel,
        function(layer){ layer.getProperties()},
        function(layer){/*filter layers you want to get property data on*/})
  }
}

The above will only work if CORS is setup on the server and if you can set the crossOrigin setting on the OpenLayers layer that vue-layers is using behind the scenes. the above method is better but if you get an error stating

"SecurityError: Failed to execute 'getImageData' on 
'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data

Then you can use a more general function like

evt.map.getLayers().item(0)

or

evt.map.getLayers.forEach(
    function(layer){
        layerProps = layer.getProperties()
        if(layerProps.id === "the one you want")
        {
            // You will have to implement your own intersection logic here
            // to see if the click point intersected with the layer.
        }
})
Esemplastic answered 3/6, 2019 at 14:32 Comment(4)
thank you for your answer but when i try it i get this error Error in v-on handler: "SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin dataScat
Yeah I'm not very familiar with open layers but that sounds like a canvas issue that is not going to be easy to solve. You can lookup that error and see that it's an security feature of the canvas element that can only be worked around with server side headers or you can use a more general function. I will edit my answer to reflect.Esemplastic
The historical account is in the revision history of this answer. Perhaps change the answer to only reflect the most current version? (If needed, further explanation for the change can be put in comments here.)Lappet
the first version will work and is preferred but requires the server to be setup properly with CORS. Also the documentation for vue-layers is incomplete and does not specify a way to set the crossOrigin setting in the backing OpenLayers layer.Esemplastic

© 2022 - 2024 — McMap. All rights reserved.