Ol-ext:旋转更改图像大小

of1yzvn4  于 2022-09-26  发布在  其他
关注(0)|答案(1)|浏览(353)

我使用ol.interaction.Transform在选择Map上的一个图像后旋转它。最终目标是能够缩放、拉伸、旋转和平移(拖放)图像。
我的问题是:
1.当我旋转图像时,它不会保持纵横比(图像的大小会发生变化,并且会进一步拉伸)

1.当图像被选中时,沿图像周长出现的红色虚线并不跟随旋转运动,例如,这是我开始旋转之前的样子:

这是我旋转时的样子:

我确实想这样(黑色虚线):

我怎样才能修好它?
这是我的代码:

var styleCache = {};

            function getStyle(img, scaleX, scaleY) {

                var view = map.getView();
                var resolutionAtEquator = view.getResolution();
                var y = Math.round(img.height * scaleY);
                var x = Math.round(img.width * scaleX);
                var key = img.src + ',' + x + ',' + y;
                var style = styleCache[key];

                if (!style) {
                    var canvas = document.createElement('canvas');
                    canvas.width = x;
                    canvas.height = y;
                    var ctx = canvas.getContext("2d");
                    ctx.drawImage(img, 0, 0, x, y);
                    var resizeImageUrl = canvas.toDataURL();
                    canvas.remove();
                    var keys = Object.keys(styleCache);
                    if (keys.length >= 100) {
                        // delete an old entry to limit the cache size
                        delete styleCache[keys[0]];
                    }
                    var style = new ol.style.Style({
                        image: new ol.style.Icon({
                           src: resizeImageUrl,
                           opacity: imageOpacity,
                        })
                    });
                    styleCache[key] = style;
                }
                return style;
            }

            styles = [
              new ol.style.Style({
                fill: new ol.style.Fill({
                  color: transparent
                })
              }),
              new ol.style.Style({
                stroke: new ol.style.Stroke({
                  color: transparent,
                  width: width + 2
                })
              }),
              new ol.style.Style({
                stroke: new ol.style.Stroke({
                  color: transparent,
                  width: width
                })
              }),
              new ol.style.Style({
                image: new ol.style.Circle({
                  radius: width * 2,
                  fill: new ol.style.Fill({
                    color: blue
                  }),
                  stroke: new ol.style.Stroke({
                    color: transparent,
                    width: width / 2
                  })
                }),
                zIndex: Infinity
              })
            ];

            var florplanStyle = new ol.style.Style({
                image: new ol.style.Icon({
                   src: img.src,
                   opacity: imageOpacity,
                })
            });

            styleFunction = function(feature, resolution) {

               var rayDrawValueX = img.width/2;
               var resAdjustX = rayDrawValueX * resolution;

               var rayDrawValueY = img.height/2;
               var resAdjustY = rayDrawValueY * resolution;

               var rotation = feature.get('rotation');

               if (rotation !== undefined) {
                    var extent = feature.getGeometry().getExtent();
                    var coordinates = feature.getGeometry().getCoordinates()[0];

                    var getBottomLeft = ol.extent.getBottomLeft(extent);
                    var getBottomRight = ol.extent.getBottomRight(extent);
                    var getTopLeft = ol.extent.getTopLeft(extent);
                    var getTopRight = ol.extent.getTopRight(extent);
                    var center = ol.extent.getCenter(extent);

                    var dx = center[0] - getBottomLeft[0];
                    var dy = 0;
                    var scaleX = Math.sqrt(dx * dx + dy * dy)/resAdjustX;

                    var dx = 0;
                    var dy = getTopRight[1] - center[1];

                    var scaleY = Math.sqrt(dx * dx + dy * dy)/resAdjustY;

                    var florplanStyle2 = getStyle(img, scaleX, scaleY);
                    florplanStyle2.setGeometry(new ol.geom.Point(center));
                    florplanStyle2.getImage().setRotation(rotation);
                    return debug ? styles.concat([florplanStyle2]) : florplanStyle2;

                } else if (feature.getGeometry().getCenter) {
                    //scrolling map case
                    florplanStyle.setGeometry(new ol.geom.Point(feature.getGeometry().getCenter()));
                    // get rotation from drawn feature or geometry
                    florplanStyle.getImage().setRotation(feature.getGeometry().get('rotation'));
                    florplanStyle.getImage().setScale(feature.getGeometry().getRadius()/resAdjustX);
                    return florplanStyle;
                } else {
                   return styles;
                }
            };

            if ( this.nord && this.sud && this.est && this.ovest && this.floorplanImage && this.opacity) {

                 var extent = ol.proj.transformExtent([this.ovest, this.sud, this.est, this.nord], 'EPSG:4326', 'EPSG:3857');
                 var center = ol.extent.getCenter(extent);
                 var size = ol.extent.getSize(extent);
                 var view = map.getView();
                 var resolutionAtEquator = view.getResolution();
                 var width = ol.extent.getWidth(extent);
                 var height = ol.extent.getHeight(extent);
                 var radius = width/2;
                 var rotation = 0;
                 var circle = circle || new ol.geom.Circle(center, radius);
                 var circleFeature = new ol.Feature(circle);
                 circleFeature.set('rotation', rotation);
                 var geom = ol.geom.Polygon.fromExtent(extent);
                 circleFeature.setGeometry(geom);
                 this.features.push(circleFeature);
                 this.mapView.fit(geom, {minResolution: 0.05});
            } else {
                this.controller.fireEvent('mapstaterequest');
            }

            var raster = new ol.layer.Tile({
                source: new ol.source.OSM()
            });

            var source = new ol.source.Vector({
                wrapX: false,
                features: this.features
            });

            var vector = new ol.layer.Vector({
                source: source,
                style: styleFunction
            });
            vector.setMap(map);

            var draw = new ol.interaction.Draw({
                source: source,
                type: 'Circle',
                geometryFunction: function(coordinates, geometry) {
                    var center = coordinates[0];
                    var last = coordinates[1];
                    var dx = center[0] - last[0];
                    var dy = center[1] - last[1];
                    var radius = dx;
                    var rotation = Math.PI - Math.atan2(dy, dx);
                    geometry = geometry || new ol.geom.Circle(center, radius);
                    geometry.setCenterAndRadius(center, radius);
                    geometry.set('rotation', rotation);
                    return geometry;
                },
                style: styleFunction,
                handler: 'onSaveClick'
            });

            draw.on('drawstart', function () {
                source.clear();
            });

            draw.on('drawend', function (evt) {
                // move rotation from geometry to drawn feature
                var rotation = evt.feature.getGeometry().get('rotation');
                evt.feature.set('rotation', rotation);

                var extent = evt.feature.getGeometry().getExtent();
                var geom = ol.geom.Polygon.fromExtent(extent);

                if(img.width!==img.height){
                    scaleY = img.height/img.width
                    geom.scale(1,scaleY);
                }
                evt.feature.setGeometry(geom);
            });

            this.map.addInteraction(draw);

            var isCorner = true; // use opposite corner to scale/stretch, (false = use center);

            var transform = new ol.interaction.Transform({
                features: this.features,
                translateFeature: false,
                // flip wouldn't be compatible with rotation
                noFlip: true,
                rotate: true,
                modifyCenter: function(){ return isCorner; }
            });

            var startangle = 0;

            transform.on('select', function(e) {
                draw.setActive(e.features.length == 0 );
            });

           transform.on('rotatestart', function(e) {
                startangle = e.feature.get('rotation') || 0;
            });

            transform.on('rotating', function (e) {
                // Set angle attribute to be used on style !
                e.feature.set('rotation', startangle - e.angle);
            });

            this.map.addInteraction(transform);

