Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ struct DuZzonKuFramePreviewView: View {
case photoLibrary
}

// 제스처 임시 값
@State private var currentScale: CGFloat = 1.0
@State private var currentRotation: Angle = .zero
@State private var currentOffset: CGSize = .zero
// 제스처 임시 값 (인덱스별로 저장)
@State private var currentScales: [Int: CGFloat] = [:]
@State private var currentRotations: [Int: Angle] = [:]
@State private var currentOffsets: [Int: CGSize] = [:]

// 크기 설정
private let targetFrameHeight: CGFloat = 376
Expand Down Expand Up @@ -84,17 +84,17 @@ struct DuZzonKuFramePreviewView: View {
// 현재 편집 중인 영역에 사진 저장
if let index = editingRectIndex {
viewModel.setPhoto(image, at: index)
// 새 사진 선택 시 해당 인덱스의 변환 초기화
viewModel.setPhotoScale(1.0, at: index)
viewModel.setPhotoRotation(.zero, at: index)
viewModel.setPhotoOffset(.zero, at: index)
currentScales[index] = 1.0
currentRotations[index] = .zero
currentOffsets[index] = .zero
} else {
viewModel.selectedPhotoImage = image
}

// 새 사진 선택 시 변환 초기화
viewModel.photoScale = 1.0
viewModel.photoRotation = .zero
viewModel.photoOffset = .zero
currentScale = 1.0
currentRotation = .zero
currentOffset = .zero
showEditButton = false
editingRectIndex = nil
}
Expand Down Expand Up @@ -130,17 +130,17 @@ struct DuZzonKuFramePreviewView: View {
// 현재 편집 중인 영역에 사진 저장
if let index = editingRectIndex {
viewModel.setPhoto(uiImage, at: index)
// 새 사진 선택 시 해당 인덱스의 변환 초기화
viewModel.setPhotoScale(1.0, at: index)
viewModel.setPhotoRotation(.zero, at: index)
viewModel.setPhotoOffset(.zero, at: index)
currentScales[index] = 1.0
currentRotations[index] = .zero
currentOffsets[index] = .zero
} else {
viewModel.selectedPhotoImage = uiImage
}

// 새 사진 선택 시 변환 초기화
viewModel.photoScale = 1.0
viewModel.photoRotation = .zero
viewModel.photoOffset = .zero
currentScale = 1.0
currentRotation = .zero
currentOffset = .zero
showEditButton = false
editingRectIndex = nil
}
Expand All @@ -152,53 +152,59 @@ struct DuZzonKuFramePreviewView: View {
}
}

