简体   繁体   English

将拖动限制在 SwiftUI 中的矩形边界

[英]Limit drag to rectangle bounds in SwiftUI

I want to be able to drag an arrow shape around on top of an image in swiftUI.我希望能够在 swiftUI 中的图像顶部拖动箭头形状。 I have tried to simplify it and limit it to a rectangle here in the beginning.我一开始就试图简化它并将其限制为一个矩形。 I have taken some inspiration from this post: Limit drag to circular bounds in SwiftUI我从这篇文章中获得了一些灵感: 在 SwiftUI 中将拖动限制为圆形边界

And this is my take on it ATM.这是我对 ATM 的看法。 I hope someone can point me in the right direction :)我希望有人能指出我正确的方向:)

So imagine that the gray rectangle is the image and the blue one is the arrow, then I only want to be able to drag the blue rectangle inside the gray rectangle.所以想象灰色矩形是图像,蓝色是箭头,那么我只想能够将蓝色矩形拖到灰色矩形内。

struct ImageView: View {
    @State private var position = CGPoint(x: 100, y: 100)
    private var rectSize: CGFloat = 600
    var body: some View {
        VStack {
            Text("Current postion = (x: \(Int(position.x)), y: \(Int(position.y))")
            
            Rectangle()
                .fill(.gray)
                .frame(width: rectSize, height: rectSize)
                .overlay(
                    Rectangle()
                        .fill(.blue)
                        .frame(width: rectSize / 4, height: rectSize / 4)
                        .position(x: position.x, y: position.y)
                        .gesture(
                            DragGesture()
                                .onChanged({ value in
                                    let currentLocation = value.location
                                    let center = CGPoint(x: self.rectSize/2, y: self.rectSize/2)
                                    
                                    let distance = center.distance(to: currentLocation)
                                    if distance > self.rectSize / 2 {
                                        let const = (self.rectSize / 2) / distance
                                        let newLocX = (currentLocation.x - center.x) * const+center.x
                                        let newLocY = (currentLocation.y - center.y) * const+center.y
                                        self.position = CGPoint(x: newLocX, y: newLocY)
                                    } else {
                                        self.position = value.location
                                    }
                                })
                                )
                )
        }
    }
}

You're almost there.您快到了。 As you're outer shape is a rect, you don't need to calculate complicated distances.由于你的外形是一个矩形,你不需要计算复杂的距离。 It's enough to check whether the position is still in the outer rect, and limit drag to its size values (0...rectSize).检查位置是否仍在外部矩形中,并将拖动限制在其大小值(0...rectSize)就足够了。 If you don't want your selection frame to move over the borders, you have to correct by 1/2 of its size (rectSize / 4 / 2)如果你不希望你的选择框移动到边界上,你必须修正它的 1/2 大小(rectSize / 4 / 2)

struct ContentView: View {
    
    @State private var position = CGPoint(x: 100, y: 100)
    private var rectSize: CGFloat = 350
    
    var body: some View {
        VStack {
            Text("Current postion = (x: \(Int(position.x)), y: \(Int(position.y))")
            
            Rectangle()
                .fill(.gray)
                .frame(width: rectSize, height: rectSize)
                .overlay(
                    Rectangle()
                        .fill(.clear)
                        .border(.blue, width: 2.0)
                        .contentShape(Rectangle())
                        .frame(width: rectSize / 4, height: rectSize / 4)
                        .position(position)
                        .gesture(
                            DragGesture()
                                .onChanged { value in
                                    // limit movement to min and max value 
                                    let limitedX = max(min(value.location.x, rectSize - rectSize / 8), rectSize / 8)
                                    let limitedY = max(min(value.location.y, rectSize - rectSize / 8), rectSize / 8)

                                    self.position = CGPoint(x: limitedX,
                                                            y: limitedY)
                                }
                        )
                )
        }
    }
}

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

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