简体   繁体   English

如何围绕其中心旋转 SwiftUI 路径?

[英]How to rotate SwiftUI Path around its center?

I have the following simple SwiftUI Path of an arrow which I wish to rotate around it's center:我有以下简单的 SwiftUI 我希望围绕它的中心旋转的箭头Path

@State var heading: Double = 0.0
@State var xOffset = 0.0
@State var yOffset = 0.0
var body: some View {
    TabView {
        NavigationStack {
            Path { path in
                path.move(to: CGPoint(x: xOffset, y: yOffset))
                path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset + 20))
                path.addLine(to: CGPoint(x: xOffset + 50, y: yOffset + 0))
                path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset - 20))
                path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset + 0))
            }
            .stroke(lineWidth: 3)
            .foregroundColor(.red)
            .rotationEffect(Angle(degrees: heading), anchor: .center)
            .transformEffect(CGAffineTransform(translationX: 80, y: 80))

            Slider(value: $heading, in: 0...360, step: 30)
        }
    }
}

在 0º

It does however not rotate around its center:然而,它不会围绕其中心旋转:

在 30º

How can I rotate a Path around its center (or around any other relative point on its bounds)?如何围绕其中心(或围绕其边界上的任何其他相对点)旋转Path

The Path view greedily takes up all of the space available to it, so the view is much larger than you think, and its center is far away. Path视图贪婪地占用了它所有可用的空间,因此视图比你想象的要大得多,而且它的中心也很远。 So when you rotate the path, it moves off the screen.因此,当您旋转路径时,它会移出屏幕。 You can see this by adding .background(Color.yellow) to the Path view.您可以通过将.background(Color.yellow)添加到Path视图来看到这一点。

It's easier to manage the rotation of the arrow if you make it an .overlay of another View ( Color.clear ) and then rotate that View .如果将箭头.overlay为另一个View ( Color.clear ) 的 .overlay ,然后旋转该View ,则管理箭头的旋转会更容易。 You can make the view visible by using Color.yellow while tuning, and then position the arrow relative to its parent view.您可以在调整时使用Color.yellow使视图可见,然后 position 相对于其父视图的箭头。 The nice thing about this is that when you rotate the parent view, the arrow will stick to it and rotate predictably.这样做的好处是,当您旋转父视图时,箭头会粘在它上面并可以预测地旋转。

struct ContentView: View {
    @State var heading: Double = 0.0
    @State var xOffset = 0.0
    @State var yOffset = 0.0
    var body: some View {
        TabView {
            NavigationStack {
                Color.clear
                    .frame(width: 60, height: 60)
                    .overlay (
                        Path { path in
                            path.move(to: CGPoint(x: xOffset, y: yOffset))
                            path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset + 20))
                            path.addLine(to: CGPoint(x: xOffset + 50, y: yOffset + 0))
                            path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset - 20))
                            path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset + 0))
                        }
                        .stroke(lineWidth: 3)
                        .foregroundColor(.red)
                        .transformEffect(CGAffineTransform(translationX: 5, y: 30))
                    )
                    .rotationEffect(Angle(degrees: heading), anchor: .center)
                
                Slider(value: $heading, in: 0...360, step: 30)
            }
        }
    }
}

在模拟器中旋转的箭头


How do I make my code work?如何使我的代码工作?

You need to give your Path view a reasonable sized frame .你需要给你的Path视图一个合理大小的frame Since you have defined xOffset and yOffset , use them to move the path drawing within its view.由于您已定义xOffsetyOffset ,请使用它们在其视图中移动路径图。

This has the same effect as the overlay method presented above:这与上面介绍的覆盖方法具有相同的效果:

struct ContentView: View {
    @State var heading: Double = 0.0
    @State var xOffset = 5.0   // here
    @State var yOffset = 30.0  // here

    var body: some View {
        TabView {
            NavigationStack {
                Path { path in
                    path.move(to: CGPoint(x: xOffset, y: yOffset))
                    path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset + 20))
                    path.addLine(to: CGPoint(x: xOffset + 50, y: yOffset + 0))
                    path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset - 20))
                    path.addLine(to: CGPoint(x: xOffset + 0, y: yOffset + 0))
                }
                .stroke(lineWidth: 3)
                .foregroundColor(.red)
                // .background(Color.yellow)
                .frame(width: 60, height: 60)  // here
                .rotationEffect(Angle(degrees: heading), anchor: .center)
                //.transformEffect(CGAffineTransform(translationX: 80, y: 80))

                Slider(value: $heading, in: 0...360, step: 30)
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM