やりたい事
・円を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を使うのがポイントです。