4

我刚开始使用 .Net 的 GEPlugin 控件使用 Google 地球进行编码,但仍有很多东西要学。

让我感到困惑的是当我尝试拖动多边形时。

每当 mousemove 事件触发并且应该移动多边形的每个点同时保持多边形的原始形状时,都会调用下面的方法。每个点的纬度/经度都会更改,但多边形不会在地图上移动位置。

在多边形中移动一个点会导致它重绘,我是否需要调用一个方法来强制重绘或者完全做其他事情?

谢谢!

private void DoMouseMove(IKmlMouseEvent mouseEvent)
    {
        if (isDragging)
        {
            mouseEvent.preventDefault();

            var placemark = mouseEvent.getTarget() as IKmlPlacemark;

            if (placemark == null)
            {
                return;
            }

            IKmlPolygon polygon = placemark.getGeometry() as IKmlPolygon;


            if (polygon != null)
            {
                float latOffset = startLatLong.Latitude - mouseEvent.getLatitude();
                float longOffset = startLatLong.Longitude - mouseEvent.getLongitude();

                KmlLinearRingCoClass outer = polygon.getOuterBoundary();
                KmlCoordArrayCoClass coordsArray = outer.getCoordinates();

                for(int i = 0; i < coordsArray.getLength(); i++)
                {
                    KmlCoordCoClass currentPoint = coordsArray.get(i);
                    currentPoint.setLatLngAlt(currentPoint.getLatitude() + latOffset, 
                        currentPoint.getLongitude() + longOffset, 0);
                }
            }
        }
    }
4

2 回答 2

1

更新:

我已经发布了扩展库:https ://bitbucket.org/mutopia/earth

请参阅https://bitbucket.org/mutopia/earth/src/master/sample/index.html运行它。

请参阅示例代码类中的 drag() 方法,该方法调用setDragMode()addDragEvent()以启用对KmlPolygon.


我在earth-api-utility-library和三个事件中使用takeOverCamera成功实现了这一点:

setDragMode: function (mode) {
    // summary:
    //      Sets dragging mode on and off
    if (mode == this.dragMode) {
        Log.info('Drag mode is already', mode);
    } else {
        this.dragMode = mode;
        Log.info('Drag mode set', mode);
        if (mode) {
            this.addEvent(this.ge.getGlobe(), 'mousemove', this.dragMouseMoveCallback);
            this.addEvent(this.ge.getGlobe(), 'mouseup', this.dragMouseUpCallback);
            this.addEvent(this.ge.getView(), 'viewchange', this.dragViewChange, false);
        } else {
            this.removeEvent(this.ge.getGlobe(), 'mousemove', this.dragMouseMoveCallback);
            this.removeEvent(this.ge.getGlobe(), 'mouseup', this.dragMouseUpCallback);
            this.removeEvent(this.ge.getView(), 'viewchange', this.dragViewChange, false);
        }
    }
},

这是在一个更大的项目中的实用程序库中。dragMode是一个添加和删除事件的布尔值。这三个事件控制拖动时发生的情况。addEvent并且removeEvent是我自己的包装函数:

addEvent: function (targetObject, eventID, listenerCallback, capture) {
    // summary:
    //      Convenience method for google.earth.addEventListener
    capture = setDefault(capture, true);
    google.earth.addEventListener(targetObject, eventID, listenerCallback, capture);
},

removeEvent: function (targetObject, eventID, listenerCallback, capture) {
    // summary:
    //      Convenience method for google.earth.removeEventListener
    capture = setDefault(capture, true);
    google.earth.removeEventListener(targetObject, eventID, listenerCallback, capture);
},

忽略次要细节,所有重要的东西都在这些事件的回调中。该mousedown事件锁定相机并将我拖动的多边形设置为dragObject(它只是我正在使用的一个变量)。它保存了原始的经纬度坐标。

this.dragMouseDownCallback = lang.hitch(this, function (event) {
    var obj = event.getTarget();
    this.lockCamera(true);
    this.setSelected(obj);
    this.dragObject = obj;
    this.dragLatOrigin = this.dragLatLast = event.getLatitude();
    this.dragLngOrigin = this.dragLngLast = event.getLongitude();
}

mousemove回调更新到最新的经纬度坐标:

this.dragMouseMoveCallback = lang.hitch(this, function (event) {
    if (this.dragObject) {
        var lat = event.getLatitude();
        var lng = event.getLongitude();
        var latDiff = lat - this.dragLatLast;
        var lngDiff = lng - this.dragLngLast;
        if (Math.abs(latDiff) > this.dragSensitivity || Math.abs(lngDiff > this.dragSensitivity)) {
            this.addPolyCoords(this.dragObject, [latDiff, lngDiff]);
            this.dragLatLast = lat;
            this.dragLngLast = lng;
        }
    }
});

在这里,我使用了一些花哨的灵敏度值来防止过于频繁地更新它。最后,addPolyCoords也是我自己的函数,它将经纬度值添加到多边形的现有坐标中 - 有效地将其移动到全球范围内。我使用每个坐标的内置函数setLatitude()和函数来执行此操作。setLongitude()您可以像这样获得坐标,其中多边形是一个KmlPolyon对象:

polygon.getGeometry().getOuterBoundary().getCoordinates()

当然,mousedown回调会关闭拖动模式,这样移动鼠标就不会继续拖动多边形:

this.dragMouseUpCallback = lang.hitch(this, function (event) {
    if (this.dragObject) {
        Log.info('Stop drag', this.dragObject.getType());
        setTimeout(lang.hitch(this, function () {
            this.lockCamera(false);
            this.setSelected(null);
        }), 100);
        this._dragEvent(event);
        this.dragObject = this.dragLatOrigin = this.dragLngOrigin = this.dragLatLast = this.dragLngLast = null;
    }
});

最后,_dragEvent调用以确保最终坐标是鼠标事件完成的实际坐标(而不是最新mousemove调用):

_dragEvent: function (event) {
    // summary:
    //      Helper function for moving drag object
    var latDiff = event.getLatitude() - this.dragLatLast;
    var lngDiff = event.getLongitude() - this.dragLngLast;
    if (!(latDiff == 0 && lngDiff == 0)) {
        this.addPolyCoords(this.dragObject, [latDiff, lngDiff]);
        Log.info('Moved ' + latDiff + ', ' + lngDiff);
    }
},

回调不是很重要,mousemove实际上可以忽略 - 我使用它的唯一原因是显示多边形在用户移动鼠标时移动。移除它会导致当他们抬起鼠标时对象被移动。

希望这个令人难以置信的长答案能让您对如何在 Google 地球 API 中实现拖动有所了解。而且我还计划在将来解决问题后发布我的库:)

于 2013-01-22T11:23:55.793 回答