【问题标题】:OpenLayers 6: Forcibly Select PolygonOpenLayers 6:强制选择多边形
【发布时间】:2019-12-04 17:19:24
【问题描述】:

我已经使用 Select 交互和 Draw 交互实现了 OpenLayers 6,我在它们之间切换。

我们可以假设用户只绘制多边形(三点或更多的几何图形)。

我希望绘制完成后选择多边形。

所以,我在 Draw 交互上监听“drawend”,将绘制交互设置为非活动,将选择交互设置为活动,但是我需要将选定的特征设置为仅绘制的特征。

到目前为止,我所拥有的只是我想出的这个笨重的 hack:

// Find the center point of the drawn feature (EPSG:3857)
const featureCenter: [number, number] = this._getCenterOfExtent(geometry.getExtent());
// Get the local pixel coordinate for the feature's center
const pixel: Pixel = this._map.getPixelFromCoordinate(featureCenter);
// Create a new MapBrowserEvent registering a 'click' on this local pixel coordinate
const mbEvent: MapBrowserEvent = new MapBrowserEvent('click', this._map, new MouseEvent('click', {
    bubbles: true,
    cancelable: true,
    clientX: pixel[0],
    clientY: pixel[1]
}));
// Turn off multi-polygon selection on our Select Interaction. We only want the top polygon at this spot.
this._registeredSelector.setProperties({
    multi: false
});
// Trigger the 'click' event on the map
this._map.dispatchEvent(mbEvent);

不幸的是,这并不总是有效。 我在我的 Select 交互中监听“点击”,它在强行触发点击后触发。 但是,有时,该事件具有 Point、LineString 和 Polygon 的多个几何图形。很多时候,它甚至在selected 数组中都没有多边形几何。其他时候,它在 selected 数组中有一个附近的 Polygon 几何体,而不是我们上次绘制的那个。

是否有OpenLayers原生方法强制触发选择特定特征?

另外,这是我的_getCenterOfExtent 方法:

/* EXPECTS EPSG:3857 */
private _getCenterOfExtent(extent: Extent):[number, number] {
    return [
        extent[0] + (extent[2]-extent[0])/2,
        extent[1] + (extent[3]-extent[1])/2
    ];
}

更新 对窗口对象使用我的点击事件的屏幕坐标似乎比在地图上尝试客户端坐标更准确。 此外,我发现在 Select Interaction 上以编程方式切换 multi 并没有实际工作,至少不是我尝试的方式。我切换到始终使用单选,这应该可以满足我们的需求。

const bbox: ClientRect | DOMRect = this._map.getTargetElement().getBoundingClientRect();
let mbEvent: MapBrowserEvent | undefined;
if (bbox) {
    pixel[0] += bbox.left;
    pixel[1] += bbox.top;
    mbEvent = new MapBrowserEvent('click', this._map, new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true,
        screenX: pixel[0],
        screenY: pixel[1]
    }));
} else {
    mbEvent = new MapBrowserEvent('click', this._map, new MouseEvent('click', {
        bubbles: true,
        cancelable: true,
        clientX: pixel[0],
        clientY: pixel[1]
    }));
}
this._map.dispatchEvent(mbEvent);

【问题讨论】:

    标签: typescript openlayers openlayers-6


    【解决方案1】:

    我在一个非常不起眼的地方找到了我的答案。这是an old answer to an old question 关于将视口拟合到一组选定的多边形。

    您似乎可以通过引用修改集合,地图将更新以反映更改。

    因此,我们可以从 Select Interaction 中获取所选特征的 Collection,清除内容,并设置新内容。

    import { Collection } from 'ol';
    
    ...
    
    type RegisteredListener = (event: MapBrowserEvent | DrawEvent | SelectEvent) => boolean;
    
    ...
    
    private _drawingSource: VectorSource = new VectorSource({wrapX: false});
    private _drawingLayer: VectorLayer = new VectorLayer({
        source: this._drawingSource
    });
    private _registeredDraw: Draw = new Draw({
        source: this._drawingSource,
        type: 'Polygon'
    });
    private _registeredSelector: Select = new Select({
        condition: click,
        multi: false,
        filter: (feature: FeatureLike, layer: Layer) => {
            const geometry: RenderFeature | Geometry | undefined = feature.getGeometry();
            if (geometry && geometry.getType() === 'Polygon') {
                return true;
            }
            return false;
        }
    });
    
    ...
    
    private _onDrawEnd: RegisteredListener = (event: DrawEvent) => {
        if (event.feature) {
            // Get Collection of selected Features
            const selectedCollection: Collection<FeatureLike> = this._registeredSelector.getFeatures();
            // Clear the Collection
            selectedCollection.clear();
            // Add the recently drawn Feature to the collection
            selectedCollection.push(event.feature);
            event.stopPropagation();
            // Re-enable the Select Interaction
            // If we don't set a timeout before enabling the Select Interaction again,
            // it will fire with the location if the last point, selecting only Point and/or LineString,
            // not the Polygon. This would clear the selected features. This occurs even if we stop the event propagation.
            setTimeout(() => {
                this._registeredDraw.setActive(true);
                this._registeredSelect.setActive(true);
            });
        }
        return false;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多