这是代码的一部分,我觉得自己做错了什么,但我不明白是什么:

if (rotation !== undefined) {
                    var extent = feature.getGeometry().getExtent();
                    var coordinates = feature.getGeometry().getCoordinates()[0];

                    var getBottomLeft = ol.extent.getBottomLeft(extent);
                    var getBottomRight = ol.extent.getBottomRight(extent);
                    var getTopLeft = ol.extent.getTopLeft(extent);
                    var getTopRight = ol.extent.getTopRight(extent);
                    var center = ol.extent.getCenter(extent);

                    var dx = center[0] - getBottomLeft[0];
                    var dy = 0;
                    var scaleX = Math.sqrt(dx * dx + dy * dy)/resAdjustX;

                    var dx = 0;
                    var dy = getTopRight[1] - center[1];

                    var scaleY = Math.sqrt(dx * dx + dy * dy)/resAdjustY;

                    var florplanStyle2 = getStyle(img, scaleX, scaleY);
                    florplanStyle2.setGeometry(new ol.geom.Point(center));
                    florplanStyle2.getImage().setRotation(rotation);
                    return debug ? styles.concat([florplanStyle2]) : florplanStyle2;

                }
swvgeqrz

swvgeqrz1#

我找到了解决我两个问题的方法。关于我在问题底部提到的代码部分,我觉得是对的。我用错误的方法计算scaleX和scaleY。
这是解决我第一个问题的正确代码
当我旋转图像时,它不会保持纵横比

