Закрыть жест с эффектом масштаба
Когда я добавляю жест перетаскивания, чтобы отклонить мой «большой вид», он масштабируется до размера жеста, но если он отклоняется, вид переходит к своему исходному масштабу и анимирует вид до «маленького вида».
Вот мой пример кода:`struct TestView: View {@State var showBigView = false
@Namespace private var animationNameSpace
@State var gestureOffset: CGSize = .zero
var body: some View {
ZStack {
if !showBigView {
Image(systemName: "tshirt")
.resizable()
.scaledToFit()
.foregroundColor(.red)
.matchedGeometryEffect(id: "circel", in: animationNameSpace)
.transition(.scale(scale: 1))
.frame(width: 100, height: 100)
.onTapGesture {
withAnimation {
showBigView = true
}
}
} else {
Image(systemName: "tshirt")
.resizable()
.scaledToFit()
.foregroundColor(.red)
.matchedGeometryEffect(id: "circel", in: animationNameSpace)
.transition(.scale(scale: 1))
.frame(width: 300, height: 300)
.scaleEffect(abs(gestureOffset.height / 1000 - 1))
.gesture(DragGesture().onChanged {
guard $0.translation.height > 0 else { return }
self.gestureOffset = $0.translation
if abs($0.translation.height) > 150 {
withAnimation {
showBigView = false
gestureOffset = .zero
}
}
})
}
}
}
} `
Он не должен прыгать, когда представление закрывается с определенным масштабным эффектом.
1 ответ
Я считаю, что вы пытаетесь:
- Покажите изображение футболки в кадре 100 на 100.
- При нажатии он увеличивается до 300 на 300 кадров с анимацией.
- Перетаскивание вниз уменьшает изображение. Когда высота перетаскивания превышает 150 точек, изображение сжимается до исходного размера 100 на 100 кадров с анимацией.
Этот подход работает:
struct TestView: View {
@State private var isBig = false
@State private var frame = TestView.smallFrame
@State private var scale = 1.0
static private let smallFrame = 100.0
static private let bigFrame = 300.0
var body: some View {
Image(systemName: "tshirt")
.resizable()
.scaledToFit()
.frame(width: frame, height: frame)
.scaleEffect(scale)
.foregroundColor(.red)
.onTapGesture {
if !isBig {
withAnimation {
frame = TestView.bigFrame
}
isBig = true
}
}
.gesture(DragGesture().onChanged {
let dragHeight = $0.translation.height
if isBig && dragHeight > 0 {
if dragHeight >= 150 {
frame = TestView.bigFrame * scale
scale = 1
withAnimation {
frame = TestView.smallFrame
}
isBig = false
} else {
scale = 1 - (dragHeight / 1000)
}
}
}.onEnded { _ in
withAnimation {
scale = 1
}
})
}
}
Нет необходимости создавать два отдельных образа и синхронизировать их сmatchedGeometryEffect
. Вместо этого вы можете использовать свой@State
boolean, чтобы контролировать, имеют ли жесты какой-либо эффект.