将拖动限制为SwiftUI中的圆形边界 [英] Limit drag to circular bounds in SwiftUI

查看:75
本文介绍了将拖动限制为SwiftUI中的圆形边界的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

 导入SwiftUIstruct ContentView:查看{@State私有变量位置= CGSize.zero@GestureState var dragOffset:CGSize = .zero私人var dragRadius:CGFloat = 200.0var body:some View {ZStack {圆圈().fill(颜色.红色).frame(width:dragRadius,height:dragRadius)圆圈().fill(颜色.黑色).frame(宽度:dragRadius/4,高度:dragRadius/4).offset(x:position.width + dragOffset.width,y:position.height + dragOffset.height).手势(DragGesture().updating($ dragOffset,body:{(value,state,transaction)in//这里需要钳制圆形边界吗?状态= value.translation}).onEnded({self.position.height + = value.translation.heightself.position.width + = value.translation.width}))}}} 

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

解决方案

实现该功能的代码并不多.我只是计算点之间的距离(对此做了扩展,例如

 导入SwiftUI扩展名CGPoint {函数距离(至点:CGPoint)->CGFloat {返回sqrt(pow((point.x-x),2)+ pow((point.y-y),2))}}struct ContentView:查看{@State私有变量位置= CGPoint(x:100,y:100)私人var dragDiametr:CGFloat = 200.0var body:some View {返回VStack {Text(当前位置=(x:\(Int(position.x)),y:\(Int(position.y)))")圆圈().fill(颜色.红色).frame(宽度:dragDiametr,高度:dragDiametr).覆盖(圆圈().fill(颜色.黑色).frame(宽度:dragDiametr/4,高度:dragDiametr/4).position(x:position.x,y:position.y).gesture(DragGesture().onChanged(){value in让currentLocation = value.location让中心= CGPoint(x:self.dragDiametr/2,y:self.dragDiametr/2)让距离= center.distance(to:currentLocation)如果距离>self.dragDiametr/2 {令k =(self.dragDiametr/2)/距离让newLocationX =(currentLocation.x-center.x)* k + center.x让newLocationY =(currentLocation.y-center.y)* k + center.yself.position = CGPoint(x:newLocationX,y:newLocationY)}别的{self.position = value.location}}))}}} 

I would like to implement circular dragging in SwiftUI, but am not sure of the best way to go about it.

Here is the basic dragging code - there is one small draggable circle which I would like to limit to the bounds of the bigger one during the updating phase of the DragGesture. At the moment the black circle is draggable across the entire view.

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
              })
          )
      }
    }
}

I wonder whether it's a case of using trigonometry and polar co-ordinates to calculate the distance from the centre and limit to the radius in the direction of the dragged circle, or is there an easier way to get SwiftUI to "see" the circular bounds of a view?

解决方案

its not so much code to implement that. I just calculate distance between points (made an extension for that like in that question) and use that coefficient to make actual distance shorter. Is that what you want to reach?

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
                    }
                  })
              )
        }
    }
}

这篇关于将拖动限制为SwiftUI中的圆形边界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