我正在构建一个简单的UIView
子类,它将一些数据绘制为折线图。我希望在数据点出现时为它们设置动画,但作为CAShapeLayer
的新手,我觉得必须有比我正在做的更好的方式。我已经阅读了一些文章,并根据this article松散地汇总了一些代码。
这是代码。基本上,每次有新数据时,它都会重绘整个路径,但只会动画新部分(嗯,近似)。
let animationLayer = CALayer()
func setupDrawingLayer(){
pathLayer.frame = self.animationLayer.bounds
pathLayer.bounds = self.animationLayer.bounds
pathLayer.geometryFlipped = true
pathLayer.strokeColor = UIColor.blackColor().CGColor
pathLayer.fillColor = nil
pathLayer.lineWidth = 3.0
pathLayer.lineJoin = kCALineJoinBevel
self.animationLayer.addSublayer(pathLayer)
}
func nextPoint(){ // This is called by a timer to simulate a new data point
let path = UIBezierPath()
path.moveToPoint(self.dataPoints[0])
for i in 1...pointIndex{
path.addLineToPoint(self.dataPoints[i])
}
pathLayer.path = path.CGPath
pointIndex += 1
let pathAnimation = CABasicAnimation(keyPath:"strokeEnd")
pathAnimation.duration = 0.5
pathAnimation.fromValue = (Double(pointIndex) - 1.0) / Double(pointIndex)
pathAnimation.toValue = 1.0
self.pathLayer.addAnimation(pathAnimation, forKey:"strokeEnd")
}
另外,由于我的fromValue
加权只是一个近似值,因此它不会导致平滑的动画效果。理想情况下,我认为nextPoint()
中的方法应该仅为最新部分设置动画,然后"保存"它到层...但不知道如何处理。任何指针都会非常受欢迎。
更新
这种方法仍然会在每次调用nextPoint()
时重新创建路径,但至少动画现在是准确的:
func nextPoint(){
let oldPath = pathLayer.path
let path = UIBezierPath()
path.moveToPoint(self.dataPoints[0])
for i in 1...pointIndex{
path.addLineToPoint(self.dataPoints[i])
}
pathLayer.path = path.CGPath
pointIndex += 1
let pathAnimation = CABasicAnimation(keyPath:"path")
pathAnimation.duration = 0.5
pathAnimation.fromValue = oldPath
pathAnimation.toValue = path.CGPath
self.pathLayer.addAnimation(pathAnimation, forKey:"path")
}