OpenLayers:使用ModifyFeature作为Polygon或其他方式旋转图像

时间:2014-02-02 16:05:30

标签: javascript bitmap rotation openlayers

我需要允许用户使用OpenLayers.Control.ModifyFeature或其他方式在地图上旋转位图功能,因为它适用于多边形或其他几何对象,但Point除外,但只有Point I可以使用我的位图设置“externalGraphic”。像我预期的那样将ModifyFeature转换为旋转的示例:ModifyFeature example

当我使用Point几何体添加Vector并激活ModifyFeature时,没有显示旋转工具 - 只有拖放。我知道什么是重点,但我需要有旋转位图功能的工具。它可能是任何其他几何对象上的图像,但可能是自定义图像。

2 个答案:

答案 0 :(得分:0)

经过长时间的研究,我在gis.stackexchange.com找到了一个例子并修复了它。 这是一个适合我的代码:

OpenLayers.Control.RotateGraphicFeature = OpenLayers.Class(OpenLayers.Control.ModifyFeature, {
    rotateHandleStyle: null,

    initialize: function(layer, options) {
        OpenLayers.Control.ModifyFeature.prototype.initialize.apply(this, arguments);
        this.mode = OpenLayers.Control.ModifyFeature.ROTATE; // This control can only be used to rotate the feature
        this.geometryTypes = ['OpenLayers.Geometry.Point'] // This control can only be used to rotate point because the 'exteralGraphic' is a point style property

        var init_style = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style.select);
        this.rotateHandleStyle = OpenLayers.Util.extend(init_style, {
            externalGraphic: "./static/resources/images/cross.png",
            graphicWidth: 12,
            graphicHeight: 12,
            fillOpacity: 1
        });

    },

    resetVertices: function() {
        // You need to set yours renderIntent or use "vertex"
        if (this.feature && this.feature.renderIntent == "vertex") {
            var vertex = this.feature;
            this.feature = this.backup_feature;
            this.layer.destroyFeatures([this.radiusHandle], {silent: true});
            this.collectRadiusHandle();
            return;
        }
        if (this.dragControl.feature) {
            this.dragControl.outFeature(this.dragControl.feature);
        }
        if (this.vertices.length > 0) {
            this.layer.removeFeatures(this.vertices, {silent: true});
            this.vertices = [];
        }
        if (this.virtualVertices.length > 0) {
            this.layer.removeFeatures(this.virtualVertices, {silent: true});
            this.virtualVertices = [];
        }
        if (this.dragHandle) {
            this.layer.destroyFeatures([this.dragHandle], {silent: true});
            this.dragHandle = null;
        }
        if (this.radiusHandle) {
            this.layer.destroyFeatures([this.radiusHandle], {silent: true});
            this.radiusHandle = null;
        }
        if (this.feature && this.feature.geometry &&
            this.feature.geometry.CLASS_NAME != "OpenLayers.Geometry.Point") {
            if ((this.mode & OpenLayers.Control.ModifyFeature.DRAG)) {
                this.collectDragHandle();
            }
            if ((this.mode & (OpenLayers.Control.ModifyFeature.ROTATE |
            OpenLayers.Control.ModifyFeature.RESIZE))) {
                this.collectRadiusHandle();
            }
            if (this.mode & OpenLayers.Control.ModifyFeature.RESHAPE) {
                if (!(this.mode & OpenLayers.Control.ModifyFeature.RESIZE)) {
                    this.collectVertices();
                }
            }
        }
        this.collectRadiusHandle();
    },

    collectRadiusHandle: function() {
        var scope = this,
            feature = this.feature,
            geometry = this.feature.geometry || this.backup_feature.geometry,
            centroid = geometry.getCentroid().transform(this.WGS84_google_mercator, this.WGS84),
            lon = centroid.x, lat = centroid.y;

        if (this.feature.geometry) {
            this.backup_feature = this.feature;
        } else {
            this.feature.geometry = this.backup_feature.geometry;
        }

        var originGeometry = new OpenLayers.Geometry.Point(lon, lat);

        // radius geometry position.
        var pixel_dis_x = 10,
            pixel_dis_y = -10;
        var rotationFeatureGeometry = new OpenLayers.Geometry.Point(lon+pixel_dis_x, lat+pixel_dis_y);

        var rotationFeature = new OpenLayers.Feature.Vector(rotationFeatureGeometry, null, this.rotateHandleStyle);
        var resize = (this.mode & OpenLayers.Control.ModifyFeature.RESIZE);
        var reshape = (this.mode & OpenLayers.Control.ModifyFeature.RESHAPE);
        var rotate = (this.mode & OpenLayers.Control.ModifyFeature.ROTATE);

        rotationFeatureGeometry.move = function(x, y) {
            OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
            var dx1 = this.x - originGeometry.x;
            var dy1 = this.y - originGeometry.y;
            var dx0 = dx1 - x;
            var dy0 = dy1 - y;
            if (rotate) {
                var a0 = Math.atan2(dy0, dx0);
                var a1 = Math.atan2(dy1, dx1);
                var angle = a1 - a0;
                angle *= 180 / Math.PI;
                var old_angle = feature.attributes.angle;
                var new_angle = old_angle - angle;
                feature.attributes.angle = new_angle;
                // redraw the feature
                scope.feature.layer.redraw.call(scope.feature.layer);
            }
        };
        rotationFeature._sketch = true;
        this.radiusHandle = rotationFeature;
        this.radiusHandle.renderIntent = this.vertexRenderIntent;
        this.layer.addFeatures([this.radiusHandle], {silent: true});
    },

    CLASS_NAME: "OpenLayers.Control.RotateGraphicFeature"
});

您的Vector的样式可能如下:

