動畫(一)

詳細(xì)分析frame臊岸、bounds嘱能、center、position查蓉、anchorPoint
iOS開發(fā)系列--讓你的應(yīng)用“動”起來
老司機(jī)帶你走進(jìn)Core Animation 之CAAnimation
iOS CoreAnimation 隱式動畫

class ViewController: UIViewController {
    var cv: CusView!
    var bgLayer: CALayer!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let btn = UIButton(frame: CGRect(x: 50, y: 100, width: 200, height: 50 ))
        cv = CusView(frame: CGRect(x: 50  , y: btn.frame.maxY+20, width: 200, height: 200))
        cv.backgroundColor = .green
        self.view.addSubview(cv)
        bgLayer = CALayer()
        bgLayer.frame = cv.bounds
        cv.layer.addSublayer(bgLayer)
        
        
        btn.setTitle("changeColor", for: .normal)
        btn.backgroundColor = UIColor.gray
       
        view.addSubview(btn)
        btn.addTarget(self, action: #selector(clicked), for: .touchUpInside)

    }

    @objc func clicked(sender: UIButton) {

       case3()
    }
    func case1() {
        //CATransaction 只對layer生效赫段,view無效
        CATransaction.begin()
        //        CATransaction.setDisableActions(true)
        CATransaction.setAnimationDuration(10)
        cv.layer.backgroundColor = UIColor.red.cgColor
        
        CATransaction.commit()
        CATransaction.setCompletionBlock {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+3) {
                self.cv.layer.backgroundColor = UIColor.green.cgColor
            }
        }
    }
    func case2() {
        //CATransaction 只對layer生效呀打,view無效
        CATransaction.begin()
        //        CATransaction.setDisableActions(true)
        CATransaction.setAnimationDuration(10)
        bgLayer.backgroundColor = UIColor.red.cgColor
        
        CATransaction.commit()
        CATransaction.setCompletionBlock {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+3) {
                self.bgLayer.backgroundColor = UIColor.green.cgColor
            }
        }
    }
    func case3() {
        let ani = CABasicAnimation(keyPath: "backgroundColor")
        ani.duration = 3
        ani.toValue = UIColor.red.cgColor
        ani.timeOffset = 3
        ani.isRemovedOnCompletion = false
        ani.fillMode = CAMediaTimingFillMode.forwards
        cv.layer.add(ani, forKey: "colorAnimate")
      
    }
}

class CusView: UIView,CAAction {
    func run(forKey event: String, object anObject: Any, arguments dict: [AnyHashable : Any]?) {
        print("event:\(event)  object:\(anObject)  dict:\(dict)")

        let temp: CALayer? = anObject as? CALayer
        guard let layer = temp else { return }
        if event == "position" && layer.position == CGPoint(x: 150,y: 270) {
            let ca = CABasicAnimation(keyPath: "position")
            ca.duration = 3
            ca.toValue = CGPoint(x: self.superview?.bounds.width ?? 0/2, y: self.superview?.bounds.height ?? 0/2)
            ca.fillMode = CAMediaTimingFillMode.forwards
            ca.isRemovedOnCompletion = false
            self.layer.add(ca, forKey: "move")
        }
    }
    

    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */
    override func action(for layer: CALayer, forKey event: String) -> CAAction? {
        let action = super.action(for: layer, forKey: event)
//        print("key:\(event)")
        
        return action
    }

}