private var photoGestures: some Gesture {
private func photoGestures(for index: Int) -> some Gesture {
// 확대/축소
let magnificationGesture = MagnificationGesture(minimumScaleDelta: 0.0)
.onChanged { value in
Task { @MainActor in
currentScale = value
currentScales[index] = value
}
}
.onEnded { value in
Task { @MainActor in
let newScale = viewModel.photoScale * value
viewModel.photoScale = min(max(newScale, 0.5), 3.0)
currentScale = 1.0
let currentScale = viewModel.getPhotoScale(at: index)
let newScale = currentScale * value
viewModel.setPhotoScale(min(max(newScale, 0.5), 3.0), at: index)
currentScales[index] = 1.0
}
}

// 회전
let rotationGesture = RotationGesture(minimumAngleDelta: .zero)
.onChanged { value in
Task { @MainActor in
currentRotation = value
currentRotations[index] = value
}
}
.onEnded { value in
Task { @MainActor in
viewModel.photoRotation += value
currentRotation = .zero
let currentRotation = viewModel.getPhotoRotation(at: index)
viewModel.setPhotoRotation(currentRotation + value, at: index)
currentRotations[index] = .zero
}
}

// 이동
let dragGesture = DragGesture(minimumDistance: 10)
.onChanged { value in
Task { @MainActor in
currentOffset = CGSize(
currentOffsets[index] = CGSize(
width: value.translation.width,
height: value.translation.height
)
}
}
.onEnded { value in
Task { @MainActor in
viewModel.photoOffset = CGSize(
width: viewModel.photoOffset.width + value.translation.width,
height: viewModel.photoOffset.height + value.translation.height
let currentOffset = viewModel.getPhotoOffset(at: index)
viewModel.setPhotoOffset(
CGSize(
width: currentOffset.width + value.translation.width,
height: currentOffset.height + value.translation.height
),
at: index
)
currentOffset = .zero
currentOffsets[index] = .zero
}
}

Expand All @@ -207,19 +213,26 @@ struct DuZzonKuFramePreviewView: View {
.simultaneously(with: dragGesture)
}

private var finalScale: CGFloat {
let calculatedScale = viewModel.photoScale * currentScale
// 특정 인덱스의 최종 변환 값 계산
private func finalScale(for index: Int) -> CGFloat {
let baseScale = viewModel.getPhotoScale(at: index)
let currentScale = currentScales[index] ?? 1.0
let calculatedScale = baseScale * currentScale
return min(max(calculatedScale, 0.5), 3.0)
}

private var finalRotation: Angle {
viewModel.photoRotation + currentRotation
private func finalRotation(for index: Int) -> Angle {
let baseRotation = viewModel.getPhotoRotation(at: index)
let currentRotation = currentRotations[index] ?? .zero
return baseRotation + currentRotation
}

private var finalOffset: CGSize {
CGSize(
width: viewModel.photoOffset.width + currentOffset.width,
height: viewModel.photoOffset.height + currentOffset.height
private func finalOffset(for index: Int) -> CGSize {
let baseOffset = viewModel.getPhotoOffset(at: index)
let currentOffset = currentOffsets[index] ?? .zero
return CGSize(
width: baseOffset.width + currentOffset.width,
height: baseOffset.height + currentOffset.height
)
}

Expand Down Expand Up @@ -265,6 +278,7 @@ struct DuZzonKuFramePreviewView: View {
.onDisappear {
isFrameLoaded = false
}
.offset(x: 2)
.onAppear {
print("checkerBoardRects:", frame.checkerBoardRects ?? [])
}
Expand Down Expand Up @@ -311,9 +325,9 @@ struct DuZzonKuFramePreviewView: View {
.resizable()
.scaledToFill()
.frame(width: photoWidth, height: photoHeight)
.scaleEffect(finalScale)
.rotationEffect(finalRotation)
.offset(finalOffset)
.scaleEffect(finalScale(for: index))
.rotationEffect(finalRotation(for: index))
.offset(finalOffset(for: index))
.clipShape(clipShape)

// 수정 버튼 표시 시 딤 처리
Expand All @@ -324,7 +338,7 @@ struct DuZzonKuFramePreviewView: View {
.frame(width: photoWidth, height: photoHeight)
.clipShape(clipShape)
.contentShape(clipShape)
.gesture(photoGestures)
.gesture(photoGestures(for: index))
.onTapGesture {
withAnimation(.easeInOut(duration: 0.2)) {
if editingRectIndex == index {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ extension DuZzonKuVM {
let renderer = UIGraphicsImageRenderer(size: targetFrameSize)

let composedImage = renderer.image { context in
// 전체 context를 x축으로 2포인트 이동
context.cgContext.translateBy(x: 2, y: 0)

// 1. 각 체커보드 영역에 체커보드 + 사진 그리기
for (index, rect) in checkerBoardRects.enumerated() {
Expand All @@ -79,7 +81,11 @@ extension DuZzonKuVM {
// 1-2. 해당 인덱스의 사진 그리기
if let photo = getPhoto(at: index) {
context.cgContext.saveGState()
context.cgContext.addRect(photoRect)

// cornerRadius 적용하여 클리핑
let cornerRadius = rect.cornerRadius ?? 0
let path = UIBezierPath(roundedRect: photoRect, cornerRadius: cornerRadius)
context.cgContext.addPath(path.cgPath)
context.cgContext.clip()

// 사진을 영역에 맞게 scaledToFill로 그리기
Expand Down Expand Up @@ -107,9 +113,11 @@ extension DuZzonKuVM {
)
}

// 사진 변환 적용 (확대/축소, 회전, 이동)
// 현재는 모든 사진에 동일한 변환 적용
// 필요시 인덱스별로 다른 변환 저장 가능
// 해당 인덱스의 변환 적용
let photoScale = getPhotoScale(at: index)
let photoRotation = getPhotoRotation(at: index)
let photoOffset = getPhotoOffset(at: index)

let centerX = drawRect.midX
let centerY = drawRect.midY

Expand All @@ -127,10 +135,10 @@ extension DuZzonKuVM {
photo.draw(in: centeredRect)
context.cgContext.restoreGState()
}

// 2. 프레임 이미지
originalFrameImage.draw(in: CGRect(origin: .zero, size: targetFrameSize))
}

// 2. 프레임 이미지
originalFrameImage.draw(in: CGRect(origin: .zero, size: targetFrameSize))
}

bodyImage = composedImage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,36 @@ class DuZzonKuVM: KeyringViewModelProtocol {
var selectedPhotoImage: UIImage? = nil
var photoImages: [Int: UIImage] = [:] // 인덱스별 사진 저장

// MARK: - Photo Transform State
var photoScale: CGFloat = 1.0
var photoRotation: Angle = .zero
var photoOffset: CGSize = .zero
// MARK: - Photo Transform State (인덱스별)
var photoScales: [Int: CGFloat] = [:]
var photoRotations: [Int: Angle] = [:]
var photoOffsets: [Int: CGSize] = [:]

// 특정 인덱스의 변환 값 가져오기 (기본값 반환)
func getPhotoScale(at index: Int) -> CGFloat {
return photoScales[index] ?? 1.0
}

func getPhotoRotation(at index: Int) -> Angle {
return photoRotations[index] ?? .zero
}

func getPhotoOffset(at index: Int) -> CGSize {
return photoOffsets[index] ?? .zero
}

// 특정 인덱스의 변환 값 설정
func setPhotoScale(_ scale: CGFloat, at index: Int) {
photoScales[index] = scale
}

func setPhotoRotation(_ rotation: Angle, at index: Int) {
photoRotations[index] = rotation
}

func setPhotoOffset(_ offset: CGSize, at index: Int) {
photoOffsets[index] = offset
}

// MARK: - Body Image
var bodyImage: UIImage? = nil
Expand Down Expand Up @@ -91,6 +117,11 @@ class DuZzonKuVM: KeyringViewModelProtocol {
/// 특정 인덱스의 사진 제거
func removePhoto(at index: Int) {
photoImages.removeValue(forKey: index)
// 변환 값도 제거
photoScales.removeValue(forKey: index)
photoRotations.removeValue(forKey: index)
photoOffsets.removeValue(forKey: index)

if index == 0 {
selectedPhotoImage = nil
}
Expand Down Expand Up @@ -163,9 +194,9 @@ class DuZzonKuVM: KeyringViewModelProtocol {
selectedFrame = nil
selectedPhotoImage = nil
photoImages.removeAll()
photoScale = 1.0
photoRotation = .zero
photoOffset = .zero
photoScales.removeAll()
photoRotations.removeAll()
photoOffsets.removeAll()
bodyImage = nil
availableFrames.removeAll()
isComposingPhoto = false
Expand Down