ZStacked 视图和旋转的 SwiftUI 帧大小

SwiftUI Frame Sizes For ZStacked Views, and Rotation

我正在尝试安排一组小指针来突出显示图像上感兴趣的区域。我的方法是将图像和指针 ZStack 放在顶部,一开始效果很好。但是,我想旋转指针图形以避免模糊图像的某些区域,这就是我遇到的问题,我似乎无法解决。

请注意,在下面的第一张图片中,绘制的指针使其指向框架的中心,因此我可以轻松地从父视图定位它们。框架表示为黑色矩形。但是,即使指定了小帧尺寸,旋转似乎也适用于 ZStack space 的整个几何形状,而不仅仅是提供给指针的帧尺寸。您可以在第二张图片中看到,两个项目都相对于较大视图尺寸的中心旋转,而不是提供的框架尺寸。这最终改变了指向的位置,这不是我所期望的,因为指针在小框架矩形的边界内正确呈现。指针视图似乎完全了解这些限制。

有没有一种方法可以强制旋转操作相对于为指针提供的 .frame 的中心发生?还是我注定要根据几何 reader 写出一些复杂的三角函数?感谢您的帮助!

图 1 是未旋转的指针。图 2 是应用旋转后的结果。

struct ContentView: View {
    let origin: CGPoint = CGPoint(x: 100, y: 100)
    
    var body: some View {
        ZStack {
            Rectangle() //draw the frame the arrow is rendered within
                .frame(width: 50, height: 18, alignment: .center)
                .position(x: origin.x, y: origin.y)
                .border(.brown, width: 5)
                //.rotationEffect(Angle(degrees: 45))
                
            Circle() //Just to show the target of the arrow in the frame
                .foregroundColor(.white)
                .frame(width: 3, height: 3, alignment: .center)
                .position(x: origin.x, y: origin.y)
                //.rotationEffect(Angle(degrees: 45))
            
            Pointer()
                .foregroundColor(.red)
                .frame(width: 50, height: 18, alignment: .center)
                .position(x: origin.x, y: origin.y)
                .border(.green, width: 3)
                //.rotationEffect(Angle(degrees: 45))
        }
        .frame(width: 250, height: 450, alignment: .center)
    }
}
struct Pointer: Shape {
    func path(in rect: CGRect) -> Path {
        let X = rect.width
        let Y = rect.height
        < ... Path instructions to render the arrow ... > 
        return path
    }
}

单个元素上的 .border 导致了问题,因为它采用了外框的大小。跳过它,你就没事了。我觉得你也不需要第一个Rectangle,把它注释掉,结果是一样的。

    var body: some View {
        ZStack {
            // you dont really need this Rect ...
            Rectangle() //draw the frame the arrow is rendered within
                .frame(width: 50, height: 18, alignment: .center)
                .rotationEffect(Angle(degrees: 45)) // here
               .position(x: origin.x, y: origin.y)
                
            Circle() //Just to show the target of the arrow in the frame
                .foregroundColor(.white)
                .frame(width: 3, height: 3, alignment: .center)
                .position(x: origin.x, y: origin.y)
            
            Image(systemName: "arrow.right")
                .resizable()
                .foregroundColor(.red)
                .frame(width: 25, height: 18)
                .frame(width: 50, alignment: .leading)
                .rotationEffect(Angle(degrees: 45)) // here
                .position(x: origin.x, y: origin.y)
        }
        .frame(width: 250, height: 450, alignment: .center)
        .border(.brown, width: 5)
    }