Fix dragzoom with rotated view
When the view is rotated the extent of the drag box is not the same as the drag box.
This commit is contained in:
@@ -1076,7 +1076,7 @@ class View extends BaseObject {
|
|||||||
* the given size.
|
* the given size.
|
||||||
*/
|
*/
|
||||||
getResolutionForExtentInternal(extent, opt_size) {
|
getResolutionForExtentInternal(extent, opt_size) {
|
||||||
const size = opt_size || this.getViewportSize_();
|
const size = opt_size || this.getViewportSizeMinusPadding_();
|
||||||
const xResolution = getWidth(extent) / size[0];
|
const xResolution = getWidth(extent) / size[0];
|
||||||
const yResolution = getHeight(extent) / size[1];
|
const yResolution = getHeight(extent) / size[1];
|
||||||
return Math.max(xResolution, yResolution);
|
return Math.max(xResolution, yResolution);
|
||||||
@@ -1298,6 +1298,32 @@ class View extends BaseObject {
|
|||||||
this.fitInternal(geometry, opt_options);
|
this.fitInternal(geometry, opt_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate rotated extent
|
||||||
|
* @param {import("./geom/SimpleGeometry.js").default} geometry The geometry.
|
||||||
|
* @return {import("./extent").Extent} The rotated extent for the geometry.
|
||||||
|
*/
|
||||||
|
rotatedExtentForGeometry(geometry) {
|
||||||
|
const rotation = this.getRotation();
|
||||||
|
const cosAngle = Math.cos(rotation);
|
||||||
|
const sinAngle = Math.sin(-rotation);
|
||||||
|
const coords = geometry.getFlatCoordinates();
|
||||||
|
const stride = geometry.getStride();
|
||||||
|
let minRotX = +Infinity;
|
||||||
|
let minRotY = +Infinity;
|
||||||
|
let maxRotX = -Infinity;
|
||||||
|
let maxRotY = -Infinity;
|
||||||
|
for (let i = 0, ii = coords.length; i < ii; i += stride) {
|
||||||
|
const rotX = coords[i] * cosAngle - coords[i + 1] * sinAngle;
|
||||||
|
const rotY = coords[i] * sinAngle + coords[i + 1] * cosAngle;
|
||||||
|
minRotX = Math.min(minRotX, rotX);
|
||||||
|
minRotY = Math.min(minRotY, rotY);
|
||||||
|
maxRotX = Math.max(maxRotX, rotX);
|
||||||
|
maxRotY = Math.max(maxRotY, rotY);
|
||||||
|
}
|
||||||
|
return [minRotX, minRotY, maxRotX, maxRotY];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("./geom/SimpleGeometry.js").default} geometry The geometry.
|
* @param {import("./geom/SimpleGeometry.js").default} geometry The geometry.
|
||||||
* @param {FitOptions} [opt_options] Options.
|
* @param {FitOptions} [opt_options] Options.
|
||||||
@@ -1319,44 +1345,28 @@ class View extends BaseObject {
|
|||||||
} else {
|
} else {
|
||||||
minResolution = 0;
|
minResolution = 0;
|
||||||
}
|
}
|
||||||
const coords = geometry.getFlatCoordinates();
|
|
||||||
|
|
||||||
// calculate rotated extent
|
const rotatedExtent = this.rotatedExtentForGeometry(geometry);
|
||||||
const rotation = this.getRotation();
|
|
||||||
const cosAngle = Math.cos(-rotation);
|
|
||||||
let sinAngle = Math.sin(-rotation);
|
|
||||||
let minRotX = +Infinity;
|
|
||||||
let minRotY = +Infinity;
|
|
||||||
let maxRotX = -Infinity;
|
|
||||||
let maxRotY = -Infinity;
|
|
||||||
const stride = geometry.getStride();
|
|
||||||
for (let i = 0, ii = coords.length; i < ii; i += stride) {
|
|
||||||
const rotX = coords[i] * cosAngle - coords[i + 1] * sinAngle;
|
|
||||||
const rotY = coords[i] * sinAngle + coords[i + 1] * cosAngle;
|
|
||||||
minRotX = Math.min(minRotX, rotX);
|
|
||||||
minRotY = Math.min(minRotY, rotY);
|
|
||||||
maxRotX = Math.max(maxRotX, rotX);
|
|
||||||
maxRotY = Math.max(maxRotY, rotY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate resolution
|
// calculate resolution
|
||||||
let resolution = this.getResolutionForExtentInternal(
|
let resolution = this.getResolutionForExtentInternal(rotatedExtent, [
|
||||||
[minRotX, minRotY, maxRotX, maxRotY],
|
size[0] - padding[1] - padding[3],
|
||||||
[size[0] - padding[1] - padding[3], size[1] - padding[0] - padding[2]]
|
size[1] - padding[0] - padding[2],
|
||||||
);
|
]);
|
||||||
resolution = isNaN(resolution)
|
resolution = isNaN(resolution)
|
||||||
? minResolution
|
? minResolution
|
||||||
: Math.max(resolution, minResolution);
|
: Math.max(resolution, minResolution);
|
||||||
resolution = this.getConstrainedResolution(resolution, nearest ? 0 : 1);
|
resolution = this.getConstrainedResolution(resolution, nearest ? 0 : 1);
|
||||||
|
|
||||||
// calculate center
|
// calculate center
|
||||||
sinAngle = -sinAngle; // go back to original rotation
|
const rotation = this.getRotation();
|
||||||
let centerRotX = (minRotX + maxRotX) / 2;
|
const sinAngle = Math.sin(rotation);
|
||||||
let centerRotY = (minRotY + maxRotY) / 2;
|
const cosAngle = Math.cos(rotation);
|
||||||
centerRotX += ((padding[1] - padding[3]) / 2) * resolution;
|
const centerRot = getCenter(rotatedExtent);
|
||||||
centerRotY += ((padding[0] - padding[2]) / 2) * resolution;
|
centerRot[0] += ((padding[1] - padding[3]) / 2) * resolution;
|
||||||
const centerX = centerRotX * cosAngle - centerRotY * sinAngle;
|
centerRot[1] += ((padding[0] - padding[2]) / 2) * resolution;
|
||||||
const centerY = centerRotY * cosAngle + centerRotX * sinAngle;
|
const centerX = centerRot[0] * cosAngle - centerRot[1] * sinAngle;
|
||||||
|
const centerY = centerRot[1] * cosAngle + centerRot[0] * sinAngle;
|
||||||
const center = this.getConstrainedCenter([centerX, centerY], resolution);
|
const center = this.getConstrainedCenter([centerX, centerY], resolution);
|
||||||
const callback = options.callback ? options.callback : VOID;
|
const callback = options.callback ? options.callback : VOID;
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,7 @@
|
|||||||
* @module ol/interaction/DragZoom
|
* @module ol/interaction/DragZoom
|
||||||
*/
|
*/
|
||||||
import DragBox from './DragBox.js';
|
import DragBox from './DragBox.js';
|
||||||
import {
|
|
||||||
createOrUpdateFromCoordinates,
|
|
||||||
getBottomLeft,
|
|
||||||
getTopRight,
|
|
||||||
scaleFromCenter,
|
|
||||||
} from '../extent.js';
|
|
||||||
import {easeOut} from '../easing.js';
|
import {easeOut} from '../easing.js';
|
||||||
import {fromExtent as polygonFromExtent} from '../geom/Polygon.js';
|
|
||||||
import {shiftKeyOnly} from '../events/condition.js';
|
import {shiftKeyOnly} from '../events/condition.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,22 +64,17 @@ class DragZoom extends DragBox {
|
|||||||
onBoxEnd(event) {
|
onBoxEnd(event) {
|
||||||
const map = this.getMap();
|
const map = this.getMap();
|
||||||
const view = /** @type {!import("../View.js").default} */ (map.getView());
|
const view = /** @type {!import("../View.js").default} */ (map.getView());
|
||||||
let extent = this.getGeometry().getExtent();
|
let geometry = this.getGeometry();
|
||||||
|
|
||||||
if (this.out_) {
|
if (this.out_) {
|
||||||
const size = /** @type {!import("../size.js").Size} */ (map.getSize());
|
const rotatedExtent = view.rotatedExtentForGeometry(geometry);
|
||||||
const mapExtent = view.calculateExtentInternal(size);
|
const resolution = view.getResolutionForExtentInternal(rotatedExtent);
|
||||||
const boxPixelExtent = createOrUpdateFromCoordinates([
|
const factor = view.getResolution() / resolution;
|
||||||
map.getPixelFromCoordinateInternal(getBottomLeft(extent)),
|
geometry = geometry.clone();
|
||||||
map.getPixelFromCoordinateInternal(getTopRight(extent)),
|
geometry.scale(factor * factor);
|
||||||
]);
|
|
||||||
const factor = view.getResolutionForExtentInternal(boxPixelExtent, size);
|
|
||||||
|
|
||||||
scaleFromCenter(mapExtent, 1 / factor);
|
|
||||||
extent = mapExtent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view.fitInternal(polygonFromExtent(extent), {
|
view.fitInternal(geometry, {
|
||||||
duration: this.duration_,
|
duration: this.duration_,
|
||||||
easing: easeOut,
|
easing: easeOut,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user