我向UIView添加了幾個圖層,現在希望按順序對這些圖層進行動畫處理。Swift:從UIView序列動畫層
我有5層動畫,這些都是圈子。我使用observable字段來獲取值的更改通知,並開始使用needsDisplayForKey()和actionForKey()方法進行動畫處理。
可觀察到的字段:
@NSManaged private var _startAngle: CGFloat
@NSManaged private var _endAngle: CGFloat
目前所有的層動畫的同時,當我改變每個層可觀察的領域之一。我希望改變這一點,並希望在2.5秒的時間內依次對所有這些動畫進行動畫處理。所以,當一個動畫完成後,我希望動畫下一層等。
現在我知道動畫已完成的唯一方法是使用animationDidStop()方法。然而,這種方式我無法知道其他動畫的圖層。你們知道這是一個好的解決方案嗎?
我的層:
class HourLayer: CAShapeLayer {
@NSManaged private var _startAngle: CGFloat
@NSManaged private var _endAngle: CGFloat
@NSManaged private var _fillColor: UIColor
@NSManaged private var _strokeWidth: CGFloat
@NSManaged private var _strokeColor: UIColor
@NSManaged private var _duration: CFTimeInterval
private var _previousEndAngle: CGFloat = 0.0
private var _previousStartAngle: CGFloat = 0.0
private let _lenghtOfArc: CGFloat = CGFloat(2 * M_PI)
internal var StartAngle: CGFloat {
get {
return _startAngle
}
set {
_startAngle = newValue
}
}
internal var EndAngle: CGFloat {
get {
return _endAngle
}
set {
_endAngle = newValue
}
}
internal var FillColor: UIColor {
get {
return _fillColor
}
set {
_fillColor = newValue
}
}
internal var StrokeWidth: CGFloat {
get {
return _strokeWidth
}
set {
_strokeWidth = newValue
}
}
internal var StrokeColor: UIColor {
get {
return _strokeColor
}
set {
_strokeColor = newValue
}
}
internal var DurationOfAnimation: CFTimeInterval {
get {
return _duration
}
set {
_duration = newValue
}
}
required override init!() {
super.init()
self._startAngle = 0.0
self._endAngle = 0.0
self._fillColor = UIColor.clearColor()
self._strokeWidth = 4.0
self._strokeColor = UIColor.blackColor()
self._duration = 1.0
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("required init(:coder) is missing")
}
override init!(layer: AnyObject!) {
super.init(layer: layer)
if layer.isKindOfClass(HourLayer) {
var other: HourLayer = layer as HourLayer
self._startAngle = other._startAngle
self._endAngle = other._endAngle
self._fillColor = other._fillColor
self._strokeWidth = other._strokeWidth
self._strokeColor = other._strokeColor
self._duration = other._duration
}
}
override var frame: CGRect {
didSet {
self.setNeedsLayout()
self.setNeedsDisplay()
}
}
override func actionForKey(event: String!) -> CAAction! {
if event == "_startAngle" || event == "_endAngle" {
return makeAnimationForKey(event)
}
return super.actionForKey(event)
}
private func makeAnimationForKey(event: String) -> CABasicAnimation {
// We want to animate the strokeEnd property of the circleLayer
let animation: CABasicAnimation = CABasicAnimation(keyPath: event)
// Set the animation duration appropriately
animation.duration = self._duration
// When no animation has been triggered and the presentation layer does not exist yet.
if self.presentationLayer() == nil {
if event == "_startAngle" {
animation.fromValue = self._previousStartAngle
self._previousStartAngle = self._startAngle
} else if event == "_endAngle" {
animation.fromValue = self._previousEndAngle
self._previousEndAngle = self._endAngle
}
} else {
animation.fromValue = self.presentationLayer()!.valueForKey(event)
}
animation.removedOnCompletion = false
animation.delegate = self
// Do a linear animation (i.e. the speed of the animation stays the same)
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
return animation
}
override class func needsDisplayForKey(key: String) -> Bool {
if key == "_startAngle" || key == "_endAngle" {
return true
}
return super.needsDisplayForKey(key)
}
override func drawInContext(ctx: CGContext!) {
var center: CGPoint = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2)
var radius: CGFloat = CGFloat((CGFloat(self.bounds.width) - CGFloat(_strokeWidth))/2)
// Set the stroke color
CGContextSetStrokeColorWithColor(ctx, _strokeColor.CGColor)
// Set the line width
CGContextSetLineWidth(ctx, _strokeWidth)
// Set the fill color (if you are filling the circle)
CGContextSetFillColorWithColor(ctx, UIColor.clearColor().CGColor)
// Draw the arc around the circle
CGContextAddArc(ctx, center.x, center.y, radius, _startAngle, _lenghtOfArc * _endAngle, 0)
// Draw the arc
CGContextDrawPath(ctx, kCGPathStroke) // or kCGPathFillStroke to fill and stroke the circle
super.drawInContext(ctx)
}
override func animationDidStop(anim: CAAnimation!, finished flag: Bool) {
// Trigger animation for other layer by setting their values for _startAngle and _endAngle.
}
}
製作動畫時請分享代碼 – Arbitur 2015-03-13 09:43:06