Я пытаюсь анимировать пользовательскую форму в SwiftUI, полученную из данных в массиве объектов. Я создал этот образец, чтобы проиллюстрировать проблему, с которой я сталкиваюсь, пытаясь заставить это работать.
В этом простом примере. После перетаскивания красной точки она смещает свои X и Y с помощью весенней анимации. Однако форма привязывается к новому положению вместо плавной анимации с точкой.
Я пробовал несколько версий на animatableData
, но все еще не смог заставить анимацию работать. Надеюсь, что кто-то, кто разбирается в этом, может помочь! Спасибо.
final class Item: Identifiable {
let id: String
var position: CGPoint
let radius: CGFloat = 10
var offset: CGSize {
CGSize(width: position.x-radius, height: position.y-radius)
}
init(id: String, position: CGPoint) {
self.id = id
self.position = position
}
}
final class Manager: ObservableObject {
var items = [
Item(id: "Item 1", position: .init(x: 50, y: 200)),
Item(id: "Item 2", position: .init(x: 200, y: 200)),
Item(id: "Item 3", position: .init(x: 200, y: 50))
]
}
struct CustomShape: Shape {
@ObservedObject var manager: Manager
var animatableData: [Item] {
get { manager.items }
set { manager.items = newValue }
}
func path(in rect: CGRect) -> Path {
Path { path in
for i in 0..<animatableData.count {
let item = animatableData[i]
if i == 0 {
path.move(to: item.position)
} else {
path.addLine(to: item.position)
}
}
}
}
}
struct ContentView: View {
@ObservedObject var manager = Manager()
var body: some View {
ZStack(alignment: .topLeading) {
CustomShape(manager: manager)
ForEach(manager.items) { item in
Circle().foregroundColor(.red)
.frame(width: item.radius*2, height: item.radius*2)
.offset(item.offset)
.gesture(
DragGesture()
.onChanged { gesture in
manager.objectWillChange.send()
item.position = gesture.location
}
.onEnded { gesture in
withAnimation(.spring()) {
manager.objectWillChange.send()
item.position = CGPoint(
x: item.position.x + 20,
y: item.position.y + 20
)
}
}
)
}
}
}
}