0

I'm trying to create a mobile experience for editing images, imagine a photoshop for mobile, one of the features is zoom & pan, which works except for one thing.

I'm trying to prevent the user from scrolling the image outside the screen boundaries, if he does I simply want to animate the stage back into position

this is the function I use to detect if the image is getting cropped on a border

function getImageBordersCropping(stage, image) {
  const stageScale = stage.scale()
  const stagePosition = stage.position()

  const imgSize = image.size()

  const stageWidth = stage.width()
  const stageHeight = stage.height()

  const imgTopLeft = {
    x: stagePosition.x,
    y: stagePosition.y,
  }

  const imgBottomRight = {
    x: imgTopLeft.x + imgSize.width * stageScale.x,
    y: imgTopLeft.y + imgSize.height * stageScale.y,
  }

  // Create an object for the borders
  let borders = {
    top: false,
    right: false,
    bottom: false,
    left: false,
  }

  // Check each border
  if (imgTopLeft.x < 0) borders.left = true // Image extends beyond the left border of the stage
  if (imgTopLeft.y < 0) borders.top = true // Image extends beyond the top border of the stage
  if (imgBottomRight.x > stageWidth) borders.right = true // Image extends beyond the right border of the stage
  if (imgBottomRight.y > stageHeight) borders.bottom = true // Image extends beyond the bottom border of the stage

  return borders
}

my pan & zoom feature is totally based of: https://konvajs.org/docs/sandbox/Multi-touch_Scale_Stage.html

my dragEnd:

  const onDragEnd = e => {
    const stage = e.target.getStage()!
    const { left, top, bottom, right } = getImageBordersCropping(
      stage,
      stage.findOne('.imageElement')!
    )

    let newX = stage.x()
    let newY = stage.y()

    if (right) newX = stage.width() - window.innerWidth
    else if (left) newX = 0

    if (top) newY = 0
    else if (bottom) {
      newY = stage.height() - canvasDimensions.height / ratio
    }

    if (top || right || bottom || left) {
      // Animate the stage back to the center within the defined scope
      const tween = new Konva.Tween({
        node: stage!,
        duration: 1, // Animation duration in seconds
        easing: Konva.Easings.EaseInOut,
        x: newX,
        y: newY,
        onFinish: function () {
          // isAnimating = false // Reset the animation flag
        },
      })

      // isAnimating = true; // Set the animation flag
      tween.play()
    }
  }

so far everything is working as expected before zooming in, but when i zoom in things start to break, panning always to the side even though I'm within the boundaries

Doctor Strange
  • 189
  • 1
  • 3
  • 12

0 Answers0