onScaleUpdate method

  1. @protected
void onScaleUpdate(
  1. ScaleUpdateDetails details, {
  2. bool inner = false,
})

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,
      );
  }
}