handleScaleUpdate method
Implementation
void handleScaleUpdate(ScaleUpdateDetails details) {
if (_tapUpCounter == 1) {
_handleDoubleTapHold(details);
return;
}
final eventSource =
_dragMode ? MapEventSource.onDrag : MapEventSource.onMultiFinger;
final flags = options.interactiveFlags;
final focalOffset = details.localFocalPoint;
final currentRotation = radianToDeg(details.rotation);
if (_dragMode) {
if (InteractiveFlag.hasFlag(flags, InteractiveFlag.drag)) {
if (!_dragStarted) {
// We could emit start event at [handleScaleStart], however it is
// possible drag will be disabled during ongoing drag then
// [didUpdateWidget] will emit MapEventMoveEnd and if drag is enabled
// again then this will emit the start event again.
_dragStarted = true;
mapState.emitMapEvent(
MapEventMoveStart(
center: mapState.center,
zoom: mapState.zoom,
source: eventSource,
),
);
}
final oldCenterPt = mapState.project(mapState.center, mapState.zoom);
final localDistanceOffset =
_rotateOffset(_lastFocalLocal - focalOffset);
final newCenterPt = oldCenterPt + _offsetToPoint(localDistanceOffset);
final newCenter = mapState.unproject(newCenterPt, mapState.zoom);
mapState.move(
newCenter,
mapState.zoom,
hasGesture: true,
source: eventSource,
);
}
} else {
final hasIntPinchMove =
InteractiveFlag.hasFlag(flags, InteractiveFlag.pinchMove);
final hasIntPinchZoom =
InteractiveFlag.hasFlag(flags, InteractiveFlag.pinchZoom);
final hasIntRotate =
InteractiveFlag.hasFlag(flags, InteractiveFlag.rotate);
if (hasIntPinchMove || hasIntPinchZoom || hasIntRotate) {
final hasGestureRace = options.enableMultiFingerGestureRace;
if (hasGestureRace && _gestureWinner == MultiFingerGesture.none) {
if (hasIntPinchZoom &&
(_getZoomForScale(_mapZoomStart, details.scale) - _mapZoomStart)
.abs() >=
options.pinchZoomThreshold) {
if (options.debugMultiFingerGestureWinner) {
debugPrint('Multi Finger Gesture winner: Pinch Zoom');
}
_yieldMultiFingerGestureWinner(MultiFingerGesture.pinchZoom, true);
} else if (hasIntRotate &&
currentRotation.abs() >= options.rotationThreshold) {
if (options.debugMultiFingerGestureWinner) {
debugPrint('Multi Finger Gesture winner: Rotate');
}
_yieldMultiFingerGestureWinner(MultiFingerGesture.rotate, true);
} else if (hasIntPinchMove &&
(_focalStartLocal - focalOffset).distance >=
options.pinchMoveThreshold) {
if (options.debugMultiFingerGestureWinner) {
debugPrint('Multi Finger Gesture winner: Pinch Move');
}
_yieldMultiFingerGestureWinner(MultiFingerGesture.pinchMove, true);
}
}
if (!hasGestureRace || _gestureWinner != MultiFingerGesture.none) {
final gestures = _getMultiFingerGestureFlags();
final hasGesturePinchMove = MultiFingerGesture.hasFlag(
gestures, MultiFingerGesture.pinchMove);
final hasGesturePinchZoom = MultiFingerGesture.hasFlag(
gestures, MultiFingerGesture.pinchZoom);
final hasGestureRotate =
MultiFingerGesture.hasFlag(gestures, MultiFingerGesture.rotate);
final hasMove = hasIntPinchMove && hasGesturePinchMove;
final hasZoom = hasIntPinchZoom && hasGesturePinchZoom;
final hasRotate = hasIntRotate && hasGestureRotate;
var mapMoved = false;
var mapRotated = false;
if (hasMove || hasZoom) {
double newZoom;
// checking details.scale to prevent situation whew details comes
// with zero scale
if (hasZoom && details.scale > 0.0) {
newZoom = _getZoomForScale(
_mapZoomStart, details.scale + _scaleCorrector);
if (!_pinchZoomStarted) {
if (newZoom != _mapZoomStart) {
_pinchZoomStarted = true;
if (!_pinchMoveStarted) {
// emit MoveStart event only if pinchMove hasn't started
mapState.emitMapEvent(
MapEventMoveStart(
center: mapState.center,
zoom: mapState.zoom,
source: eventSource,
),
);
}
}
}
} else {
newZoom = mapState.zoom;
}
LatLng newCenter;
if (hasMove) {
if (!_pinchMoveStarted && _lastFocalLocal != focalOffset) {
_pinchMoveStarted = true;
if (!_pinchZoomStarted) {
// emit MoveStart event only if pinchZoom hasn't started
mapState.emitMapEvent(
MapEventMoveStart(
center: mapState.center,
zoom: mapState.zoom,
source: eventSource,
),
);
}
}
if (_pinchZoomStarted || _pinchMoveStarted) {
final oldCenterPt = mapState.project(mapState.center, newZoom);
final newFocalLatLong = _offsetToCrs(_focalStartLocal, newZoom);
final newFocalPt = mapState.project(newFocalLatLong, newZoom);
final oldFocalPt = mapState.project(_focalStartLatLng, newZoom);
final zoomDifference = oldFocalPt - newFocalPt;
final moveDifference =
_rotateOffset(_focalStartLocal - _lastFocalLocal);
final newCenterPt = oldCenterPt +
zoomDifference +
_offsetToPoint(moveDifference);
newCenter = mapState.unproject(newCenterPt, newZoom);
} else {
newCenter = mapState.center;
}
} else {
newCenter = mapState.center;
}
if (_pinchZoomStarted || _pinchMoveStarted) {
mapMoved = mapState.move(
newCenter,
newZoom,
hasGesture: true,
source: eventSource,
);
}
}
if (hasRotate) {
if (!_rotationStarted && currentRotation != 0.0) {
_rotationStarted = true;
mapState.emitMapEvent(
MapEventRotateStart(
center: mapState.center,
zoom: mapState.zoom,
source: eventSource,
),
);
}
if (_rotationStarted) {
final rotationDiff = currentRotation - _lastRotation;
final oldCenterPt = mapState.project(mapState.center);
final rotationCenter =
mapState.project(_offsetToCrs(_lastFocalLocal));
final vector = oldCenterPt - rotationCenter;
final rotatedVector = vector.rotate(degToRadian(rotationDiff));
final newCenter = rotationCenter + rotatedVector;
mapMoved = mapState.move(
mapState.unproject(newCenter), mapState.zoom,
source: eventSource) ||
mapMoved;
mapRotated = mapState.rotate(
mapState.rotation + rotationDiff,
hasGesture: true,
source: eventSource,
);
}
}
if (mapMoved || mapRotated) mapState.setState(() {});
}
}
}
_lastRotation = currentRotation;
_lastScale = details.scale;
_lastFocalLocal = focalOffset;
}