我正在尝试沿圆形路径为线形CAShapeLayer设置动画。我创建了线层的初始路径和最终路径,并将它们添加到CABasicAnimation的值中。
但是动画不是我所期望的。我在这里停留了过去两天。
func getAllLayers() -> [CALayer]
{
var layers = []
let pointerEndPoint = CGPoint(x: xPointOfPointer , y: yPointOfPointer) // Final end point of pointer
let radius = 5
let pointerFinalPath = UIBezierPath()
pointerFinalPath.addArc(withCenter: circleCenter, radius: radius, startAngle: 0, endAngle:2 * CGFloat.pi, clockwise: false)
pointerFinalPath.move(to: circleCenter)
pointerFinalPath.addLine(to: endPoint)
pointerFinalPath.close()
let pointerPathLayer = CAShapeLayer()
pointerPathLayer.path = pointerFinalPath.cgPath
pointerPathLayer.lineWidth = 2
pointerPathLayer.fillColor = UIColor.black.cgColor
pointerPathLayer.strokeColor = UIColor.black.cgColor
layers.append(pointerPathLayer)
let pointerInitialBezierPath = UIBezierPath()
pointerInitialBezierPath.addArc(withCenter: circleCenter, radius: radius,startAngle: 0 , endAngle: 2 * CGFloat.pi , clockwise: false)
pointerInitialBezierPath.move(to: circleCenter)
pointerInitialBezierPath.addLine(to: CGPoint(x: circleCenter.x - 50 , y: centerY))
pointerInitialBezierPath.close()
let pointerInitialCGPath = pointerInitialBezierPath.cgPath
let pointerFinalCGPath = pointerFinalPath.cgPath
// Pointer Animation
let pointerAnimation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path))
pointerAnimation.fromValue = pointerInitialCGPath
pointerAnimation.toValue = pointerFinalCGPath
pointerAnimation.duration = 0.5
pointerAnimation.isCumulative = true
pointerPathLayer.add(pointerAnimation, forKey: "Animation")
return layers
}
在Stack over流中搜索解决方案,但找不到我的错误。我希望动画能像时钟一样转动。
请注意,随着动画的进行,针的长度也在变化。我希望它保持恒定的长度,只希望改变针的角度。我将不胜感激。
编辑1:如果我尝试transform.rotation动画使针头旋转,但发生在错误的中心点附近。
// Pointer Animation
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = angleOfActualValueinRad
rotateAnimation.duration = 2.0
pointerPathLayer.add(rotateAnimation, forKey: "Animation")
编辑2:使用此链接找到我的github项目。 Animation Issue
答案 0 :(得分:1)
您使用了错误的变换旋转,请尝试执行以下操作
let rAnimation = CABasicAnimation(keyPath:"transform.rotation.z")
rAnimation.duration = 1
rAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
rAnimation.fromValue = degree2radian(90)
rAnimation.repeatCount = Float.infinity
rAnimation.toValue = degree2radian(180)
progressLineLayer.add(rAnimation, forKey:"rotate")
func degree2radian(_ a: CGFloat) -> CGFloat {
return CGFloat.pi * a / 180
}
通过此链接http://sketchytech.blogspot.com/2014/11/swift-how-to-draw-clock-face-using_12.html查看,也许会有所帮助
已更新:
我写了一些代码来演示其工作原理
private func animateProgress() {
// black circle at center
let blackCirclePath = UIBezierPath()
blackCirclePath.addArc(withCenter: view.center, radius: 5, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true)
blackCirclePath.fill()
UIColor.black.setFill()
blackCirclePath.close()
let circleLayer = CAShapeLayer()
circleLayer.path = blackCirclePath.cgPath
view.layer.addSublayer(circleLayer)
// all scale gray background layer
let grayHalfCirclePath = UIBezierPath()
grayHalfCirclePath.addArc(withCenter: view.center, radius: 50, startAngle: 0, endAngle: CGFloat.pi, clockwise: false)
let grayHalfCircleLayer = CAShapeLayer()
grayHalfCircleLayer.frame = view.bounds
grayHalfCircleLayer.path = grayHalfCirclePath.cgPath
grayHalfCircleLayer.strokeColor = UIColor.lightGray.cgColor
grayHalfCircleLayer.fillColor = nil
grayHalfCircleLayer.lineWidth = 10
view.layer.addSublayer(grayHalfCircleLayer)
// animated progress scale
let progressHalfCirclePath = UIBezierPath()
progressHalfCirclePath.addArc(withCenter: view.center, radius: 50, startAngle: CGFloat.pi, endAngle: -CGFloat.pi / 2, clockwise: true)
let progressLayer = CAShapeLayer()
progressLayer.frame = view.bounds
progressLayer.path = progressHalfCirclePath.cgPath
progressLayer.strokeColor = UIColor.orange.cgColor
progressLayer.fillColor = nil
progressLayer.lineWidth = 10
view.layer.addSublayer(progressLayer)
// animation
let pAnimation = CABasicAnimation(keyPath: "strokeEnd")
pAnimation.duration = 1.0
pAnimation.fromValue = NSNumber(floatLiteral: 0)
pAnimation.toValue = NSNumber(floatLiteral: 1)
progressLayer.add(pAnimation, forKey: "strokeEnd")
// black arrow
let progressLineLayer = CAShapeLayer()
progressLineLayer.frame = view.bounds
let progressLinePath = CGMutablePath()
progressLinePath.move(to: CGPoint(x: view.center.x, y: view.center.y))
progressLinePath.addLine(to: CGPoint(x: view.center.x - 30, y: view.center.y - 30))
progressLineLayer.path = progressLinePath
progressLineLayer.strokeColor = UIColor.green.cgColor
progressLineLayer.lineWidth = 1
progressLineLayer.strokeColor = UIColor.black.cgColor
view.layer.addSublayer(progressLineLayer)
let rAnimation = CABasicAnimation(keyPath:"transform.rotation.z")
rAnimation.duration = 1
rAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
rAnimation.fromValue = degree2radian(-45)
rAnimation.repeatCount = 1
rAnimation.toValue = degree2radian(45)
progressLineLayer.add(rAnimation, forKey:"rotate")
}
func degree2radian(_ a: CGFloat) -> CGFloat {
return CGFloat.pi * a / 180
}
答案 1 :(得分:0)
答案 2 :(得分:0)
您无法使用UIBezierPath实现速度计动画。 您需要以任何角度变换Line。 请参考以下代码,我只为解决您的问题而进行了轮换。
let circleCenter = CGPoint(x: 150.0, y: 150.0)
let startPoint = CGPoint(x: 100, y: 150.0)
// Start Path
let pointerStartPath = UIBezierPath()
pointerStartPath.move(to: circleCenter)
pointerStartPath.addLine(to: startPoint)
pointerStartPath.close()
let pointerPathLayer = CAShapeLayer()
pointerPathLayer.frame = CGRect(x: 0, y:0, width: 300, height: 300)
pointerPathLayer.path = pointerStartPath.cgPath
pointerPathLayer.lineWidth = 2
pointerPathLayer.fillColor = UIColor.green.cgColor
pointerPathLayer.strokeColor = UIColor.black.cgColor
self.view.layer.addSublayer(pointerPathLayer)
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = CGFloat.pi * 2.0
rotateAnimation.duration = 2.0
pointerPathLayer.add(rotateAnimation, forKey: "Animation")
使用此代码,可以实现360度旋转。