본문 바로가기

Project/PhotoDiary

✅ A 이미지 위에 B 이미지를 올리고, 이동 범위를 이미 A 이미지 사이즈내로 하는 방법

@objc func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
    guard let targetView = gesture.view,
          let containerView = targetView.superview else { return }

    switch gesture.state {
    case .began:
        initialCenter = targetView.center

    case .changed:
        let translation = gesture.translation(in: containerView)
        var newCenter = CGPoint(
            x: initialCenter.x + translation.x,
            y: initialCenter.y + translation.y
        )

        // ❗️ 제한 조건: containerView 내부로만 이동
        let halfWidth = targetView.bounds.width / 2
        let halfHeight = targetView.bounds.height / 2

        let minX = halfWidth
        let maxX = containerView.bounds.width - halfWidth
        let minY = halfHeight
        let maxY = containerView.bounds.height - halfHeight

        newCenter.x = min(max(newCenter.x, minX), maxX)
        newCenter.y = min(max(newCenter.y, minY), maxY)

        targetView.center = newCenter

    default:
        break
    }
}

 

🧠 함수 흐름 설명

🟢 guard let targetView = gesture.view, ...

  • 이 제스처가 어떤 뷰(예: UIImageView, UILabel)에 붙어 있는지 확인
  • 만약 대상 뷰가 없거나, 상위 뷰가 없다면 함수 종료

👉 gesture.view = 이동 중인 스티커
👉 superview = 이동 범위를 제한할 부모 뷰 (mainImageView가 되겠지)

 

🟢 gesture.state == .began

initialCenter = targetView.center

 

  • 사용자가 드래그를 시작했을 때, 현재 위치를 저장
  • 이후 .changed 상태에서 얼마나 움직였는지 계산할 기준이 됨

 

🟢 gesture.state == .changed

let translation = gesture.translation(in: containerView)

 

 

  • 손가락이 얼마나 움직였는지 (translation)를 얻음
  • 이건 containerView 기준이야 (즉, mainImageView 좌표계 기준)

 

var newCenter = CGPoint(
    x: initialCenter.x + translation.x,
    y: initialCenter.y + translation.y
)

 

  • 이전 위치(initialCenter)에서 손가락이 움직인 거리만큼 더해서 새로운 center 계산

 

🔒 "📏 이동 제한" 부분

let halfWidth = targetView.bounds.width / 2
let halfHeight = targetView.bounds.height / 2
  • center가 기준이므로, 뷰의 절반 크기만큼은 양쪽 여백으로 확보해야 함
    → 그래야 뷰 전체가 containerView 안에 있도록 만들 수 있어

 

let minX = halfWidth
let maxX = containerView.bounds.width - halfWidth
let minY = halfHeight
let maxY = containerView.bounds.height - halfHeight

 

  • center.x의 최소값은 왼쪽 끝에서 halfWidth만큼 떨어진 곳
  • center.x의 최대값은 오른쪽 끝에서 halfWidth만큼 떨어진 곳
  • 마찬가지로 Y도 위아래 같은 원리
newCenter.x = min(max(newCenter.x, minX), maxX)
newCenter.y = min(max(newCenter.y, minY), maxY)

 

  • center.x가 minX보다 작으면 → minX로 고정
  • center.x가 maxX보다 크면 → maxX로 고정

👉 이렇게 하면 오버레이 뷰 전체가 containerView 바깥으로 못 나감
(뷰의 중앙 기준으로 바깥 경계를 계산하니까 정확함)

 

✅ 이렇게 되면

  • 사용자가 스티커를 드래그하더라도
  • mainImageView 안에서만 움직일 수 있음
  • 화면 밖으로 나가는 일이 절대 없음!