寫在前面的:
實(shí)現(xiàn)限制在圓形區(qū)域拖動(dòng)眷篇,雖然邏輯也很簡(jiǎn)單例诀,但是調(diào)試起來還挺費(fèi)心思的朽肥!…… 這里將我自己的經(jīng)驗(yàn)寫下來菇民,供需要的人參考尽楔!
最終效果:
實(shí)現(xiàn)思路:
- 實(shí)現(xiàn)小圓拖動(dòng)
- 限制拖動(dòng)范圍
實(shí)現(xiàn)小圓拖動(dòng):
實(shí)現(xiàn)小圓拖動(dòng)的邏輯比較簡(jiǎn)單投储,給小圓添加拖動(dòng)手勢(shì)就可以了!...
為了簡(jiǎn)單起見(偷懶的借口^_^)阔馋,這里直接用 UIButton 通過設(shè)置圓角(高度的一半玛荞,以下的圓形拖動(dòng)區(qū)域也是一樣的做法)
var circle: UIView! // 定義【圓形】區(qū)域
var button: UIButton! // 定義【拖動(dòng)】按鈕
設(shè)置圓角以及添加拖動(dòng)手勢(shì)
// 添加【拖動(dòng)】按鈕
button = UIButton(frame: CGRect(x: origin.x - bRadius, y: origin.y - bRadius, width: bRadius * 2, height: bRadius * 2))
button.setTitle("測(cè)試", for: .normal)
button.backgroundColor = UIColor.orange // 設(shè)置背景色
button.layer.cornerRadius = bRadius // 設(shè)置圓角半徑
let pan = UIPanGestureRecognizer(target: self, action: #selector(dragButton)) // 定義【拖動(dòng)】手勢(shì)
button.addGestureRecognizer(pan) // 添加【拖動(dòng)】手勢(shì)
定義拖動(dòng)手勢(shì)handler
@objc func dragButton(_ pan: UIPanGestureRecognizer) {
let center = pan.location(in: pan.view!.superview)
switch pan.state {
case .changed:
let newCenter = dragLimitInCircle(target: center, origin: origin, radius: cRadius) // 限制在【圓形】上拖動(dòng)
button.center = newCenter // 設(shè)置【拖動(dòng)】按鈕 中心點(diǎn)位置
default:
break
}
}
限制拖動(dòng)范圍:
繪制大圓拖動(dòng)限制區(qū)域(這里同樣通過設(shè)置圓角的方法實(shí)現(xiàn)!)
// 添加【圓形】區(qū)域
circle = UIView(frame: CGRect(x: origin.x - cRadius, y: origin.y - cRadius, width: cRadius * 2, height: cRadius * 2))
circle.backgroundColor = UIColor.blue // 設(shè)置背景色
circle.layer.cornerRadius = cRadius // 設(shè)置圓角半徑
view.addSubview(circle) // 添加【圓形】區(qū)域 到【主視圖】
限制在圓形區(qū)域里面拖動(dòng)
// 限制【圓形】區(qū)域拖動(dòng) 方法
func dragLimitInCircle(target ePoint: CGPoint, origin oPoint: CGPoint, radius: CGFloat) -> CGPoint {
var newPoint: CGPoint
let x0 = ePoint.x - oPoint.x // 坐標(biāo) X
let y0 = ePoint.y - oPoint.y // 坐標(biāo) Y
let distance = sqrt(pow(x0, 2) + pow(y0, 2)) // 拖動(dòng)距離
if distance <= radius - bRadius {
newPoint = ePoint
} else {
let angle = atan(y0 / x0)
var a: CGFloat = 1 // 定義【翻轉(zhuǎn)】系數(shù)
if x0 < 0 {
// 第二象限 | 第三象限
a = -a
}
let x = oPoint.x + a * (radius - bRadius) * cos(angle)
let y = oPoint.y + a * (radius - bRadius) * sin(angle)
newPoint = CGPoint(x: x, y: y)
}
return newPoint
}
完整代碼:
//
// DragInCircle.swift
// UIKit-basic
//
// Created by Qire_er on 2021/11/26.
//
import UIKit
class DragInCircleVC: UIViewController {
var circle: UIView! // 定義【圓形】區(qū)域
var button: UIButton! // 定義【拖動(dòng)】按鈕
let dWidth = UIScreen.main.bounds.width //【設(shè)備】寬度
let dHeight = UIScreen.main.bounds.height //【設(shè)備】高度
let cRadius: CGFloat = 160 // 定義【圓形】區(qū)域 半徑
let bRadius: CGFloat = 30 // 定義【拖動(dòng)】按鈕 半徑
var origin: CGPoint {
CGPoint(x: dWidth / 2, y: dHeight / 2)
} // 【原點(diǎn)】位置
override func viewDidLoad() {
super.viewDidLoad()
// 添加【圓形】區(qū)域
circle = UIView(frame: CGRect(x: origin.x - cRadius, y: origin.y - cRadius, width: cRadius * 2, height: cRadius * 2))
circle.backgroundColor = UIColor.blue // 設(shè)置背景色
circle.layer.cornerRadius = cRadius // 設(shè)置圓角半徑
view.addSubview(circle) // 添加【圓形】區(qū)域 到【主視圖】
// 添加【拖動(dòng)】按鈕
button = UIButton(frame: CGRect(x: origin.x - bRadius, y: origin.y - bRadius, width: bRadius * 2, height: bRadius * 2))
button.setTitle("測(cè)試", for: .normal)
button.backgroundColor = UIColor.orange // 設(shè)置背景色
button.layer.cornerRadius = bRadius // 設(shè)置圓角半徑
let pan = UIPanGestureRecognizer(target: self, action: #selector(dragButton)) // 定義【拖動(dòng)】手勢(shì)
button.addGestureRecognizer(pan) // 添加【拖動(dòng)】手勢(shì)
view.addSubview(button) // 添加【拖動(dòng)】按鈕 到【主視圖】
view.backgroundColor = UIColor.white
}
@objc func dragButton(_ pan: UIPanGestureRecognizer) {
let center = pan.location(in: pan.view!.superview)
switch pan.state {
case .changed:
let newCenter = dragLimitInCircle(target: center, origin: origin, radius: cRadius) // 限制在【圓形】上拖動(dòng)
button.center = newCenter // 設(shè)置【拖動(dòng)】按鈕 中心點(diǎn)位置
default:
break
}
}
// 限制【圓形】區(qū)域拖動(dòng) 方法
func dragLimitInCircle(target ePoint: CGPoint, origin oPoint: CGPoint, radius: CGFloat) -> CGPoint {
var newPoint: CGPoint
let x0 = ePoint.x - oPoint.x // 坐標(biāo) X
let y0 = ePoint.y - oPoint.y // 坐標(biāo) Y
let distance = sqrt(pow(x0, 2) + pow(y0, 2)) // 拖動(dòng)距離
if distance <= radius - bRadius {
newPoint = ePoint
} else {
let angle = atan(y0 / x0)
var a: CGFloat = 1 // 定義【翻轉(zhuǎn)】系數(shù)
if x0 < 0 {
// 第二象限 | 第三象限
a = -a
}
let x = oPoint.x + a * (radius - bRadius) * cos(angle)
let y = oPoint.y + a * (radius - bRadius) * sin(angle)
newPoint = CGPoint(x: x, y: y)
}
return newPoint
}
}