mirror of
https://github.com/FoggedLens/iD.git
synced 2026-04-05 11:32:23 +02:00
Merge branch 'zoom_pan'
This commit is contained in:
@@ -81,6 +81,7 @@ export function rendererMap(context) {
|
||||
var dimensions = [1, 1];
|
||||
var _dblClickEnabled = true;
|
||||
var _redrawEnabled = true;
|
||||
var _gestureTransformStart;
|
||||
var _transformStart = projection.transform();
|
||||
var _transformLast;
|
||||
var _transformed = false;
|
||||
@@ -178,36 +179,12 @@ export function rendererMap(context) {
|
||||
.selectAll('.surface')
|
||||
.attr('id', 'surface');
|
||||
|
||||
|
||||
var prevScale;
|
||||
|
||||
surface
|
||||
.call(drawLabels.observe)
|
||||
.on('gesturestart.surface', function() {
|
||||
prevScale = d3_event.scale;
|
||||
})
|
||||
.on('gesturechange.surface', function() {
|
||||
// Remap Safari gesture events to wheel events - #5492
|
||||
// We want these disabled most places, but enabled for zoom/unzoom on map surface
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/GestureEvent
|
||||
var e = d3_event;
|
||||
e.preventDefault();
|
||||
|
||||
var deltaY = (e.scale > prevScale) ? -15 : 20;
|
||||
prevScale = e.scale;
|
||||
|
||||
var props = {
|
||||
deltaY: deltaY ,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
screenX: e.screenX,
|
||||
screenY: e.screenY,
|
||||
x: e.x,
|
||||
y: e.y
|
||||
};
|
||||
var e2 = new WheelEvent('wheel', props);
|
||||
_selection.node().dispatchEvent(e2);
|
||||
_gestureTransformStart = projection.transform();
|
||||
})
|
||||
.on('gesturechange.surface', gestureChange)
|
||||
.on('mousedown.zoom', function() {
|
||||
if (d3_event.button === 2) {
|
||||
d3_event.stopPropagation();
|
||||
@@ -392,40 +369,127 @@ export function rendererMap(context) {
|
||||
}
|
||||
|
||||
|
||||
function gestureChange() {
|
||||
// Remap Safari gesture events to wheel events - #5492
|
||||
// We want these disabled most places, but enabled for zoom/unzoom on map surface
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/GestureEvent
|
||||
var e = d3_event;
|
||||
e.preventDefault();
|
||||
|
||||
var props = {
|
||||
deltaMode: 0, // dummy values to ignore in zoomPan
|
||||
deltaY: 1, // dummy values to ignore in zoomPan
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
screenX: e.screenX,
|
||||
screenY: e.screenY,
|
||||
x: e.x,
|
||||
y: e.y
|
||||
};
|
||||
|
||||
var e2 = new WheelEvent('wheel', props);
|
||||
e2._scale = e.scale; // preserve the original scale
|
||||
e2._rotation = e.rotation; // preserve the original rotation
|
||||
|
||||
_selection.node().dispatchEvent(e2);
|
||||
}
|
||||
|
||||
|
||||
function zoomPan(manualEvent) {
|
||||
var event = (manualEvent || d3_event);
|
||||
var source = event.sourceEvent;
|
||||
var eventTransform = event.transform;
|
||||
var x = eventTransform.x;
|
||||
var y = eventTransform.y;
|
||||
var k = eventTransform.k;
|
||||
|
||||
if (_transformStart.x === eventTransform.x &&
|
||||
_transformStart.y === eventTransform.y &&
|
||||
_transformStart.k === eventTransform.k) {
|
||||
if (_transformStart.x === x &&
|
||||
_transformStart.y === y &&
|
||||
_transformStart.k === k) {
|
||||
return; // no change
|
||||
}
|
||||
|
||||
// Normalize mousewheel - #3029
|
||||
// If wheel delta is provided in LINE units, recalculate it in PIXEL units
|
||||
// We are essentially redoing the calculations that occur here:
|
||||
// https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203
|
||||
// See this for more info:
|
||||
// https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js
|
||||
if (source && source.type === 'wheel' && source.deltaMode === 1 /* LINE */) {
|
||||
// pick sensible scroll amount if user scrolling fast or slow..
|
||||
var lines = Math.abs(source.deltaY);
|
||||
var scroll = lines > 2 ? 40 : lines * 10;
|
||||
// Special handling of 'wheel' events:
|
||||
// They might be triggered by the user scrolling the mouse wheel,
|
||||
// or 2-finger pinch/zoom gestures, the transform may need adjustment.
|
||||
if (source && source.type === 'wheel') {
|
||||
var dX = source.deltaX;
|
||||
var dY = source.deltaY;
|
||||
var x2 = x;
|
||||
var y2 = y;
|
||||
var k2 = k;
|
||||
var t0, p0, p1;
|
||||
|
||||
var t0 = _transformed ? _transformLast : _transformStart;
|
||||
var p0 = mouse(source);
|
||||
var p1 = t0.invert(p0);
|
||||
var k2 = t0.k * Math.pow(2, -source.deltaY * scroll / 500);
|
||||
var x2 = p0[0] - p1[0] * k2;
|
||||
var y2 = p0[1] - p1[1] * k2;
|
||||
// Normalize mousewheel scroll speed (Firefox) - #3029
|
||||
// If wheel delta is provided in LINE units, recalculate it in PIXEL units
|
||||
// We are essentially redoing the calculations that occur here:
|
||||
// https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203
|
||||
// See this for more info:
|
||||
// https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js
|
||||
if (source.deltaMode === 1 /* LINE */) {
|
||||
// Convert from lines to pixels, more if the user is scrolling fast.
|
||||
// (I made up the exp function to roughly match Firefox to what Chrome does)
|
||||
var lines = clamp(Math.abs(source.deltaY), 0, 12);
|
||||
var sign = (source.deltaY > 0) ? 1 : -1;
|
||||
dY = sign * Math.exp((lines - 1) * 0.5) * 4.000244140625;
|
||||
|
||||
// recalculate x2,y2,k2
|
||||
t0 = _transformed ? _transformLast : _transformStart;
|
||||
p0 = mouse(source);
|
||||
p1 = t0.invert(p0);
|
||||
k2 = t0.k * Math.pow(2, -dY / 500);
|
||||
x2 = p0[0] - p1[0] * k2;
|
||||
y2 = p0[1] - p1[1] * k2;
|
||||
|
||||
// 2 finger map pinch zooming (Safari) - #5492
|
||||
// These are fake `wheel` events we made from Safari `gesturechange` events..
|
||||
} else if (source._scale) {
|
||||
// recalculate x2,y2,k2
|
||||
t0 = _gestureTransformStart;
|
||||
p0 = mouse(source);
|
||||
p1 = t0.invert(p0);
|
||||
k2 = t0.k * source._scale;
|
||||
x2 = p0[0] - p1[0] * k2;
|
||||
y2 = p0[1] - p1[1] * k2;
|
||||
|
||||
// 2 finger map panning (all browsers) - #5492
|
||||
// Panning via the `wheel` event will always have:
|
||||
// - `ctrlKey = false`
|
||||
// - `deltaX`,`deltaY` are round integer pixels
|
||||
} else if (!source.ctrlKey && isInteger(dX) && isInteger(dY)) {
|
||||
p1 = projection.translate();
|
||||
x2 = p1[0] - dX;
|
||||
y2 = p1[1] - dY;
|
||||
k2 = projection.scale();
|
||||
|
||||
// 2 finger map pinch zooming (all browsers except Safari) - #5492
|
||||
// Pinch zooming via the `wheel` event will always have:
|
||||
// - `ctrlKey = true`
|
||||
// - `deltaY` is not round integer pixels (ignore `deltaX`)
|
||||
} else if (source.ctrlKey && !isInteger(dY)) {
|
||||
dY *= 6; // slightly scale up whatever the browser gave us
|
||||
|
||||
// recalculate x2,y2,k2
|
||||
t0 = _transformed ? _transformLast : _transformStart;
|
||||
p0 = mouse(source);
|
||||
p1 = t0.invert(p0);
|
||||
k2 = t0.k * Math.pow(2, -dY / 500);
|
||||
x2 = p0[0] - p1[0] * k2;
|
||||
y2 = p0[1] - p1[1] * k2;
|
||||
}
|
||||
|
||||
// something changed - replace the event transform
|
||||
if (x2 !== x || y2 !== y || k2 !== k) {
|
||||
x = x2;
|
||||
y = y2;
|
||||
k = k2;
|
||||
eventTransform = d3_zoomIdentity.translate(x2, y2).scale(k2);
|
||||
_selection.node().__zoom = eventTransform;
|
||||
}
|
||||
|
||||
eventTransform = d3_zoomIdentity.translate(x2,y2).scale(k2);
|
||||
_selection.node().__zoom = eventTransform;
|
||||
}
|
||||
|
||||
if (geoScaleToZoom(eventTransform.k, TILESIZE) < minzoom) {
|
||||
if (geoScaleToZoom(k, TILESIZE) < minzoom) {
|
||||
surface.interrupt();
|
||||
uiFlash().text(t('cannot_zoom'))();
|
||||
setZoom(context.minEditableZoom(), true);
|
||||
@@ -436,15 +500,15 @@ export function rendererMap(context) {
|
||||
|
||||
projection.transform(eventTransform);
|
||||
|
||||
var scale = eventTransform.k / _transformStart.k;
|
||||
var tX = (eventTransform.x / scale - _transformStart.x) * scale;
|
||||
var tY = (eventTransform.y / scale - _transformStart.y) * scale;
|
||||
var scale = k / _transformStart.k;
|
||||
var tX = (x / scale - _transformStart.x) * scale;
|
||||
var tY = (y / scale - _transformStart.y) * scale;
|
||||
|
||||
if (context.inIntro()) {
|
||||
curtainProjection.transform({
|
||||
x: eventTransform.x - tX,
|
||||
y: eventTransform.y - tY,
|
||||
k: eventTransform.k
|
||||
x: x - tX,
|
||||
y: y - tY,
|
||||
k: k
|
||||
});
|
||||
}
|
||||
|
||||
@@ -455,6 +519,15 @@ export function rendererMap(context) {
|
||||
scheduleRedraw();
|
||||
|
||||
dispatch.call('move', this, map);
|
||||
|
||||
|
||||
function clamp(num, min, max) {
|
||||
return Math.max(min, Math.min(num, max));
|
||||
}
|
||||
|
||||
function isInteger(val) {
|
||||
return typeof val === 'number' && isFinite(val) && Math.floor(val) === val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user