
やりたい事
・円をCGContextFillEllipseInRectで描きたい
・描いた円の色を赤から青にだんだんとアニメーションさせたい
これを実装する方法です。
こちらはダメな例。こういう風にやっても、色のアニメーションはしません。
青い円がいきなり表示されて、はい、おしまい。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var rect = CGRectMake(10, 10, 200, 200)
var testView = TestView(frame: rect)
self.view.addSubview(testView)
UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {() -> Void in
testView.shapeColor = UIColor.blueColor()
}, completion: {(finished: Bool) -> Void in
})
}
import Foundation
import UIKit
class TestView: UIView {
var shapeColor: UIColor = UIColor.redColor()
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clearColor()
}
override func drawRect(rect: CGRect) {
var context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, shapeColor.CGColor)
CGContextFillEllipseInRect(context, CGRectMake(100, 100, 100, 100))
}
}
以上、ダメな例おしまい。
では改良です。
CALayerを継承したクラス(MyLayer)を作って、そこに変更したいプロパティを追加します。
描画の部分はこのレイヤーのdrawInContextにごっそり移動します。
この追加したプロパティをCABasicAnimationで変化させればアニメーションしてくれます。
以下、ちゃんと動作するソースです。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var rect = CGRectMake(10, 10, 200, 200)
var testView = Test2View(frame: rect)
self.view.addSubview(testView)
var anim = CABasicAnimation(keyPath: "shapeColor")
anim.duration = 1.0
anim.fromValue = UIColor.redColor().CGColor
anim.toValue = UIColor.blueColor().CGColor
anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
testView.myLayer.addAnimation(anim, forKey: "animate")
testView.myLayer.shapeColor = UIColor.blueColor().CGColor
}
}
import Foundation
import UIKit
class Test2View: UIView {
var myLayer: MyLayer! = nil
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clearColor()
myLayer = MyLayer()
myLayer.frame = self.bounds
myLayer.shapeColor = UIColor.redColor().CGColor
myLayer.setNeedsDisplay()
self.layer.addSublayer(myLayer)
}
}
class MyLayer: CALayer {
var shapeColor: CGColorRef! = nil
override init!() {
super.init()
}
override init(layer: AnyObject!) {
if let layer = layer as? MyLayer {
shapeColor = layer.shapeColor
}
super.init(layer: layer)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override class func needsDisplayForKey(key: String!) -> Bool {
if key == "shapeColor" {
return true
}
return super.needsDisplayForKey(key)
}
override func drawInContext(context: CGContext!) {
CGContextSetFillColorWithColor(context, shapeColor)
CGContextFillEllipseInRect(context, CGRectMake(100, 100, 100, 100))
}
}
CABasicAnimationはUIColorだとアニメーションしてくれないので、CGColorを使うのがポイントです。



