沿较大的圆弧路径移动圆弧段路径.SWIFT



我正在尝试制作动画,使弧段路径(绿色部分(沿着"母亲;弧形路径(红色部分(。

mainView

以下是完整的存储库:https://github.com/gmb55/movingArcs

完整代码:


import UIKit
class MovingArcs: UIView {
var path: UIBezierPath!
var shapeLayer: CAShapeLayer!
var movement: CAKeyframeAnimation!
// set path for moving and draw it on screen
func pathShapeLayer() -> UIBezierPath {
let startDegree = 180.0
let endDegree = 360.0
let start = CGFloat(startDegree).toRadians()
let end = CGFloat(endDegree).toRadians()
path = UIBezierPath(arcCenter: CGPoint(x: 100, y: 100),
radius: 100.0,
startAngle: start,
endAngle: end,
clockwise: true)
let pathShapeLayer = CAShapeLayer()
pathShapeLayer.path = path.cgPath
pathShapeLayer.fillColor = UIColor.clear.cgColor
pathShapeLayer.lineWidth = CGFloat(4)
pathShapeLayer.strokeColor = UIColor.red.cgColor
pathShapeLayer.position = .init(x: 0, y: 0)
self.layer.addSublayer(pathShapeLayer)
return path
}
// set movemnet along path with rotation
func addAnimation() {
let movement = CAKeyframeAnimation(keyPath: "position")
movement.path = pathShapeLayer().cgPath
movement.duration = 3
movement.repeatCount = 1
movement.rotationMode = CAAnimationRotationMode.rotateAuto
movement.calculationMode = CAAnimationCalculationMode.paced
movement.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)]
self.movement = movement
}
// set path for arc that will be moving
func movingArc() -> UIBezierPath {
let startDegree = 180.0
let endDegree = 210.0
let start = CGFloat(startDegree).toRadians()
let end = CGFloat(endDegree).toRadians()
let arcPath = UIBezierPath(arcCenter: CGPoint(x: 100, y: 100),
radius: 100.0,
startAngle: start,
endAngle: end,
clockwise: true)
return arcPath
}
// draw shapeLayer for moving arc
func movingArcLayer() -> CAShapeLayer {
let color = UIColor.green
let backgroundCircleLayer = CAShapeLayer()
backgroundCircleLayer.path = movingArc().cgPath
backgroundCircleLayer.fillColor = UIColor.clear.cgColor
backgroundCircleLayer.strokeColor = color.cgColor
backgroundCircleLayer.lineWidth = 4.0
backgroundCircleLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
//  backgroundCircleLayer.position = CGPoint(x: 0, y: 100)
//  backgroundCircleLayer.transform = CATransform3DMakeTranslation(0, -100, 0)
//  backgroundCircleLayer.transform = CATransform3DMakeRotation(CGFloat(-180).toRadians(), 0, 0, 1)
self.layer.addSublayer(backgroundCircleLayer)
return backgroundCircleLayer
}
// init for animation
func initiateAnimation() {
let layer = movingArcLayer()
layer.add(self.movement, forKey: "Object Movement")
}
init() {
super.init(frame: .zero)
addAnimation()
movingArcLayer()
initiateAnimation()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
extension CGFloat {
func toRadians() -> CGFloat {
return self * CGFloat(Double.pi) / 180.0
}
}

当绿色弧形代码看起来像这样时,它正在移动,但位置不对,而不是沿着红色路径。https://media.giphy.com/media/loSPpw2TPNNJyXSqcO/giphy.gif

当我将转换设置为:

backgroundCircleLayer.position = CGPoint(x: 0, y: 100)
backgroundCircleLayer.transform = CATransform3DMakeTranslation(0, -100, 0)

它在正确的路径上移动,但旋转错误:https://media.giphy.com/media/S85AIcXObCMfOhAjEe/giphy.gif

当我将转换设置为:

backgroundCircleLayer.position = CGPoint(x: 100, y: 0)
backgroundCircleLayer.transform = CATransform3DMakeTranslation(-100, 0, 0)

它在错误的路径上移动(偏移90度(,但旋转是正确的。https://media.giphy.com/media/mEEWv5i32TELTseyQG/giphy.gif

问题是,我应该如何正确设置层变换,也许你知道解释CoreAnimation如何工作的好教程?

问题是如何为绿色圆弧声明路径。以前它是一条粗曲线。但现在它是一个2D平面。

以下工作代码:

import UIKit
class MovingRect: UIView {
var path: UIBezierPath!
var shapeLayer: CAShapeLayer!
var movement: CAKeyframeAnimation!
// set path for moving and draw it on screen
func pathShapeLayer() -> UIBezierPath {
let startDegree = 180.0
let endDegree = 360.0
let start = CGFloat(startDegree).toRadians()
let end = CGFloat(endDegree).toRadians()
path = UIBezierPath(arcCenter: CGPoint(x: 100, y: 100),
radius: 100.0,
startAngle: start,
endAngle: end,
clockwise: true)
let pathShapeLayer = CAShapeLayer()
pathShapeLayer.path = path.cgPath
pathShapeLayer.fillColor = UIColor.clear.cgColor
pathShapeLayer.lineWidth = CGFloat(4)
pathShapeLayer.strokeColor = UIColor.red.cgColor
pathShapeLayer.position = .init(x: 0, y: 0)
self.layer.addSublayer(pathShapeLayer)
return path
}
// set movemnet along path with rotation
func addAnimation() {
let movement = CAKeyframeAnimation(keyPath: "position")
movement.path = pathShapeLayer().cgPath
movement.duration = 2
movement.repeatCount = 1
movement.rotationMode = CAAnimationRotationMode.rotateAuto
movement.calculationMode = CAAnimationCalculationMode.paced
movement.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)]
self.movement = movement
}

func movingArcPath() -> UIBezierPath {
let startDegree = 255.0
let endDegree = 285.0
let start = CGFloat(startDegree).toRadians()
let end = CGFloat(endDegree).toRadians()
path = UIBezierPath()

path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 110, startAngle: start, endAngle: end, clockwise: true)
path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 90, startAngle: end, endAngle: start, clockwise: false)
path.close()

return path
}

// draw shapeLayer for moving arc
func movingArcLayer() -> CAShapeLayer {
let color = UIColor.green
let movingRectLayer = CAShapeLayer()
movingRectLayer.path = movingArcPath().cgPath
movingRectLayer.fillColor = color.cgColor
movingRectLayer.strokeColor = color.cgColor
movingRectLayer.lineWidth = 4.0
movingRectLayer.transform = CATransform3DMakeTranslation(-100, 0, 0)
movingRectLayer.position = CGPoint(x: 200, y: 100)
movingRectLayer.anchorPoint = CGPoint(x: 200, y: 100)
//   movingRectLayer.transform = CATransform3DMakeRotation(CGFloat(90).toRadians(), 0, 0, 1)

self.layer.addSublayer(movingRectLayer)
return movingRectLayer
}
// init for animation
func initiateAnimation() {
let layer = movingArcLayer()
layer.add(self.movement, forKey: "Object Movement")
}
init() {
super.init(frame: .zero)
addAnimation()
initiateAnimation()
//  removeArcLayer()

}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}

最新更新