Основная идея состоит в том, что вы можете определить квадратичный Безье для этой кривой, например, с небольшой функцией полезности, point(at:)
, чтобы сообщить вам значения от 0 до 1, где точка находится начто Безье:
struct QuadBezier {
var point1: CGPoint
var point2: CGPoint
var controlPoint: CGPoint
var path: UIBezierPath {
let path = UIBezierPath()
path.move(to: point1)
path.addQuadCurve(to: point2, controlPoint: controlPoint)
return path
}
func point(at t: CGFloat) -> CGPoint {
let t1 = 1 - t
return CGPoint(
x: t1 * t1 * point1.x + 2 * t * t1 * controlPoint.x + t * t * point2.x,
y: t1 * t1 * point1.y + 2 * t * t1 * controlPoint.y + t * t * point2.y
)
}
}
Затем вы можете использовать это, чтобы определить изогнутый путь:
let bounds = view.bounds
let point1 = CGPoint(x: bounds.minX, y: bounds.midY)
let point2 = CGPoint(x: bounds.maxX, y: bounds.midY)
let controlPoint = CGPoint(x: bounds.midX, y: bounds.midY + 100)
let bezier = QuadBezier(point1: point1, point2: point2, controlPoint: controlPoint)
И затем вы можете установить center
вашего кругового обзора соответственно:
circleView.center = bezier.point(at: t)
Например, здесь я использовал вычисленное свойство path
, чтобы отобразить синий CAShapeLayer
, и используя point(at:)
, чтобы установить center
красного кругового представления на основе значения t
:

Очевидно, я использую жест для очистки изменений t
, но вы можете использовать свой пользовательский степпер или любой другой для достижения того жевещь.