Swiftui 如何使用matchedGeometryEffect和视图缩放
我试图制作动画,当我点击“视图”时,它会变成全屏,当我向下拖动“视图”时,它会缩小并返回到以前的状态。我对两个视图使用matchedGeometryEffect,并使用DragGesture更改目标视图框架,转换到源视图“意外”工作。如何修复它或如何使此动画正确?如果我不更改目标图幅,它将按预期工作(单击按钮)。GIF此处:Swiftui 如何使用matchedGeometryEffect和视图缩放,swiftui,Swiftui,我试图制作动画,当我点击“视图”时,它会变成全屏,当我向下拖动“视图”时,它会缩小并返回到以前的状态。我对两个视图使用matchedGeometryEffect,并使用DragGesture更改目标视图框架,转换到源视图“意外”工作。如何修复它或如何使此动画正确?如果我不更改目标图幅,它将按预期工作(单击按钮)。GIF此处: struct Test4:视图{ @名称空间变量动画 @状态私有变量显示=false @国有-私有var规模:CGFloat=1 var body:一些观点{ ZStack
struct Test4:视图{
@名称空间变量动画
@状态私有变量显示=false
@国有-私有var规模:CGFloat=1
var body:一些观点{
ZStack(对齐:.topTrailing){
如果显示{
滚动视图{
颜色:灰色
.边框(颜色.黑色,宽度:30)
.matchedGeometryEffect(id:“动画”,在:动画中)
.框架(
宽度:UIScreen.main.bounds.width*比例,
高度:UIScreen.main.bounds.height*比例)
.手势(
牵引力(最小距离:0)
.onChanged(onChanged)
.onEnded(onEnded)
)
}
.ignoresSafeArea()
按钮(“返回”){
带动画(Animation.easeInOut(持续时间:1)){
self.show.toggle()
}
}
}否则{
VStack{
颜色:灰色
.边框(颜色.黑色,宽度:30)
.matchedGeometryEffect(id:“动画”,在:动画中)
.框架(宽:200,高:200)
.ontapsigne{
动画片{
self.scale=1
show.toggle()
}
}
}
}
}
}
更改函数(值:DragGesture.value){
带动画(动画.easeInOut(持续时间:3)){
让currentScale=value.translation.height/UIScreen.main.bounds.height
如果当前刻度为0.85{
self.scale=newScale
}否则,如果newScale<0.85{
self.show=false
}
}
}
函数已合并(值:DragGesture.value){
带动画(动画.easeInOut(持续时间:3)){
如果自评量表<0.85{
self.show=false
}
}
}
}
结构测试4_预览:PreviewProvider{
静态var预览:一些视图{
Test4()
}
}
如果没有匹配的几何效果,您尝试获取的东西是可能的,下面是一个简单的方法:
struct Test4: View {
@Namespace var animation
@State private var show = false
@State private var scale: CGFloat = 1
var body: some View {
ZStack(alignment: .topTrailing) {
if show {
ScrollView {
Color.gray
.border(Color.black, width: 30)
.matchedGeometryEffect(id: "animation", in: animation)
.frame(
width: UIScreen.main.bounds.width * scale,
height: UIScreen.main.bounds.height * scale)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged(onChanged)
.onEnded(onEnded)
)
}
.ignoresSafeArea()
Button("go back") {
withAnimation(Animation.easeInOut(duration: 1)) {
self.show.toggle()
}
}
} else {
VStack {
Color.gray
.border(Color.black, width: 30)
.matchedGeometryEffect(id: "animation", in: animation)
.frame(width: 200, height: 200)
.onTapGesture {
withAnimation {
self.scale = 1
show.toggle()
}
}
}
}
}
}
func onChanged(value: DragGesture.Value) {
withAnimation(Animation.easeInOut(duration: 3)) {
let currentScale = value.translation.height / UIScreen.main.bounds.height
if currentScale <= 0 {
return
}
let newScale = 1 - currentScale
if newScale > 0.85 {
self.scale = newScale
} else if newScale < 0.85 {
self.show = false
}
}
}
func onEnded(value: DragGesture.Value) {
withAnimation(Animation.easeInOut(duration: 3)) {
if self.scale < 0.85 {
self.show = false
}
}
}
}
struct Test4_Previews: PreviewProvider {
static var previews: some View {
Test4()
}
}
import SwiftUI
struct ContentView: View {
var body: some View {
ScaleView()
}
}
struct ScaleView: View {
@State private var translation: CGFloat = CGFloat()
@State private var lastTranslation: CGFloat = CGFloat()
var body: some View {
GeometryReader { geometry in
Color.black
ZStack {
Color
.gray
Image(systemName: "arrow.triangle.2.circlepath.circle")
.font(Font.largeTitle)
.onTapGesture {
if lastTranslation == 400.0 {
lastTranslation = 0.0
translation = lastTranslation
}
else {
lastTranslation = 400.0
translation = lastTranslation
}
}
}
.position(x: geometry.size.width/2, y: geometry.size.height/2)
.cornerRadius(30)
.scaleEffect(1.0 - translation/(geometry.size.width > geometry.size.height ? geometry.size.width : geometry.size.height))
.gesture(DragGesture(minimumDistance: 0.0).onChanged(onChanged).onEnded(onEnded))
}
.ignoresSafeArea()
.animation(.easeInOut(duration: 0.35))
.statusBar(hidden: true)
}
func onChanged(value: DragGesture.Value) { translation = lastTranslation + value.translation.height }
func onEnded(value: DragGesture.Value) {
if value.translation.height > 0.0 {
lastTranslation = 400.0
translation = lastTranslation
}
else {
lastTranslation = 0.0
translation = lastTranslation
}
}
}