沿更大的圆弧路径移动圆弧段路径。 SWIFT
Moving arc segment path along bigger arc path. 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 工作原理的好教程?
问题出在我为绿色弧线声明路径的方式上。以前它是一条单一的粗曲线。但是现在是二维平面了。
下面的工作代码:
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)
}
}
我正在尝试制作沿“母”弧路径(红色部分)移动弧段路径(绿色部分)的动画。
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 工作原理的好教程?
问题出在我为绿色弧线声明路径的方式上。以前它是一条单一的粗曲线。但是现在是二维平面了。
下面的工作代码:
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)
}
}