Swiftui 如何使用matchedGeometryEffect和视图缩放

Swiftui 如何使用matchedGeometryEffect和视图缩放,swiftui,Swiftui,我试图制作动画,当我点击“视图”时,它会变成全屏,当我向下拖动“视图”时,它会缩小并返回到以前的状态。我对两个视图使用matchedGeometryEffect,并使用DragGesture更改目标视图框架,转换到源视图“意外”工作。如何修复它或如何使此动画正确?如果我不更改目标图幅,它将按预期工作(单击按钮)。GIF此处: struct Test4:视图{ @名称空间变量动画 @状态私有变量显示=false @国有-私有var规模:CGFloat=1 var body:一些观点{ ZStack

我试图制作动画,当我点击“视图”时,它会变成全屏,当我向下拖动“视图”时,它会缩小并返回到以前的状态。我对两个视图使用matchedGeometryEffect,并使用DragGesture更改目标视图框架,转换到源视图“意外”工作。如何修复它或如何使此动画正确?如果我不更改目标图幅,它将按预期工作(单击按钮)。GIF此处:

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
        }
        
    }
}