OpenLayers 要素查询的三种方法

前言

要素(Feature)查询是GIS开发要解决的一个重要问题,通过数据查询是否高效、准确,可以判断一个GIS系统是否具备易用性。要素查询作为GIS开发的核心功,常用于地图交互、空间分析与过滤等场景。

本文将介绍两个Map对象方法forEachFeatureAtPixel(pixel)getFeaturesAtPixel(pixel)和一个矢量图层方法getFeatures(pixel)三种要素查询的方法,读者可以根据自己的应用场景进行选择。

1. forEachFeatureAtPixel(pixel)

forEachFeatureAtPixel:

该方法为Map对象属性,接收三个参数:第一个参数为事件像素坐标;第二个参数为回调函数;第三个参数为可选对象。

检测视口上与像素相交的特征,并对每个相交的特征执行回调。对于没有填充的多边形,只有笔划将用于命中检测。多边形必须应用填充样式,以确保检测到多边形内的像素。填充物可以是透明的。

const feature = map.forEachFeatureAtPixel(pixel, feature => feature, {})

第一个参数很简单,就不多做解释了,重点说一下后两个参数。第二个参数callback是一个回调函数,该回调函数具有两个参数,具体可见下方说明(来源于百度翻译)

  • 回调函数将使用两个参数调用。
  • 第一个参数是像素处的一个特征或渲染特征,第二个参数是该特征的图层,对于非托管图层将为空。
  • 为了停止检测,回调函数可以返回一个真值。

具体使用就是可以使用回调函数返回查询要素,并且在查询到数据之后,返回一个真值以停止检测。

const feature = map.forEachFeatureAtPixel(pixel, feature => {
    if (feature) {
        return feature
    }
})

第三个参数为可选对象,主要是规定了数据过滤的附加条件。该对象又具有三个参数,第一个参数layerFilter为图层过滤器;第二个参数hitTolerance为过滤容差值;第三个参数检查是否是有效的几何对象,反正使用默认值,设置为true就OK了。

图层过滤器参数可以用一个函数表示,这个函数具有一个图层(Layer)参数,可以根据图层属性如名称、可见性、缩放大小等进行过滤。

const feature = map.forEachFeatureAtPixel(pixel, feature => {
    if (feature) {
        return feature
    }
}, {
    // 图层过滤器
    layerFilter: (layer) => {
        const properties = layer.getProperties()
        if (properties.title === "云南行政区") {
            return false
        }
    }
})

如下图所示,当将过滤条件设置为【图层名称为云南行政区】则不进行检测,此时将鼠标移入行政区图层没有反应,若想查询指定图层,将返回值改为true即可。

hitTolerance参数为过滤容差,默认值为0,单位为CSS像素。通过该值可以检测给定位置以容差值为半径圆形区域内的要素。

const feature = map.forEachFeatureAtPixel(pixel, feature => {
    if (feature) {
        return feature
    }
}, {
    // 图层过滤器
    layerFilter: (layer) => {
        const properties = layer.getProperties()
        if (properties.title === "云南行政区") {
            return false
        }
    },
    // 过滤容差
    hitTolerance: 100
})

如上我将过滤容差设置为100个像素单位,则鼠标还处于查询图层外部就可以查询到要素信息。

2. getFeaturesAtPixel(pixel)

getFeaturesAtPixel:

该方法与forEachFeatureAtPixel一样,都属于Map对象属性。但是getFeaturesAtPixel方法只接收两个参数。第一个参数为事件像素坐标;第二个参数为可选对象。

两者的区别在于参数个数和返回值不一样。使用getFeaturesAtPixel方法如果查询到数据的将会返回一个要素数组,否则返回一个空数组。其实现效果与forEachFeatureAtPixel一致。

const features = map.getFeaturesAtPixel(pixel, {
    // 图层过滤器
    layerFilter: (layer) => {
        const properties = layer.getProperties()
        if (properties.title === "云南行政区") {
            return true
        }
    },
    // 过滤容差
    hitTolerance: 100
})

3. getFeatures(pixel)

getFeatures(pixel):

getFeatures(pixel)方法与前两个不同,它是矢量图层属性,接收一个事件像素坐标参数,并返回一个Promise对象。

以下来源于百度翻译:

使用此方法可以获取视口上与给定像素【相交】的最顶部特征。用于此方法的命中检测算法针对性能进行了优化,但不如【map.getFeaturesAtPixel()】中使用的算法准确。不考虑文本,图标仅由其边界框表示,而不是精确的图像。

regionLayer.getFeatures(pixel).then(features => {
  // 若未查询到要素,则退出
  if (!features.length) {
      if (highlightFeat) {
          highlightLayer.getSource().removeFeature(highlightFeat)
          highlightFeat = undefined
      }
      return
  }
  // 获取要素属性
  const properties = features[0].getProperties()
  // 将事件坐标转换为地图坐标
  const coords = map.getCoordinateFromPixel(pixel)
  if (features[0] != highlightFeat) {
      // 移除高亮要素
      if (highlightFeat) {
          highlightLayer.getSource().removeFeature(highlightFeat)
          highlightFeat = undefined
      }
      highlightLayer.getSource().addFeature(features[0])
      highlightFeat = features[0]
  }
  openPopupTable(properties, popupColums, coords)
})

4. 三个方法对比

方法名

所属对象

参数

返回值

forEachFeatureAtPixel

Map

{pixel,callback,options}

最后一个回调执行值或者第一个为真的回调值

getFeaturesAtPixel

Map

{pixel,options}

一个要素数组或者空数组

getFeatures

VectorLayer

{pixel}

一个解析了要素数组的Promise对象

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部