Ограничить перетаскивание до круглых границ в SwiftUI - PullRequest
0 голосов
/ 20 января 2020

Я хотел бы реализовать перетаскивание по кругу в SwiftUI, но я не уверен в лучшем способе go.

Вот базовый c код перетаскивания - есть один маленький перетаскиваемый круг, который я хотел бы ограничить границами большего круга во время фазы updating DragGesture. В настоящий момент черный круг перетаскивается по всему виду.

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 «видеть» круговые границы вида?

1 Ответ

2 голосов
/ 20 января 2020

это не так много кода для реализации этого. Я просто вычисляю расстояние между точками (сделал расширение для этого, как в , этот вопрос ) и использую этот коэффициент, чтобы уменьшить фактическое расстояние. Это то, чего вы хотите достичь?

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
                    }
                  })
              )
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...