iOS炫酷動畫(一)

最近,看到一個很炫酷的動畫。效果是這樣的。在進行切換的時候,會有一個線跑的動畫。于是乎參照著用swift做了一份。沒有封裝成tabbar,只是做了個動畫效果。https://github.com/silan-liu/SLAnimation

1.gif
動畫拆解

乍一看,點擊另外一個item后,紅色的圓圈可以想像成是一個鐵絲圍成的圈,圈被逐漸解開,然后有根水平線在拉著圓圈走向目的地,在到達目的地的途中,又開始繞成一個圈,尾巴逐漸縮短,最終成為圓。(實在是不知道怎么描述了╮(╯▽╰)╭)

我們注意到,每個選中的item是有個紅色圓圈包圍的,圖標也是選中狀態(tài),切換選中狀態(tài),紅色圈會消失,圖標變成未選中。

其實剛開始看到,這種圓解開,又繞成圓的走法,想到了strokeStart和strokenEnd。只是沒明白,是怎樣的軌跡可以做成這種效果。

動手實現(xiàn)

1、首先寫個ItemView,即每個單獨的view。因為每個item都可以點擊,我們可以直接繼承自UIButton。有2個imageview,選中和未選中狀態(tài)的,在選中時,隱藏normalImageView。未選中時,將其顯示出來。

class SLAnimationItemView: UIButton {

    let margin: CGFloat = 8.0

    private var innerSelectStatus: Bool = false
    
    private var normalImageView: UIImageView?
    private var selectedImageView: UIImageView?
    
    var outCircleLayer: CAShapeLayer?
    
    // MARK: show/hide
    func showOutLineLayer(show: Bool) {

    }
}

2、寫動畫。其實它的效果,在點擊的時候,circle隱藏,在動畫結(jié)束之后,選中的item將circle顯示出來。動畫軌跡是這樣:0_0,兩個item分別有個圈,中間連著一根線。

2@2x.png

這種軌跡可以用貝塞爾曲線來畫,主要代碼如下。注意的是點擊的item位置問題,如果點擊的是原item左邊的,是順時針畫。反之,逆時針。

func animationBezierPath() -> UIBezierPath {

        let bezierPath = UIBezierPath()
        // true--順時針
        let clockwise: Bool = fromPoint.x > toPoint.x

        // first circle
        bezierPath.addArcWithCenter(fromPoint, radius: radius, startAngle: CGFloat(M_PI_2), endAngle: CGFloat(M_PI), clockwise: clockwise)
        bezierPath.addArcWithCenter(fromPoint, radius: radius, startAngle: CGFloat(M_PI), endAngle: CGFloat(M_PI_2), clockwise: clockwise)

        // line
        bezierPath.moveToPoint(CGPointMake(fromPoint.x, fromPoint.y + radius))
        bezierPath.addLineToPoint(CGPointMake(toPoint.x, toPoint.y + radius))

        // second circle
        bezierPath.addArcWithCenter(toPoint, radius: radius, startAngle: CGFloat(M_PI_2), endAngle: CGFloat(M_PI), clockwise: clockwise)
        bezierPath.addArcWithCenter(toPoint, radius: radius, startAngle: CGFloat(M_PI), endAngle: CGFloat(M_PI_2), clockwise: clockwise)

        return bezierPath
    }

因為最終線不見了,所以是strokeStart到了選中item的切點位置就結(jié)束了,strokeEnd到了路徑最終點。動畫代碼如下:

func createAnimation(completion: () -> ()) -> CAAnimationGroup {

        let duration: CFTimeInterval = 0.75
        let strokeStartAnimation = CABasicAnimation(keyPath: "strokeStart")

        strokeStartAnimation.duration = duration
        strokeStartAnimation.fromValue = 0
        strokeStartAnimation.toValue = distance() / totalLength()

        let strokeEndAnimation = CABasicAnimation(keyPath: "strokeEnd")

        strokeEndAnimation.duration = duration
        strokeEndAnimation.fromValue = 0.1
        strokeEndAnimation.toValue = 1

        let animationGroup: CAAnimationGroup = CAAnimationGroup()

        animationGroup.duration = duration;
        animationGroup.animations = [strokeStartAnimation, strokeEndAnimation]
        animationGroup.delegate = self
        animationGroup.fillMode = kCAFillModeBoth;
        animationGroup.removedOnCompletion = false

        return animationGroup
    }

動畫結(jié)束之后,需要將動畫layer隱藏掉或者移除掉。這里為了防止頻繁的創(chuàng)建layer,暫且只隱藏起來。

問題

這里碰到了一個問題,就是在顯示circle時,當時我不想頻繁創(chuàng)建和移除circle,直接設(shè)置opacity來操作隱藏顯示的話,會感覺閃一下。而采用重新創(chuàng)建的方式,就不會。后來想了好久,才發(fā)現(xiàn)是CALayer隱式動畫的問題,操作CALayer的屬性,會默認有個0.25s的動畫。所以將隱式動畫禁用后,一切完美了。

UIView.animateWithDuration(0.3, animations: {
            
            CATransaction.begin()
            CATransaction.setDisableActions(true)
            self.outCircleLayer.opacity = show ? 1 : 0
            
            CATransaction.commit()
            
            self.normalImageView?.alpha = show ? 0 : 1

            }) { (flag) in
        }

最后

其實看了源碼之后還是覺得動畫不是太復(fù)雜。很多炫酷的動畫都是屬性的組合動畫,或者是Bezier曲線變換什么的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,686評論 6 30
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,724評論 25 709
  • 不知不覺中我成為一名驢友已經(jīng)兩年多,參加驢行不計其數(shù)。時間長了,居然上了癮,一段時間不驢行,竟然心里如蟲撓般難受...
    玲瓏簡書閱讀 1,110評論 0 3
  • 具體構(gòu)成描述 網(wǎng)絡(luò)(network)由若干結(jié)點(node)和連接這些結(jié)點的鏈路(link)組成。互聯(lián)網(wǎng)是 "網(wǎng)絡(luò)的...
    hwk603閱讀 546評論 0 3
  • 時間:20170805星期六早6:00~6:50 地點:云之家易效能十一堂課實踐班 參與人員:教練,班委,學員等 ...
    梅丫頭閱讀 670評論 0 3

友情鏈接更多精彩內(nèi)容