if (rotation !== undefined) {
    //style during rotation
    var extent = feature.getGeometry().getExtent();
    var coordinates = feature.getGeometry().getCoordinates()[0];

    var getTopLeft = coordinates[0];
    var getBottomLeft = coordinates[1];
    var getBottomRight = coordinates[2];
    var getTopRight = coordinates[3];

    var center = ol.extent.getCenter(extent);

    var top = new ol.geom.LineString([getTopLeft, getTopRight]).getClosestPoint(center);
    var left = new ol.geom.LineString([getTopLeft, getBottomLeft]).getClosestPoint(center);

    var dx = center[0] - left[0];
    var dy = center[1] - left[1];
    var scaleX = Math.sqrt(dx * dx + dy * dy) / resAdjustX;

    var dx = top[0] - center[0];
    var dy = top[1] - center[1];
    var scaleY = Math.sqrt(dx * dx + dy * dy) / resAdjustY;

    var floorplanStyle2 = getStyle(img, scaleX, scaleY);
    floorplanStyle2.setGeometry(new ol.geom.Point(center));
    floorplanStyle2.getImage().setRotation(rotation);
    return debug ? styles.concat([floorplanStyle2]) : floorplanStyle2;

}

关于我的第二个问题
当选定图像时,沿图像周长出现的红色虚线不跟随旋转的移动
为了拥有此功能,我必须将keepRectangle: true添加到我的ol.interaction中。变换变量。这个功能最初在我的应用程序上不起作用,因为我使用的是ol-extv3.1.2,所以我必须先将其更改为ol-ext v3.2.24才能使用它。
这是我的完整代码:

var iconURL = '/media/floorplans/' + uploadedImage;
var transparent = [255, 255, 255, 0];
var blue = [0, 153, 255, 1];
var width = 3;

img.crossOrigin = 'anonymous';
img.src = iconURL;
this.features = new ol.Collection();

var styleCache = {};

function getStyle(img, scaleX, scaleY) {

    var view = map.getView();
    var resolutionAtEquator = view.getResolution();
    var y = Math.round(img.height * scaleY);
    var x = Math.round(img.width * scaleX);
    var key = img.src + ',' + x + ',' + y;
    var style = styleCache[key];

    if (!style) {
        var canvas = document.createElement('canvas');
        canvas.width = x;
        canvas.height = y;
        var ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0, x, y);
        var resizeImageUrl = canvas.toDataURL();
        canvas.remove();
        var keys = Object.keys(styleCache);
        if (keys.length >= 100) {
            // delete an old entry to limit the cache size
            delete styleCache[keys[0]];
        }
        var style = new ol.style.Style({
            image: new ol.style.Icon({
                src: resizeImageUrl,
                opacity: imageOpacity,
            })
        });
        styleCache[key] = style;
    }
    return style;
}

// Patch because ol-ext is changing extent of circle during rotation
ol.geom.Circle.prototype.rotate = function(angle, anchor) {
    var point = new ol.geom.Point(this.getCenter());
    point.rotate(angle, anchor);
    this.setCenter(point.getCoordinates());
};

styles = [
    new ol.style.Style({
        stroke: new ol.style.Stroke({
            color: transparent,
            width: width
        })
    }),
    //pointer used to draw the image
    new ol.style.Style({
        image: new ol.style.Circle({
            radius: width * 2,
            fill: new ol.style.Fill({
                color: blue
            }),
        }),
        zIndex: Infinity
    })
];

var floorplanStyle = new ol.style.Style({
    image: new ol.style.Icon({
        src: img.src,
        opacity: imageOpacity,
    })
});

