在SwiftUI中将拖动限制为圆形范围

问题描述 投票:0回答:1

我想在SwiftUI中实现循环拖动,但是不确定如何做到最好。

这是基本的拖动代码-有一个小可拖动的圆圈,我想在DragGesture的updating阶段将其限制在较大的可拖动圆圈的范围内。目前,黑色圆圈可在整个视图中拖动。

import SwiftUI

struct ContentView: View {

  @State private var position = CGSize.zero
  @GestureState var dragOffset: CGSize = .zero

  private var dragRadius: CGFloat = 200.0

    var body: some View {
      ZStack {
        Circle()
          .fill(Color.red)
          .frame(width: dragRadius, height: dragRadius)

        Circle()
          .fill(Color.black)
          .frame(width: dragRadius / 4, height: dragRadius / 4)
          .offset(x: position.width + dragOffset.width, y: position.height + dragOffset.height)
          .gesture(
            DragGesture()
              .updating($dragOffset, body: { (value, state, transaction) in
                // Need to clamp to circular bounds here??
                state = value.translation
              })
              .onEnded({ (value) in
                self.position.height += value.translation.height
                self.position.width += value.translation.width
              })
          )
      }
    }
}

我想知道是用三角函数和极坐标来计算从中心到圆弧方向上的半径的距离,还是有一种更简单的方法让SwiftUI“看到”视图的圆形边界?

ios swiftui
1个回答
1
投票

没有那么多代码来实现。我只是计算点之间的距离(像在that question中那样对其进行了扩展),并使用该系数使实际距离更短。这就是您想要达到的目标吗?

enter image description here

import SwiftUI

extension CGPoint {
    func distance(to point: CGPoint) -> CGFloat {
        return sqrt(pow((point.x - x), 2) + pow((point.y - y), 2))
    }
}

struct ContentView: View {

    @State private var position = CGPoint(x: 100, y: 100)
    private var dragDiametr: CGFloat = 200.0
    var body: some View {

    return
        VStack{
            Text("current position = (x: \(Int(position.x)), y: \(Int(position.y)))")
            Circle()
              .fill(Color.red)
              .frame(width: dragDiametr, height: dragDiametr)
              .overlay(
                Circle()
                  .fill(Color.black)
                  .frame(width: dragDiametr / 4, height: dragDiametr / 4)
                  .position(x: position.x, y: position.y)
                  .gesture(DragGesture()
                  .onChanged(){value in
                    let currentLocation = value.location
                    let center = CGPoint(x: self.dragDiametr/2, y: self.dragDiametr/2)
                    let distance = center.distance(to:currentLocation)
                    if distance > self.dragDiametr / 2 {
                        let k = (self.dragDiametr / 2) / distance
                        let newLocationX = (currentLocation.x - center.x) * k+center.x
                        let newLocationY = (currentLocation.y - center.y) * k+center.y
                        self.position = CGPoint(x: newLocationX, y: newLocationY)
                    }else{
                        self.position = value.location
                    }
                  })
              )
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.