new OpenLayers.StyleMap({
        "default": new OpenLayers.Style({
            externalGraphic: "link/to/icon",
            graphicHeight: "32px",
            graphicWidth: "25px",
            fillOpacity: 1,
            rotation: "${angle}",
            graphicZIndex: 1
        })

 })

答案 1 :(得分:0)

UPD:我为OpenLayers 2.13.1

修复了它
OpenLayers.Control.RotateGraphicFeature = OpenLayers.Class(OpenLayers.Control.ModifyFeature, {
        rotateHandleStyle: null,

        initialize: function (layer, options) {
            OpenLayers.Control.ModifyFeature.prototype.initialize.apply(this, arguments);
            this.mode = OpenLayers.Control.ModifyFeature.ROTATE; // This control can only be used to rotate the feature
            this.geometryTypes = ['OpenLayers.Geometry.Point'] // This control can only be used to rotate point because the 'exteralGraphic' is a point style property

            var init_style = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style.select);
            this.rotateHandleStyle = OpenLayers.Util.extend(init_style, {
                externalGraphic: "./static/resources/images/cross.png",
                graphicWidth: 12,
                graphicHeight: 12,
                fillOpacity: 1
            });
        },

        resetVertices: function () {
            // You need to set yours renderIntent or use "vertex"
            if (this.feature && this.feature.renderIntent == "vertex") {
                var vertex = this.feature;
                this.feature = this.backup_feature;
                if (this.dragControl.feature) {
                    this.dragControl.outFeature(this.dragControl.feature);
                }
                this.layer.destroyFeatures([this.radiusHandle], {silent: true});
                delete this.radiusHandle;
                this.collectRadiusHandle();
                return;
            }
            if (this.vertices.length > 0) {
                this.layer.removeFeatures(this.vertices, {silent: true});
                this.vertices = [];
            }
            if (this.virtualVertices.length > 0) {
                this.layer.removeFeatures(this.virtualVertices, {silent: true});
                this.virtualVertices = [];
            }
            if (this.dragHandle) {
                this.layer.destroyFeatures([this.dragHandle], {silent: true});
                this.dragHandle = null;
            }
            if (this.radiusHandle) {
                this.layer.destroyFeatures([this.radiusHandle], {silent: true});
                this.radiusHandle = null;
            }
            if (this.feature && this.feature.geometry &&
                this.feature.geometry.CLASS_NAME != "OpenLayers.Geometry.Point") {
                if ((this.mode & OpenLayers.Control.ModifyFeature.DRAG)) {
                    this.collectDragHandle();
                }
                if ((this.mode & (OpenLayers.Control.ModifyFeature.ROTATE |
                    OpenLayers.Control.ModifyFeature.RESIZE))) {
                    this.collectRadiusHandle();
                }
                if (this.mode & OpenLayers.Control.ModifyFeature.RESHAPE) {
                    if (!(this.mode & OpenLayers.Control.ModifyFeature.RESIZE)) {
                        this.collectVertices();
                    }
                }
            }
            this.collectRadiusHandle();
        },

        collectRadiusHandle: function () {
            var scope = this,
                feature = this.feature,
                data = feature.attributes,
                geometry = this.feature.geometry || this.backup_feature.geometry,
                center = this.feature.geometry.bounds.getCenterLonLat();
                centroid = geometry.getCentroid().transform(this.WGS84_google_mercator, this.WGS84),
                lon = centroid.x, lat = centroid.y;

            if (data.type && Tms.settings.roadObjectTypeSettings[data.type].NoAzimuth) {
                return;
            }

            if (this.feature.geometry) {
                this.backup_feature = this.feature;
            } else {
                this.feature.geometry = this.backup_feature.geometry;
            }

            var originGeometry = new OpenLayers.Geometry.Point(lon, lat);

            var center_px = this.map.getPixelFromLonLat(center);

            // you can change this two values to get best radius geometry position.
            var pixel_dis_x = 20,
                pixel_dis_y = 20;

            var radius_px = center_px.add(pixel_dis_x, pixel_dis_y);
            var rotation_lonlat = this.map.getLonLatFromPixel(radius_px);

            var rotationFeatureGeometry = new OpenLayers.Geometry.Point(
                rotation_lonlat.lon, rotation_lonlat.lat
            );

            var rotationFeature = new OpenLayers.Feature.Vector(rotationFeatureGeometry, null, this.rotateHandleStyle);
            var resize = (this.mode & OpenLayers.Control.ModifyFeature.RESIZE);
            var reshape = (this.mode & OpenLayers.Control.ModifyFeature.RESHAPE);
            var rotate = (this.mode & OpenLayers.Control.ModifyFeature.ROTATE);

            rotationFeatureGeometry.move = function(x, y) {
                OpenLayers.Geometry.Point.prototype.move.call(this, x, y);
                var dx1 = this.x - originGeometry.x;
                var dy1 = this.y - originGeometry.y;
                var dx0 = dx1 - x;
                var dy0 = dy1 - y;
                if (rotate) {
                    var a0 = Math.atan2(dy0, dx0);
                    var a1 = Math.atan2(dy1, dx1);
                    var angle = a1 - a0;
                    angle *= 180 / Math.PI;
                    var old_angle = feature.attributes.angle;
                    var new_angle = old_angle - angle;
                    feature.attributes.angle = new_angle;
                    // redraw the feature
                    scope.feature.layer.redraw.call(scope.feature.layer);
                }
            };
            rotationFeature._sketch = true;
            this.radiusHandle = rotationFeature;
            this.radiusHandle.renderIntent = this.vertexRenderIntent;
            this.layer.addFeatures([this.radiusHandle], {silent: true});
        },

        CLASS_NAME: "OpenLayers.Control.RotateGraphicFeature"
    });