簡體   English   中英

TypeScript + OpenLayers 7:設置和獲取功能 ID 失敗

[英]TypeScript + OpenLayers 7: Set and get feature id fails

我有一個帶有兩個自定義按鈕的 map: Draw PolygonRemove Feature ,它允許我繪制和刪除繪制的多邊形。 此外,我為顯示其面積的多邊形創建了一個測量疊加層(見圖)。 為了識別多邊形和覆蓋之間的連接,我嘗試在它們上設置相同的 id,以便在刪除多邊形時可以找到並刪除覆蓋:

const featureId = feature.get('id')
const overlay = map.getOverlayById(featureId)
map.removeOverlay(overlay)

但是,當嘗試讀取多邊形的 id 時,它總是返回 undefined。 我還嘗試將 id 設置為屬性並獲取它,但這也失敗了。

為了更容易跟隨:

  • 我在多邊形 class 中分配 id
  • 我在 RemovePolygonButton class 中讀取了 ID

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 Feature, { FeatureLike } from 'ol/Feature';
import { Overlay } from 'ol';
import { getArea } from 'ol/sphere';
import { unByKey } from 'ol/Observable';
import { EventsKey } from 'ol/events';
import { Coordinate } from 'ol/coordinate';

/**
 * 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 want to draw the polygon (feature) 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) => {
                try {
                    const featureLayerSource = mapComponent.getFeatureLayer()?.getSource()
    
                    const features: any[] = [] // It does find features
                    map.forEachFeatureAtPixel(evt.pixel, function(feature, layer) {
                        features.push(feature);
                    })

                    for (const feature of features) {
                        console.log('Feature: ', feature) // Feature exist
                        console.log('Title: ', feature.get('title')) // undefined
                        console.log('ID: ', feature.get('id')) // undefined
                        console.log('ID: ', feature.getId()) // undefined
    
                        const featureId = feature.get('id')
                        const overlay = map.getOverlayById(featureId)

                        // Remove overlay
                        map.removeOverlay(overlay)

                        // Remove feature
                        featureLayerSource?.removeFeature(feature)

                    }
                } catch (err) {
                    console.log('Error: ', err)
                }
            })
        })
    }
}

/**
 * The Polygon will be added to the map
 */
class Polygon extends Draw {
    id: string
    sketch: Feature | undefined
    measureTooltipElement: HTMLElement | undefined
    measureTooltip: Overlay | undefined

    constructor(map: Map, featureLayerSource: VectorSource) {
        super({
            type: 'Polygon',
            source: featureLayerSource
        })    

        this.id = 'randomid' // Creating id

        // this.setId('randomId') This does not work: Property 'setId' does not exist on type 'Polygon'.ts(2339)

        this.set('id', this.id) // Assigning id with set()

        this.setProperties({ // Assigning id (and title) with setProperties() 
            'id': this.id,
            'title': this.id
        })

        this.createMeasureTooltip(map)
        let listener: EventsKey | EventsKey[] | undefined = undefined

        this.on('drawstart', (event: any) => {
            this.sketch = event.feature
            
            if (!this.sketch) {
                return
            }

            let tooltipCoord: Coordinate = event.coordinate;
        
            // Show measurements while drawing
            listener = this.sketch.getGeometry()?.on('change', (evt: any) => {
                const geom = evt.target
                const output = this.formatArea(geom)
                tooltipCoord = geom.getInteriorPoint().getCoordinates()
            
                if (this.measureTooltipElement && this.measureTooltip) {
                    this.measureTooltipElement.innerHTML = output
                    this.measureTooltip.setPosition(tooltipCoord)
                }
            })
        })


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

            if (this.measureTooltipElement && this.measureTooltip) {
                this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'
                this.measureTooltip.setOffset([0, -7])

                // unset sketch
                this.sketch = undefined
                
                // unset tooltip so that a new one can be created
                this.measureTooltipElement = undefined
                this.createMeasureTooltip(map)
                
                if (listener) {
                    unByKey(listener)
                }
            }

            // Create measure tooltip
            this.createMeasureTooltip(map)
        })        

        map.addInteraction(this);
    } 

    private formatArea(polygon: any): string {
        const area = getArea(polygon)
        return area > 10000 ? 
            Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>' :
            Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>'
    }

    private createMeasureTooltip(map: Map): void {
        if (this.measureTooltipElement) {
            this.measureTooltipElement?.parentNode?.removeChild(this.measureTooltipElement)
        }

        this.measureTooltipElement = document.createElement('div')
        this.measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'
        this.measureTooltip = new Overlay({
            id: this.id, // Assigning overlay id
            element: this.measureTooltipElement,
            offset: [0, -15],
            positioning: 'bottom-center',
            stopEvent: false,
            insertFirst: false,
        })

        map.addOverlay(this.measureTooltip)
    }
}

在此處輸入圖像描述 在此處輸入圖像描述

您的代碼正在繪制交互上設置屬性,以設置您需要繪制的特征的屬性或 id

    this.on('drawend', (event) => {
        event.feature.setId('randomId')
        

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM