onScaleUpdate method
Handle an update to an ongoing gesture. All of pan, scale, and rotate are handled with GestureDetector's scale gesture.
Implementation
@protected
void onScaleUpdate(ScaleUpdateDetails details, {bool inner = false}) {
final double scale = transformationController!.value.getScaleOnZAxis();
scaleAnimationFocalPoint = details.localFocalPoint;
final Offset focalPointScene = transformationController!.toScene(
details.localFocalPoint,
);
if (gestureType == GestureType.pan) {
// When a gesture first starts, it sometimes has no change in scale and
// rotation despite being a two-finger gesture. Here the gesture is
// allowed to be reinterpreted as its correct type after originally
// being marked as a pan.
gestureType = getGestureType(details);
} else {
gestureType ??= getGestureType(details);
}
if (!gestureIsSupported(gestureType, outer: inner)) {
return;
}
switch (gestureType!) {
case GestureType.scale:
if (scaleStart == null) {
return;
}
scrollbarController?.onScrollStart();
// details.scale gives us the amount to change the scale as of the
// start of this gesture, so calculate the amount to scale as of the
// previous call to _onScaleUpdate.
final double desiredScale = scaleStart! * details.scale;
final double scaleChange = desiredScale / scale;
transformationController!.value = matrixScale(
transformationController!.value,
scaleChange,
);
// While scaling, translate such that the user's two fingers stay on
// the same places in the scene. That means that the focal point of
// the scale should be on the same place in the scene before and after
// the scale.
// BUT when the user zooms out of his controllable area, the focal
// point should always be in the middle of the screen so that the
// child stays centered.
final Offset focalPointSceneScaled = transformationController!.toScene(
details.localFocalPoint,
);
transformationController!.value = matrixTranslate(
transformationController!.value,
focalPointSceneScaled - referenceFocalPoint!,
);
// details.localFocalPoint should now be at the same location as the
// original _referenceFocalPoint point. If it's not, that's because
// the translate came in contact with a boundary. In that case, update
// _referenceFocalPoint so subsequent updates happen in relation to
// the new effective focal point.
final Offset focalPointSceneCheck = transformationController!.toScene(
details.localFocalPoint,
);
if (round(referenceFocalPoint!) != round(focalPointSceneCheck)) {
referenceFocalPoint = focalPointSceneCheck;
}
afterZoom();
case GestureType.rotate:
if (details.rotation == 0.0) {
return;
}
scrollbarController?.onScrollStart();
final double desiredRotation = rotationStart! + details.rotation;
transformationController!.value = matrixRotate(
transformationController!.value,
currentRotation - desiredRotation,
details.localFocalPoint,
);
currentRotation = desiredRotation;
case GestureType.pan:
if (referenceFocalPoint == null) {
return;
}
currentAxis ??= getPanAxis(referenceFocalPoint!, focalPointScene);
if (widget.panAxis == PanAxis.horizontal) {
scrollbarController?.onScrollStartHorizontal();
} else if (widget.panAxis == PanAxis.vertical) {
scrollbarController?.onScrollStartVertical();
} else if (widget.panAxis == PanAxis.free) {
scrollbarController?.onScrollStart();
} else if (widget.panAxis == PanAxis.aligned) {
if (currentAxis == Axis.horizontal) {
scrollbarController?.onScrollStartHorizontal();
} else {
scrollbarController?.onScrollStartVertical();
}
}
// details may have a change in scale here when scaleEnabled is false.
// In an effort to keep the behavior similar whether or not scaleEnabled
// is true, these gestures are thrown away.
if (details.scale != 1.0) {
return;
}
// Translate so that the same point in the scene is underneath the
// focal point before and after the movement.
final Offset translationChange = focalPointScene - referenceFocalPoint!;
transformationController!.value = matrixTranslate(
transformationController!.value,
translationChange,
);
referenceFocalPoint = transformationController!.toScene(
details.localFocalPoint,
);
}
}