简体   繁体   English

SwiftUI:如何根据已拖动的距离改变拖动速度?

[英]SwiftUI: How to change the speed of drag based on distance already dragged?

For example: I have a joystick that can be moved around freely, how can I make the dragging slower with distance?例如:我有一个可以自由移动的操纵杆,我怎样才能让拖动随着距离变慢? The further I drag the joystick, the slower the drag is.我拖动操纵杆越远,拖动速度越慢。 Thanks in advance.提前致谢。

My Joystick code, dragging works but has no bounds and isn't slowed down if you drag it to the edges:我的操纵杆代码,拖动有效但没有界限,如果将它拖动到边缘也不会减慢速度:

import SwiftUI

struct ContentView: View {

    @State var isDragging = false
    @State var dragValue = CGSize.zero

    var body: some View {
        VStack {
            Text("width: \(dragValue.width)")
            Text("height: \(dragValue.height)")
            VStack (spacing: 16) {
                HStack(spacing: 35) {
                    Image(systemName: "chevron.left")
                        .foregroundColor(.gray)


                    VStack (spacing: 80) {
                        Image(systemName: "chevron.up")
                            .foregroundColor(.gray)
                        Image(systemName: "chevron.down")
                            .foregroundColor(.gray)

                    }
                    Image(systemName: "chevron.right")
                        .foregroundColor(.gray)

                }


            }
            .offset(x: dragValue.width * 0.05, y: dragValue.height * 0.05)

            .frame(width: 150, height: 150)

            .background(LinearGradient(gradient: Gradient(colors: [Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)), Color(#colorLiteral(red: 0.8705882353, green: 0.8941176471, blue: 0.9450980392, alpha: 1))]), startPoint: .top, endPoint: .bottom))
            .clipShape(RoundedRectangle(cornerRadius: isDragging ? (55 - abs(dragValue.height) / 10) : 55, style: .continuous))
            .offset(x: dragValue.width, y: dragValue.height)

            .shadow(color: Color.black.opacity(0.2), radius: 20, x: 0, y: 20)
            .padding(.horizontal, 30)
            .gesture(
                DragGesture().onChanged { value in
                    self.dragValue = value.translation
                    self.isDragging = true
                }
                .onEnded { value in
                    self.dragValue = .zero
                    self.isDragging = false
                }
            )
                .animation(.spring(response: 0.5, dampingFraction: 0.6, blendDuration: 0))
        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Here is possible solution based on asymptotic curve (if somebody find it helpful).这是基于渐近曲线的可能解决方案(如果有人发现它有帮助)。

Tested with Xcode 11.4 / iOS 13.4使用 Xcode 11.4 / iOS 13.4 测试

Update: retested with Xcode 13.4 / iOS 15.5更新:用 Xcode 13.4 / iOS 15.5 重新测试

演示

Changed part更改部分

DragGesture().onChanged { value in
    let limit: CGFloat = 200        // the less the faster resistance 
    let xOff = value.translation.width
    let yOff = value.translation.height
    let dist = sqrt(xOff*xOff + yOff*yOff);
    let factor = 1 / (dist / limit + 1)
    self.dragValue = CGSize(width: value.translation.width * factor,
                        height: value.translation.height * factor)
    self.isDragging = true
}

backup 备份

A guy on reddit helped me with this issue, I just had to change.gesture to this: reddit 上的一个人帮助我解决了这个问题,我只需要将其更改为:

.gesture(
    DragGesture().onChanged { dragValue in
        let translation: CGSize = dragValue.translation
        let multiplier: CGFloat = 15
        let incrementalW: CGFloat = log(abs(translation.width)) * multiplier
        let incrementalH: CGFloat = log(abs(translation.height)) * multiplier
        let incremental = CGSize(
            width: translation.width > 0 ? incrementalW : -incrementalW,
            height: translation.height > 0 ? incrementalH : -incrementalH
        )
        let resistance = CGSize(
            width: abs(translation.width) < abs(incremental.width) ? translation.width : incremental.width,
            height: abs(translation.height) < abs(incremental.height) ? translation.height : incremental.height
        )

        self.dragValue = resistance
        self.isDragging = true
    }
    .onEnded { dragValue in
        self.dragValue = .zero
        self.isDragging = false
    }
)

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

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