如何使用 Vuelayers 与 GeoServer 提供的 WMS 瓦片层进行交互?

Posted

技术标签:

【中文标题】如何使用 Vuelayers 与 GeoServer 提供的 WMS 瓦片层进行交互?【英文标题】:How do I interact with WMS tile layer served by GeoServer using Vuelayers? 【发布时间】:2019-05-26 23:32:16 【问题描述】:

我正在使用 Vuelayers 库开发一个网络地图应用程序,该库是 具有 OpenLayers 功能的网络地图 Vue 组件

我的模板中有以下代码:

<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>

在数据对象中我有以下属性:

     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',
                ,
            ,
     ....
    ]

那么当我点击它时如何获取图层属性呢?知道vl-tile-layer 没有提到的@click 事件here

【问题讨论】:

你不应该避免v-if with v-for吗? @Andrew1325 不是问题,这工作正常,但我找不到与 WMS 层交互的方法 是的,我知道,只是说。这是一个棘手的问题。 你见过this吗? 我建议将一个包含依赖项的代码框和一个简单的示例放在一起来重现问题。 【参考方案1】:

只需将点击处理程序放在***地图组件上,如下所示:

<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>

然后在点击事件中使用forEachLayerAtPixel 函数,该函数对显示在该屏幕像素的每一层进行操作,并为您提供ol.Layer.Layer 对象,您可以在该对象上调用getProperties():

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

只有在服务器上设置了 CORS 并且您可以在 vue-layers 在幕后使用的 OpenLayers 层上设置 crossOrigin 设置时,上述内容才有效。上述方法更好,但如果您收到错误说明

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

然后你可以使用更通用的函数,比如

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.
        
)

【讨论】:

感谢您的回答,但当我尝试时,我收到此错误Error in v-on handler: "SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data 是的,我对开放图层不是很熟悉,但这听起来像是一个不容易解决的画布问题。您可以查找该错误并查看它是 canvas 元素的安全功能,只能使用服务器端标头解决,或者您可以使用更通用的功能。我将编辑我的答案以反映。 历史记录在这个答案的修订历史中。也许更改答案以仅反映最新版本? (如果需要,可以在此处的 cmets 中对更改进行进一步说明。) 第一个版本可以工作并且是首选,但需要使用 CORS 正确设置服务器。 vue-layers 的文档也不完整,并且没有指定在支持 OpenLayers 层中设置 crossOrigin 设置的方法。

以上是关于如何使用 Vuelayers 与 GeoServer 提供的 WMS 瓦片层进行交互?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 android google map v2 实现上为 geoserver 瓦片重新加载 TileOverlay

回头看一看我的2017年

Swinject:如何将委托模式与接口隔离(类与接口)一起使用?

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如何将 CameraX 与 PreviewView 一起使用?

如何将 groupBy 与 MagicalRecord 一起使用?