简体   繁体   English

TypeScript + OpenLayers 7:使用 forEachFeatureAtPixel() 方法无法在自定义层上找到特征

[英]TypeScript + OpenLayers 7: Can't find features on custom layer with forEachFeatureAtPixel() method

I can't find features on a custom layer with the forEachFeatureAtPixel() using the coordinates from a map.on('click') event listener.我无法使用来自 map.on('click') 事件侦听器的坐标在带有 forEachFeatureAtPixel() 的自定义层上找到功能。 The process is simple:过程很简单:

  1. I create the map object我创建了 map object
  2. I add a custom layer (FeatureLayer) to the map我向 map 添加了一个自定义层(FeatureLayer)
  3. I draw polygons using a custom control (DrawPolygonButton) and add them to the FeatureLayer source我使用自定义控件 (DrawPolygonButton) 绘制多边形并将它们添加到 FeatureLayer 源
  4. I want to remove clicked polygon(s) by using a custom control (RemovePolygonButton).我想使用自定义控件 (RemovePolygonButton) 删除单击的多边形。 The control listens to map click events to get map coordinates.控件监听 map 点击事件,获取 map 坐标。 The coordinates are used to find out if any polygons exist on the clicked coordinate.坐标用于找出单击的坐标上是否存在任何多边形。 For this, I use the forEachFeatureAtPixel method, but it always returns an empty array.为此,我使用了 forEachFeatureAtPixel 方法,但它总是返回一个空数组。
import Map from 'ol/Map'
import OSM from 'ol/source/OSM'
import Draw from 'ol/interaction/Draw';
import TileLayer from 'ol/layer/Tile'
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import View from 'ol/View'
import { Control } from 'ol/control'
import { Geometry } from 'ol/geom';
import { transform, useGeographic } from 'ol/proj';
import { FeatureLike } from 'ol/Feature';

/**
 * Map component
 */
export default class MapComponent {

    map: Map
    featureLayer: FeatureLayer

    constructor() {
        useGeographic()
        
        this.map = new Map({
            controls: [],
            layers: [
                new TileLayer({
                    source: new OSM(),
                })
            ],
            view: new View({
                center: [0, 0],
                zoom: 2
            }),
            target: "map"
        })

        this.featureLayer = new FeatureLayer()

        // Add Feature Layer
        this.map.addLayer(this.featureLayer)

        // Add Custom Controls to Draw- and Remove Polygon
        this.map.addControl(new DrawPolygonButton(this, this.map))
        this.map.addControl(new RemovePolygonButton(this, this.map))
    }

    public getFeatureLayer(): FeatureLayer {
        return this.featureLayer
    }

    public getMap() {
        return this.map
    }
}

/**
 * This is the layer we draw polygons (features) on
 */
class FeatureLayer extends VectorLayer<VectorSource<Geometry>> {
    constructor() { 
        super({
            source: new VectorSource(),
            properties: {
                title: 'featureLayer'
            }
        })
    }
}

/**
 * A button which starts the drawing process
 */
class DrawPolygonButton extends Control {
    constructor(mapComponent: MapComponent, map: Map) {
        const button = document.createElement('button')
        button.innerHTML = 'Draw Polygon'

        super({ element: button })

        button.addEventListener('click', () => {
            const featureLayerSource = mapComponent.getFeatureLayer()?.getSource()

            if (featureLayerSource) {
                new Polygon(map, featureLayerSource)
            }
        })
    }
}

/**
 * A button which should listen to clicking on the map, and if it hits a polygon on the
 * FeatureLayer it should remove it
 */
class RemovePolygonButton extends Control {
    constructor(mapComponent: MapComponent, map: Map) {
        const button = document.createElement('button')
        button.innerHTML = 'Remove Feature'

        super({ element: button })

        button.addEventListener('click', () => {
            map.on('click', (evt: any) => {
                const featuresInFeatureLayer = mapComponent.getFeatureLayer()?.getSource()?.getFeatures()
                console.log('Features in FeatureLayer: ', featuresInFeatureLayer) // Prints two polygon features

                const coordinate = transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326')
                const pixel = map.getPixelFromCoordinate(coordinate)
    
                const features: FeatureLike[] = []
                map.forEachFeatureAtPixel(pixel, function(feature, layer) {
                  features.push(feature);
                })

                console.log('Features: ', features) // Always shows empty array
            })
        })
    }
}

/**
 * The Polygon will be added to the map
 */
class Polygon extends Draw {
    constructor(map: Map, featureLayerSource: VectorSource) {
        super({
            type: 'Polygon',
            source: featureLayerSource
        })    

        this.on('drawend', () => {
            map.removeInteraction(this)
        })        

        map.addInteraction(this);
    } 
}

在此处输入图像描述

It does find the two polygon features on the FeatureLayer, but it never finds the feature(s) on the clicked/selected coordinate when clicking on any of the polygons.它确实在 FeatureLayer 上找到了两个多边形要素,但在单击任何多边形时,它永远不会在单击/选择的坐标上找到要素。 I also tried clicking all around the map, but the Feature array is always empty:我还尝试在 map 周围单击,但 Feature 数组始终为空:

在此处输入图像描述

Note: I tried put this in a code snippet, but it does not always like TypeScript eg when extending ol.Control... so I just pass the code.注意:我尝试将它放在代码片段中,但它并不总是像 TypeScript 例如在扩展 ol.Control 时...所以我只是传递代码。

Thanks!谢谢!

You do not need to transform the coordinate so您不需要转换坐标,所以

            const coordinate = transform(evt.coordinate, 'EPSG:3857', 'EPSG:4326')
            const pixel = map.getPixelFromCoordinate(coordinate)

            const features: FeatureLike[] = []
            map.forEachFeatureAtPixel(pixel, function(feature, layer) {
              features.push(feature);
            })

can become可以变成

            const pixel = map.getPixelFromCoordinate(evt.coordinate)

            const features: FeatureLike[] = []
            map.forEachFeatureAtPixel(pixel, function(feature, layer) {
              features.push(feature);
            })

but as the event also has a pixel property you can use但由于该事件还具有您可以使用的像素属性

            const features: FeatureLike[] = []
            map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
              features.push(feature);
            })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM