xcode 平移与视图的同步动画旋转未停留在锚点

6yoyoihd  于 2023-02-25  发布在  其他
关注(0)|答案(1)|浏览(151)

我有一个可以在屏幕上移动的灰色视图。灰色视图有一个随动画旋转的子视图(把它想象成一个时钟指针)。子视图旋转的Angular 直接与父视图用于其.offset().positiontranslation值相关。
尽管我只是尝试为子视图的.rotationEffect()设置动画,但它并没有停留在锚位置。

在下面的示例中,可以使用拖动手势或屏幕底部的按钮移动灰色视图,如果灰色视图向上移动,则子视图逆时针旋转,如果灰色视图向下移动,则子视图顺时针旋转。
如果子视图中没有.animation()属性,它将正确旋转。
问题的Here is a Xcode Playground,代码如下:

import UIKit
import SwiftUI
import PlaygroundSupport

struct Example: View {
    
    @State private var translation: CGSize = .zero
    
    var body: some View {
        ZStack {
            movingView()
                .overlay(rotatingView(), alignment: .top)
                .overlay(anchorPoint())
                .offset(translation)
                .gesture(dragGesture())
            
            controls()
        }
    }
}

private extension Example {
    
    func rotatingView() -> some View {
        Rectangle()
            .fill(Color.red)
            .frame(width: 4.0, height: 50.0)
            .rotationEffect(angle, anchor: .bottom)
            .animation(.interactiveSpring(), value: angle)
    }
    
    var angle: Angle {
        let total = translation.height
        return .degrees(total)
    }
    
}

private extension Example {
    
    func movingView() -> some View {
        Color.gray
            .frame(width: 100.0, height: 100.0)
    }
    
    func dragGesture() -> some Gesture {
        DragGesture()
            .onChanged { value in
                self.translation = value.translation
            }
            .onEnded { value in
                self.translation = .zero
            }
    }
    
}

private extension Example {
    func anchorPoint() -> some View {
        Circle()
            .fill(Color.white)
            .frame(width: 8.0, height: 8.0)
    }
}

private extension Example {
    func controls() -> some View {
        VStack {
            Spacer()
            
            HStack {
                Button("Up") {
                    withAnimation(.spring()) {
                        translation.height -= 100
                    }
                }
                
                Button("Down") {
                    withAnimation(.spring()) {
                        translation.height += 100
                    }
                }
            }
        }
    }
}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = UIHostingController(
    rootView: Example()
        .frame(width: 500.0, height: 800.0)
)
oxiaedzo

oxiaedzo1#

这可以通过在.overlay(anchorPoint())之后添加drawingGroup()修饰符来解决,例如

ZStack {
    movingView()
        .overlay(rotatingView(), alignment: .top)
        .overlay(anchorPoint())
        .drawingGroup()
        .offset(translation)
        .gesture(dragGesture())
    
    controls()
}

这会在最终显示之前将视图的内容合成到屏幕外图像中。
https://developer.apple.com/documentation/swiftui/navigationview/drawinggroup(opaque:colormode:)

相关问题