Проблема:
Когда заметка нота поворачивается, перетаскивание ее вдоль «вертикальных» или «горизонтальных» осей приводит к перемещению вдоль исходных неповернутых осей. Например, если заметку повернуть на 90 градусов, при перетаскивании вверх она сдвинется вбок.
Что я пробовал:
- Я использовал RotateEffect для обработки вращения.
- Я настраиваю перевод, чтобы учесть вращение с помощью тригонометрии, но перетаскивание по-прежнему работает неправильно. .
ZStack {
stickyNote.color
.frame(width: stickyNote.size.width, height: stickyNote.size.height)
.cornerRadius(10)
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(isSelected ? Color.blue : Color.clear, lineWidth: 3)
)
.rotationEffect(rotation, anchor: .center)
.offset(x: position.width, y: position.height)
.gesture(
TransformHelper.dragGesture(
position: $position,
lastPosition: $lastPosition,
rotation: rotation,
isResizing: isResizing,
isDragging: $isDragging
)
)
.gesture(
TransformHelper.rotationGesture(
rotation: $rotation,
lastRotation: $lastRotation
)
)
}
А вот код движения и вращения:
static func adjustTranslationForRotation(_ translation: CGSize, rotation: Angle) -> CGSize {
let radians = rotation.radians
let cosTheta = CGFloat(cos(radians))
let sinTheta = CGFloat(sin(radians))
// Adjust the translation to account for rotation
let adjustedX = translation.width * cosTheta - translation.height * sinTheta
let adjustedY = translation.width * sinTheta + translation.height * cosTheta
return CGSize(width: adjustedX, height: adjustedY)
}
static func dragGesture(
position: Binding,
lastPosition: Binding,
rotation: Angle,
isResizing: Bool,
isDragging: Binding
) -> some Gesture {
return DragGesture()
.onChanged { value in
if !isResizing {
let adjustedTranslation = adjustTranslationForRotation(value.translation, rotation: rotation)
position.wrappedValue = CGSize(
width: lastPosition.wrappedValue.width + adjustedTranslation.width,
height: lastPosition.wrappedValue.height + adjustedTranslation.height
)
isDragging.wrappedValue = true
}
}
.onEnded { _ in
if isDragging.wrappedValue {
isDragging.wrappedValue = false
lastPosition.wrappedValue = position.wrappedValue
}
}
}
Кто-нибудь сталкивался с подобной проблемой, когда направление перетаскивания было неправильным после применения поворота? Будем очень признательны за любые советы о том, как заставить заметку правильно двигаться в зависимости от ее текущей ориентации!
Заранее спасибо!
Редактировать: здесь является минимальным репродуктивным примером
import SwiftUI
struct StickyNoteView: View {
@State private var position: CGSize = .zero
@State private var lastPosition: CGSize = .zero
@State private var rotation: Angle = .zero
@State private var lastRotation: Angle = .zero
@State private var isDragging: Bool = false
var body: some View {
ZStack {
Rectangle()
.fill(Color.yellow)
.frame(width: 200, height: 200)
.rotationEffect(rotation)
.offset(x: position.width, y: position.height)
.gesture(
TransformHelper.dragGesture(
position: $position,
lastPosition: $lastPosition,
rotation: rotation,
isResizing: false,
isDragging: $isDragging
)
)
.gesture(
TransformHelper.rotationGesture(
rotation: $rotation,
lastRotation: $lastRotation
)
)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.gray.opacity(0.3))
.edgesIgnoringSafeArea(.all)
}
}
import SwiftUI
struct TransformHelper {
// Adjust the translation to account for the center of the StickyNote
static func adjustTranslationForRotation(_ translation: CGSize, rotation: Angle) -> CGSize {
let radians = rotation.radians
let cosTheta = CGFloat(cos(radians))
let sinTheta = CGFloat(sin(radians))
// Transformation der Translation in das rotierte Koordinatensystem
let adjustedX = translation.width * cosTheta - translation.height * sinTheta
let adjustedY = translation.width * sinTheta + translation.height * cosTheta
return CGSize(width: adjustedX, height: adjustedY)
}
// Drag Gesture Handler
static func dragGesture(
position: Binding,
lastPosition: Binding,
rotation: Angle,
isResizing: Bool,
isDragging: Binding
) -> some Gesture {
return DragGesture()
.onChanged { value in
if !isResizing {
let adjustedTranslation = adjustTranslationForRotation(value.translation, rotation: rotation)
position.wrappedValue = CGSize(
width: lastPosition.wrappedValue.width + adjustedTranslation.width,
height: lastPosition.wrappedValue.height + adjustedTranslation.height
)
isDragging.wrappedValue = true
}
}
.onEnded { _ in
if isDragging.wrappedValue {
isDragging.wrappedValue = false
lastPosition.wrappedValue = position.wrappedValue
}
}
}
// Rotation Gesture Handler
static func rotationGesture(
rotation: Binding,
lastRotation: Binding
) -> some Gesture {
return RotationGesture()
.onChanged { angle in
rotation.wrappedValue = lastRotation.wrappedValue + angle
}
.onEnded { angle in
lastRotation.wrappedValue += angle
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/791 ... r-rotation