上一个例子中我们通过使用多个layer进行动画的展示
有些时候我们也需要通过 Core Graphics 绘图在一个 layer 上进行动画 (比较复杂的情况)
大概步骤:
- 定义属性 使用 @NSManaged 声明
- 重写 needsDisplayForKey 方法
- 重写 display 方法 (进行绘制 设置 layer 的 contents 内容 )
重写 actionForKey:(event:string) 方法
注意绘图时获取实时差值时 要取 self.presentationLayer() 内的值
上代码: 带 easeIneaseOut 动画的 简单 横向柱状图
//
// DSProgressDrawLayer.swift
// AnimationStd
//
// Created by 鲍东升 on 16/5/23.
// Copyright © 2016年 鲍东升. All rights reserved.
//
import UIKit
class DSProgressDrawLayer: CAShapeLayer {
@NSManaged var pro:CGFloat
override init() {
super.init()
prepareLayer(self)
}
func prepareLayer(layer:CAShapeLayer) -> CAShapeLayer {
layer.bounds = CGRect(x: 0, y: 0, width: 200, height: 200)
layer.backgroundColor = UIColor.orangeColor().CGColor
return layer
}
override init(layer: AnyObject) {
super.init(layer: layer)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func display() {
print("\(self.presentationLayer()?.pro)")
//绘图
UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, 0)
let ctx:CGContextRef = UIGraphicsGetCurrentContext()!
CGContextAddRect(ctx, CGRect(x: 0, y: 10, width: ((self.presentationLayer()?.pro) ?? 0), height: 20))
CGContextSetFillColorWithColor(ctx, UIColor.greenColor().CGColor)
CGContextFillPath(ctx)
CGContextStrokePath(ctx)
self.contents = UIGraphicsGetImageFromCurrentImageContext().CGImage
UIGraphicsEndImageContext()
}
override class func needsDisplayForKey(key: String) -> Bool {
print(key)
if "pro" == key {
print("change")
return true
}
return super.needsDisplayForKey(key)
}
override func actionForKey(event: String) -> CAAction? {
if event == "pro" {
print("do some")
let animation:CABasicAnimation = CABasicAnimation(keyPath: event)
animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionEaseInEaseOut)
animation.duration = 3
animation.fromValue = self.pro
return animation
} else {
return super.actionForKey(event)
}
}
}
//
// ViewController.swift
// LayerDrawAnimation
//
// Created by 鲍东升 on 16/5/23.
// Copyright © 2016年 鲍东升. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
//MARK: - PropertyList
var sliderValueChangeBlock:((slider:UISlider)->())?
var buttonClickBlock:((btn:UIButton)->())?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
prepareView(view)
}
func prepareView(view:UIView) -> UIView {
configLayer(view,layer:DSProgressDrawLayer(),done:
{
(layer:DSProgressDrawLayer)->()
in
let btn = UIButton(frame: CGRect(x: layer.frame.origin.x, y: 420, width: 40, height: 40))
btn.backgroundColor = UIColor.brownColor()
self.configButton(
btn
, layer: layer, done: { (btn) in
view.addSubview(btn)
})
}
)
return view
}
func configLayer(view:UIView,layer:DSProgressDrawLayer,done:((layer:DSProgressDrawLayer)->()) ){
view.layer.addSublayer(layer)
layer.frame = CGRect(x: UIScreen.mainScreen().bounds.width/2 - 100, y: 200, width: 200, height: 200)
done(layer: layer)
}
func configButton(button:UIButton,layer:DSProgressDrawLayer,done:(btn:UIButton)->()){
button.addTarget(self, action: #selector(self.actionSetValueButtonClick(_:)), forControlEvents: UIControlEvents.TouchUpInside)
buttonClickBlock = {
(btn:UIButton)->()
in
layer.pro = 180
}
done(btn:button)
}
func actionSetValueButtonClick(button:UIButton){
if (buttonClickBlock != nil) {
buttonClickBlock!(btn: button)
}
}
}