resolveConstraints(duration, resolutionDirection, anchor) {
    duration = duration !== undefined ? duration : 200;
    const direction = resolutionDirection || 0;

    const newRotation = this.constraints_.rotation(this.targetRotation_);
    const size = this.getViewportSize_(newRotation);
    const newResolution = this.constraints_.resolution(
      this.targetResolution_,
      direction,
      size,
    );
    const newCenter = this.constraints_.center(
      this.targetCenter_,
      newResolution,
      size,
      false,
      this.calculateCenterShift(
        this.targetCenter_,
        newResolution,
        newRotation,
        size,
      ),
    );

    if (duration === 0 && !this.cancelAnchor_) {
      this.targetResolution_ = newResolution;
      this.targetRotation_ = newRotation;
      this.targetCenter_ = newCenter;
      this.applyTargetState_();
      return;
    }

    anchor = anchor || (duration === 0 ? this.cancelAnchor_ : undefined);
    this.cancelAnchor_ = undefined;

    if (
      this.getResolution() !== newResolution ||
      this.getRotation() !== newRotation ||
      !this.getCenterInternal() ||
      !equals(this.getCenterInternal(), newCenter)
    ) {
      if (this.getAnimating()) {
        this.cancelAnimations();
      }

      this.animateInternal({
        rotation: newRotation,
        center: newCenter,
        resolution: newResolution,
        duration: duration,
        easing: easeOut,
        anchor: anchor,
      });
    }
  }
If any constraints need to be applied, an animation will be triggered.
This is typically done on interaction end.
Note: calling this with a duration of 0 will apply the constrained values straight away,
without animation.
@param {number} [duration] The animation duration in ms.
@param {number} [resolutionDirection] Which direction to zoom.
@param {import("./coordinate.js").Coordinate} [anchor] The origin of the transformation.