case1通過CATransaction 顯示調(diào)用提交動畫并沒有生效(把v.layer.backgroundColor換成cv.backgroundColor)和case2卻生效了,why糯笙?贬丛??
通過customview override func action(for layer: CALayer, forKey event: String) -> CAAction? 斷點(diǎn)给涕,可以發(fā)現(xiàn)無論是修改view本身還是view持有的layer 都會走這個方法豺憔,并且返回了一個action為nil额获,so,并不會產(chǎn)生動畫特效恭应,UIview本身禁用了隱式動畫的原因也是這個抄邀。UIView動畫可以通過open class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil)類似系統(tǒng)api去實(shí)現(xiàn)。也可以在這個接口的動畫block里面和外面調(diào)用 action(for layer:CALayer ,forKey:String)看看得到的CAAction是否為nil昼榛。
而case2 是一個自定義的layer添加到view的layer上境肾,這個自定義layer并沒有把自己的CALayerDelegate交給任何對象,so胆屿,這個layer執(zhí)行可以動畫的屬性時候不會走override func action(for layer: CALayer, forKey event: String) -> CAAction? 這個代理方法奥喻,而是去CALayer的Actions或者style字典搜索,然后去調(diào)用open class func defaultAction(forKey event: String) -> CAAction?非迹,上面是一層層遞進(jìn)的如果返回結(jié)果為NSNull或者nil就會到下一步衫嵌,如果最后一步仍返回nil,則無動畫效果彻秆。
前面兩個case,雖然我們通過代碼去介入了结闸,但具體動畫怎么執(zhí)行的還是有系統(tǒng)完成的唇兑,這種動畫叫隱式動畫,而case3是通過代碼的方式添加具體動畫行為桦锄,這種方式叫顯示動畫

150628403626215.png

如圖中CAAnimation通過其子類添加動畫的方式都是顯示動畫扎附,這個圖還差了一個CAAction協(xié)議,具體百度吧
前面提到了UIView是禁止隱式動畫的结耀,但是某些系統(tǒng)接口本身就帶有動畫特效留夜,比如UITableView 的 reloadDate或者open func reloadRows(at indexPaths: [IndexPath], with animation: UITableView.RowAnimation),如果想取消動畫效果怎么辦?可通過另外一個接口解決問題UIView.performWithoutAnimation { }
另外在CusView中遵循了CAAction代理并實(shí)現(xiàn)了其代理方法图甜,這個是為了測試給UIView被禁用的隱式動畫屬性添加動畫行為碍粥,也就是實(shí)現(xiàn)CAAction去添加動畫,再把這個CAAction實(shí)例交給CALayerDelegate 的這個接口*/
override func action(for layer: CALayer, forKey event: String) -> CAAction?具體我怎么搞黑毅,我也沒搞好嚼摩,哈哈,一般不用搞這么麻煩矿瘦,直接操作layer就行了枕面,這里只是為了了解這個動畫執(zhí)行的過程
再補(bǔ)充一點(diǎn):CATransaction這個提交動畫的事務(wù)會在runloop中自動創(chuàng)建,在runloop即將休眠前(kCFRunLoopBeforeWaiting)調(diào)用缚去,是通過棧的形式管理潮秘。所以也會導(dǎo)致代碼或者說屬性已經(jīng)改變了,但動畫還沒有執(zhí)行這種時間差易结。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枕荞,一起剝皮案震驚了整個濱河市柜候,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌买猖,老刑警劉巖改橘,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異玉控,居然都是意外死亡飞主,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門高诺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碌识,“玉大人,你說我怎么就攤上這事虱而》げ停” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵牡拇,是天一觀的道長魁瞪。 經(jīng)常有香客問我,道長惠呼,這世上最難降的妖魔是什么导俘? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮剔蹋,結(jié)果婚禮上旅薄,老公的妹妹穿的比我還像新娘。我一直安慰自己泣崩,他們只是感情好少梁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矫付,像睡著了一般凯沪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上技即,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天著洼,我揣著相機(jī)與錄音,去河邊找鬼而叼。 笑死身笤,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的葵陵。 我是一名探鬼主播液荸,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脱篙!你這毒婦竟也來了娇钱?” 一聲冷哼從身側(cè)響起伤柄,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎文搂,沒想到半個月后适刀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡煤蹭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年笔喉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硝皂。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡常挚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出稽物,到底是詐尸還是另有隱情奄毡,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布贝或,位于F島的核電站吼过,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏咪奖。R本人自食惡果不足惜那先,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赡艰。 院中可真熱鬧,春花似錦斤葱、人聲如沸慷垮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽料身。三九已至,卻和暖如春衩茸,著一層夾襖步出監(jiān)牢的瞬間芹血,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工楞慈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留幔烛,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓囊蓝,卻偏偏與公主長得像饿悬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子聚霜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容