ios - CALayer路径动画在停止和重新启动时闪烁
问题描述
我正在尝试停止 aCABasicAnimation
然后重新启动它。为了将动画停止在其当前值,我按照这个答案说
获取动画层的presentationLayer,读取动画属性的当前值,将该值设置为动画层,然后才删除动画。
然而,当我再次启动动画时,我得到了一个奇怪的闪烁效果,像这样:
这是我的代码:
class ViewController: UIViewController {
let shapeView = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
var pathLayer: CAShapeLayer?
let startButton = UIButton(type: .system)
let stopButton = UIButton(type: .system)
override func viewDidLoad() {
super.viewDidLoad()
startButton.frame = CGRect(x: 50, y: 150, width: 80, height: 30)
startButton.setTitle("Start", for: .normal)
startButton.setTitleColor(UIColor.blue, for: .normal)
view.addSubview(startButton)
startButton.addTarget(self, action: #selector(start(_:)), for: .touchUpInside)
stopButton.frame = CGRect(x: 200, y: 150, width: 80, height: 30)
stopButton.setTitle("Stop", for: .normal)
stopButton.setTitleColor(UIColor.blue, for: .normal)
view.addSubview(stopButton)
stopButton.addTarget(self, action: #selector(stop(_:)), for: .touchUpInside)
view.addSubview(shapeView)
shapeView.backgroundColor = UIColor.blue
let pathLayer = CAShapeLayer()
pathLayer.path = getPentagonPath()
shapeView.layer.mask = pathLayer
self.pathLayer = pathLayer
}
@objc func start(_ sender: UIButton!) {
guard let pathLayer = pathLayer else { return }
let newPath = getConcavePentagonPath()
let animation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.path))
animation.fromValue = pathLayer.path
animation.toValue = newPath
animation.duration = 3
pathLayer.path = newPath
pathLayer.add(animation, forKey: "path")
}
@objc func stop(_ sender: UIButton!) {
guard let pathLayer = pathLayer else { return }
if let currentValue = pathLayer.presentation()?.value(forKeyPath: #keyPath(CAShapeLayer.path)) { /// get the presentationLayer for the animating layer
let currentPath = currentValue as! CGPath /// read the current value of the animated property
pathLayer.path = currentPath /// set that value to the animating layer
pathLayer.removeAllAnimations() /// remove the animation
}
}
func getPentagonPath() -> CGPath {
let pentagonPath = UIBezierPath()
pentagonPath.move(to: CGPoint(x: 50, y: 0))
pentagonPath.addLine(to: CGPoint(x: 97.55, y: 34.55))
pentagonPath.addLine(to: CGPoint(x: 79.39, y: 90.45))
pentagonPath.addLine(to: CGPoint(x: 20.61, y: 90.45))
pentagonPath.addLine(to: CGPoint(x: 2.45, y: 34.55))
pentagonPath.close()
return pentagonPath.cgPath
}
func getConcavePentagonPath() -> CGPath {
let pentagonPath = UIBezierPath()
pentagonPath.move(to: CGPoint(x: 50, y: 50))
pentagonPath.addLine(to: CGPoint(x: 97.55, y: 34.55))
pentagonPath.addLine(to: CGPoint(x: 79.39, y: 90.45))
pentagonPath.addLine(to: CGPoint(x: 20.61, y: 90.45))
pentagonPath.addLine(to: CGPoint(x: 2.45, y: 34.55))
pentagonPath.close()
return pentagonPath.cgPath
}
}
解决方案
推荐阅读
- sql-server - SQL Server Service Broker - 处理特定架构中的存储过程
- c# - 如何在 wpf prism 中使用不同的 ViewModel 重用相同的视图?
- node.js - Mongoose 一次插入多个相关记录
- c# - Web API 方法永远不会被路由到
- r - 使用 grepl 没有达到我想要的结果
- timezone - 如何解析时区信息格式的扩展版本?
- html - jscolor 在引导模式中不起作用
- api - 查询 Jenkins 的最后几个构建
- database - 分布式存储系统中的结构化非结构化和半结构化数据是什么
- android - 待定意图打开错误的活动