Ios 在圆形路径中设置线状层的动画
我正试图沿着一条圆形路径设置我的线状CAShapeLayer的动画。我创建了线条图层的初始路径和最终路径,并将它们添加到CABasicAnimation的from和to值中 然而,动画不是我所期望的。我在这里呆了两天Ios 在圆形路径中设置线状层的动画,ios,swift,cashapelayer,cabasicanimation,Ios,Swift,Cashapelayer,Cabasicanimation,我正试图沿着一条圆形路径设置我的线状CAShapeLayer的动画。我创建了线条图层的初始路径和最终路径,并将它们添加到CABasicAnimation的from和to值中 然而,动画不是我所期望的。我在这里呆了两天 func getAllLayers() -> [CALayer] { var layers = [] let pointerEndPoint = CGPoint(x: xPointOfPointer , y: yPointOfPointer)
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
}
在堆栈溢出中搜索解决方案,但找不到我的错误。我希望我的动画像时钟的指针一样移动
请注意,随着动画的进行,针的长度正在更改。我希望它保持恒定的长度,只希望我的针的角度改变。我将非常感谢任何帮助
编辑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项目 试试这个库
重量轻,可通过动画进行自定义
希望这有助于实现愉快的编码。使用UIBezierPath无法实现速度表动画。 您需要以任意角度变换直线。 请参考下面的代码旋转,我只是为了解决你的问题
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)
// New : Set Anchor point
pointerPathLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
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º旋转。如果使用了错误的变换旋转,请尝试这样做smth
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
}
看看这个链接,可能会有帮助
更新:
我写了一些代码来说明它是如何工作的
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
}
谢谢你抽出时间。你知道为什么我的代码不起作用吗?如果你改变
pointerPathLayer
的anchorPoint
,改为添加旋转动画怎么办?我用旋转代码发布答案。@girish\u pro问题更新你需要设置锚定点。检查我的答案。添加以下行。pointerPathLayer.ancorpoint=CGPoint(x:0.5,y:0.5)人们感谢您的帮助和时间。这里的问题是我没有为CAShapeLayer设置框架。这种做法是在UIView中使用约束的结果。因此,正如@girish_pro所建议的,我通过正确地为每个CAShapelayer计算框架,并在我的CABASICANIATION中从角度值和角度值应用来修复它。仍然是相同的问题吗?是的,兄弟,请检查我随附的git项目,它显示了这个问题。谢谢你的帮助。我真的很感谢你抽出时间来帮助我。