styleFunction = function(feature, resolution) {

    var rayDrawValueX = img.width / 2;
    var resAdjustX = rayDrawValueX * resolution;

    var rayDrawValueY = img.height / 2;
    var resAdjustY = rayDrawValueY * resolution;

    var rotation = feature.get('rotation');

    if (rotation !== undefined) {
        //style during rotation
        var extent = feature.getGeometry().getExtent();
        var coordinates = feature.getGeometry().getCoordinates()[0];

        var getTopLeft = coordinates[0];
        var getBottomLeft = coordinates[1];
        var getBottomRight = coordinates[2];
        var getTopRight = coordinates[3];

        var center = ol.extent.getCenter(extent);

        var top = new ol.geom.LineString([getTopLeft, getTopRight]).getClosestPoint(center);
        var left = new ol.geom.LineString([getTopLeft, getBottomLeft]).getClosestPoint(center);

        var dx = center[0] - left[0];
        var dy = center[1] - left[1];
        var scaleX = Math.sqrt(dx * dx + dy * dy) / resAdjustX;

        var dx = top[0] - center[0];
        var dy = top[1] - center[1];
        var scaleY = Math.sqrt(dx * dx + dy * dy) / resAdjustY;

        var floorplanStyle2 = getStyle(img, scaleX, scaleY);
        floorplanStyle2.setGeometry(new ol.geom.Point(center));
        floorplanStyle2.getImage().setRotation(rotation);
        return debug ? styles.concat([floorplanStyle2]) : floorplanStyle2;

    } else if (feature.getGeometry().getCenter) {
        //style meanwhile drawing
        floorplanStyle.setGeometry(new ol.geom.Point(feature.getGeometry().getCenter()));
        // get rotation from drawn feature or geometry
        floorplanStyle.getImage().setRotation(feature.getGeometry().get('rotation'));
        floorplanStyle.getImage().setScale(feature.getGeometry().getRadius() / resAdjustX);
        return floorplanStyle;
    } else {
        return styles;
    }
};

if (this.nord && this.sud && this.est && this.ovest && this.floorplanImage && this.opacity) {
    //floorplan when floorplan position map is opened
    var extent = ol.proj.transformExtent([this.ovest, this.sud, this.est, this.nord], 'EPSG:4326', 'EPSG:3857');

    var center = ol.extent.getCenter(extent);
    var size = ol.extent.getSize(extent);
    var view = map.getView();
    var resolutionAtEquator = view.getResolution();
    var width = ol.extent.getWidth(extent);
    var height = ol.extent.getHeight(extent);
    var radius = width / 2;
    var rotation = this.rotation;
    var rotationInRadian = rotation * Math.PI / 180;

    var circle = circle || new ol.geom.Circle(center, radius);
    var circleFeature = new ol.Feature(circle);

    circleFeature.set('rotation', rotationInRadian);
    var geom = ol.geom.Polygon.fromExtent(extent);
    geom.rotate(-rotationInRadian, ol.extent.getCenter(geom.getExtent()));
    circleFeature.setGeometry(geom);
    this.features.push(circleFeature);
    this.mapView.fit(geom, {
        minResolution: 0.05
    });
} else {
    this.controller.fireEvent('mapstaterequest');
}

var raster = new ol.layer.Tile({
    source: new ol.source.OSM()
});

var source = new ol.source.Vector({
    features: this.features
});

var vector = new ol.layer.Vector({
    source: source,
    style: styleFunction,
    updateWhileAnimating: true,
});
vector.setMap(map);

var draw = new ol.interaction.Draw({
    source: source,
    type: 'Circle',
    geometryFunction: function(coordinates, geometry) {
        var center = coordinates[0];
        var last = coordinates[1];
        var dx = center[0] - last[0];
        var dy = center[1] - last[1];
        var radius = dx;
        var rotation = Math.PI - Math.atan2(dy, dx);
        geometry = geometry || new ol.geom.Circle(center, radius);
        geometry.setCenterAndRadius(center, radius);
        geometry.set('rotation', rotation);
        return geometry;
    },
    style: styleFunction,
});

draw.on('drawstart', function() {
    source.clear();
});

draw.on('drawend', function(evt) {
    var rotation = evt.feature.getGeometry().get('rotation');
    evt.feature.set('rotation', rotation);

    var extent = evt.feature.getGeometry().getExtent();
    var geom = ol.geom.Polygon.fromExtent(extent);

    if (img.width !== img.height) {
        scaleY = img.height / img.width;
        geom.scale(1, scaleY);
    }
    geom.rotate(-rotation, ol.extent.getCenter(geom.getExtent()));
    evt.feature.setGeometry(geom);
});

this.map.addInteraction(draw);

var isCorner = true; // use opposite corner to scale/stretch, (false = use center);

var transform = new ol.interaction.Transform({
    features: this.features,
    keepRectangle: true,
    // flip wouldn't be compatible with rotation
    noFlip: true,
    translateFeature: false,
    rotate: true,
    handler: 'onSaveClick',
    modifyCenter: function() {
        return isCorner;
    }
});

var startangle;

transform.on('select', function(e) {
    if (e.feature != undefined) {
        draw.setActive(e.feature.length == 0);
    } else {
        draw.setActive(true);
    }
});

transform.on(['rotatestart', 'scalestart'], function(e) {
    startangle = e.feature.get('rotation') || 0;
});

transform.on('rotating', function(e) {
    // Set angle attribute to be used on style !
    e.feature.set('rotation', startangle - e.angle);
});

this.map.addInteraction(transform);

相关问题