【Swift】Core Graphicsで描いた図形の色をアニメーションで変更したい場合

Core Graphicsで描いた図形の色をアニメーション

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

タイトルとURLをコピーしました