iOS Animation 初窺

論動畫在App中的重要性

引言

  • 一款App是否足夠吸引人一方面是需要豐富的內(nèi)容曙博,另一方面就是要足夠人性化的交互簸搞,還有一些錦上添花的動畫效果,在這里我們討論一下關于Animation的基本實現(xiàn)鸣奔,推薦大家試用FaceBook Paper典尾,里面包含了大量的非原生動畫效果役拴,Paper團隊甚至封裝了相應的開源庫Pop,讓開發(fā)者接入自定義動畫動畫也十分簡便钾埂。動畫的接入要適當河闰,否則用戶面對眼花繚亂的動畫效果科平,都會無從下手。這里有個基于Pop的Demo

  • 當然導入一個復雜的第三方庫可能有些小題大做姜性,所以我們開始從最基本的創(chuàng)作Animation開始

  • 在iOS設備上畫動畫可以分為以下幾種方式瞪慧,最直接的時在UIView上實現(xiàn)動畫,假如實現(xiàn)效果復雜可以在Layer下繪制,此外iOS7還推出了UIDynamicAnimator部念,實現(xiàn)類似游戲中的諸多動畫效果

  • 動畫不是那種天花亂墜式弃酌,而是在一些細節(jié)之處也添加動畫,例如在view之間的約束儡炼,在設備旋轉(zhuǎn)過程中調(diào)整對應動畫妓湘,viewController之間的切換也是可以自定義transitioning

UIView Animations

UIView可以設置動畫的屬性:

屬性 改變
frame & bounds & center 改變View的位置及自身大小
transform 改變縮放scale,旋轉(zhuǎn)角度rotate(3D效果需要用Core Animation)
alpha 改變透明度
backgroundColor 改其背景色

最直接的做法

//基本
UIView.animateWithDuration(0.5, animations: {
  self.yourView.bounds.size.witdh += 70.0
  self.yourView.backgroundColor = UIColor.greenColor()
  self.yourView.alpha = 0.5
})

//View和View之間的過渡
UIView.transitionWithView(containerView, duration: 0.2, options: .TransitionFlipFromLeft, animations: { _ in fromView.removeFromSuperview(); containerView.addSubview(toView) }, completion: nil)

//入門Option,delay,option自由選擇
UIView.animateWithDuration(0.5, delay: 0.4, options: .Repeat, animations:{
    self.yourView.center.x + = 30.0
},completion: nil)


//進階乌询,Spring屬性可以調(diào)整動畫的彈簧效果
UIView.animateWithDuration(1.5, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 0.0, options: nil, animations: {
self.loginButton.bounds.size.width += 80.0 
label的文字可以進行一些過渡效果
}, completion: nil)


//高階榜贴,復雜動畫組合之KeyFrame
UIView.animateKeyframesWithDuration(1.5, delay: 0.0, options: nil, animations: {
//添加KeyFrames,options中可以選擇不同的限制

//1
UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.25, animations: {
self.planeImage.center.x += 80.0
self.planeImage.center.y -= 10.0 
})

//2
UIView.addKeyframeWithRelativeStartTime(0.1, relativeDuration: 0.4) { self.planeImage.transform = CGAffineTransformMakeRotation(CGFloat(-
M_PI_4/2)) }

}, completion: nil)

需要注意的是動畫一旦開始就沒有辦法暫停

Auto Layout

為AutoLayout Aonstraints創(chuàng)建動畫的首要條件就是楣责,你要先用了AutoLayout

動畫的創(chuàng)建方式也類似

//對已有constant作出對應修改操作 or 創(chuàng)建新的contsant
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.4, initialSpringVelocity: 10.0, options: .CurveEaseIn, animations: {
self.view.layoutIfNeeded() }, completion: nil)

其中的layoutIfNeed()十分關鍵,因為這樣UIKit才會知道你修改了layout

Layer Animation

如果說View是高度定制化的給你簡單接口的就像這樣

那CALayer就是這樣

Layer的強大之處是可以設置更多的屬性聂沙,實現(xiàn)3D效果秆麸,添加mask,添加shadow及汉,并且這一切都是建立在直接調(diào)用GPU來達到快速相應沮趣,一切都非常簡便,其實每個View都有Layer坷随,我們在Layer層面做的修改也可以展現(xiàn)在View上

屬性 作用
size & position 改變layer的位置及自身大小
transform 改2D,3D情況下的現(xiàn)實效果
shadow 改變陰影
border 邊框效果
opacity 改其透明度
//記得引入QuartzCore
//基本
let ownStyle = CABasicAnimation(keyPath:"position.x")
ownStyle.fromValue = -view.bounds.size.width/2
ownStyle.toValue = view,bounds.size.width/2
ownStyle.duration = 0.5
yourView.layer.addAnimation(ownStyle, forKey: nil)
//入門房铭,動畫之間存在時間差,我們可以設置fillMode和beginTime來實現(xiàn)特定效果
ownStyle.beginTime = CACurrentMediaTime() + 0.3
ownStyle.fillMode = KCAFillModeRemoved //default
//kCAFillMode主要作用就是控制你動畫在開始和結(jié)束時候的一些效果

//進階 CAAnimation delegate pattern
func animationDidStop & animationDidStart
//與block中的相類似温眉,你也可以利用KVC特性設置相應內(nèi)容
ownStyle.setValue(yourView.layer, forKey:"layer")
ownStyle.setValue("name", forKey:"form")
override func animationStop(anima: CAAnimation!, finished flag: Bool) {
    if let name = ownStyle.valueForKey("form") as? String {
        if name = "form" {
            //add new animation and add it to the layer
        }   
    }
}

//addAnimation中的Key作用缸匪,標示動畫,在恰當?shù)臅r候移除對應動畫类溢,而不是移除動畫效果本身


//高階凌蔬,AnimationGroup
let groupAnimation = CAAnimationGroup()
let oneAnimation = CABasicAnimation(keyPath:"transform.scale")
//blablabla

let twoAnimation = CABasicAnimation(keyPath:"opacity")
//detail set for twoAnimation

//sey timingFunction
groupAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)

//這么只能一起做動畫,這里內(nèi)部沒有時間順序
groupAnimation.animations = [oneAnimation, twoAnimation] 
yourView.layer.addAnimation(groupAnimation, forKey: nil)

//CAKeyFrame,關鍵幀動畫Layer級別效果
let wobble = CAKeyframeAnimation(keyPath: "transform.rotation") wobble.duration = 0.25
wobble.repeatCount = 4

//比View的keyFrame設置方便多了
//values與keyTimes一一對應
wobble.values = [0.0, -M_PI_4/4, 0.0, M_PI_4/4, 0.0]
wobble.keyTimes = [0.0, 0.25, 0.5, 0.75, 1.0] heading.layer.addAnimation(wobble, forKey: nil)

//不過坑爹的是這樣闯冷,比如CGPoint砂心,CGSize,CGRect蛇耀,CATransform3D辩诞,都要解包
let move = CABasicAnimation(keyPath: "position")
move.duration = 1.0
move.fromValue = NSValue(CGPoint:CGPoint(x:100.0, y:100.0))
move.toValue = NSValue(CGPoint:CGPoint(x:200.0, y:200.0))

有木有發(fā)現(xiàn)現(xiàn)在很多App中用戶頭像都是圓形的QQ的是,微博個人主頁纺涤,instagram,Path等等,這里還涉及到好多設計心理學的東西這里給個鏈接圓形頭像為何流行起來--知乎

廢話不多說直接上代碼吧译暂,so easy,簡單說來就是加一個mask,可這好像和動畫沒有什么關系抠忘,聽我慢慢道來

//1
_imageView.frame = CGRectMake(0, 0, iconWH, iconWH);
_imageView.layer.cornerRadius = _imageView.frame.size.width / 2;
_imageView.clipsToBounds = YES;
_imageView.layer.borderWidth = 2.0f;
_imageView.layer.borderColor = [UIColor whiteColor].CGColor;

//2
 let photoLayer = CALayer()
 let circleLayer = CAShapeLayer()
 let maskLayer = CAShapeLayer()

  override func didMoveToWindow() {
    layer.addSublayer(photoLayer)
    photoLayer.mask = maskLayer
    layer.addSublayer(circleLayer)
    addSubview(label)
  }

  //設置image的Frame
  photoLayer.frame = CGRect(
      x: (bounds.size.width - image.size.width + lineWidth)/2,
      y: (bounds.size.height - image.size.height - lineWidth)/2,
      width: image.size.width,
      height: image.size.height)
      
  //畫圓,用UIBezierPath
  circleLayer.path = UIBezierPath(ovalInRect: bounds).CGPath
    circleLayer.strokeColor = UIColor.whiteColor().CGColor
    circleLayer.lineWidth = lineWidth
    circleLayer.fillColor = UIColor.clearColor().CGColor
    
  //設置對應的path
    maskLayer.path = circleLayer.path
    maskLayer.position = CGPoint(x: 0.0, y: 10.0)

三者對應關系circleLayer在頂秧秉,maskLayer在中褐桌,photoLayer在底

如果你要實現(xiàn)這個imageView如在撞擊墻壁時,mask產(chǎn)生變化象迎,變成方形荧嵌,這樣一個碰撞式的動畫還是很帶感的

let maskLayer = CAShapeLayer()
imageView.mask = maskLayer

let squarePath = UIBezierPath(rect: bounds).CGPath
let morph = CABasicAnimation(keyPath: "path")
morph.duration = 0.25
morph.fromValue = circleLayer.path
morph.toValue = squarePath

circleLayer.addAnimation(morph, forKey: nil)
maskLayer.addAnimation(morph, forKey: nil)

平面效果是否不夠酷炫,那么來足夠眼前一亮的的

3D效果,這里要扯點美術內(nèi)容了砾淌,透視法

目前的屏幕還是2D平面啦撮,也無法實現(xiàn)所謂全息影像

那么在2D屏幕下的3D就需要透過視覺差來投影出來3D效果

當相機距離很小時候拉伸效果明顯,后者距離很大

    var identity = CATransform3DIdentity
    //m34啥意思汪厨,簡單說來就是你看屏幕視角的遠近赃春,這里是指近大遠小,-1.0/1000啥概念劫乱,這里1000是指相機距離织中,距離越小,近大遠效果越明顯
    identity.m34 = -1.0/1000
    
    //percent在這里是指你在移動當前View時候frame.orgin.x與一固定值如width之間的比例衷戈,這樣view的移動就產(chǎn)生相應不同程度的過渡效果
    let remainingPercent = 1.0 - percent
    let angle = remainingPercent * CGFloat(-M_PI_2)
    //這里是沿著y軸旋轉(zhuǎn)狭吼,這里不得不說一下iOS中坐標系是左手坐標系
    
    let rotationTransform = CATransform3DRotate(identity, angle, 0.0, 1.0, 0.0)
    let translationTransform = CATransform3DMakeTranslation(menuWidth * percent, 0, 0)
    //還有諸如  CATransform3DTranslate,CATransform3DScale相關設置都可以嘗試
    menuButton.imageView.layer.transform =  CATransform3DConcat(rotationTransform, translationTransform)

左邊是左手坐標系殖妇,右邊是我們慣用的右手坐標系刁笙,兩者區(qū)別在于z軸的方向,iOS是左手系

view的轉(zhuǎn)動效果如下谦趣,x,y,z軸你可以設置根據(jù)相應的軸產(chǎn)生不同動畫以及組合動畫


致此疲吸,iOS的動畫初窺到此為止,發(fā)現(xiàn)具體到動畫中矩陣轉(zhuǎn)換還是有點搞不清楚前鹅,后續(xù)還會有更多關于iOS Animation的內(nèi)容摘悴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市舰绘,隨后出現(xiàn)的幾起案子烦租,更是在濱河造成了極大的恐慌,老刑警劉巖除盏,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叉橱,死亡現(xiàn)場離奇詭異,居然都是意外死亡者蠕,警方通過查閱死者的電腦和手機窃祝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來踱侣,“玉大人粪小,你說我怎么就攤上這事大磺。” “怎么了探膊?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵杠愧,是天一觀的道長。 經(jīng)常有香客問我逞壁,道長流济,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任腌闯,我火速辦了婚禮绳瘟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘姿骏。我一直安慰自己糖声,他們只是感情好,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布分瘦。 她就那樣靜靜地躺著蘸泻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嘲玫。 梳的紋絲不亂的頭發(fā)上悦施,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音趁冈,去河邊找鬼歼争。 笑死拜马,一個胖子當著我的面吹牛渗勘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俩莽,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼旺坠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了扮超?” 一聲冷哼從身側(cè)響起取刃,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎出刷,沒想到半個月后璧疗,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡馁龟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年崩侠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坷檩。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡却音,死狀恐怖改抡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情系瓢,我是刑警寧澤阿纤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站夷陋,受9級特大地震影響欠拾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肌稻,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一清蚀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧爹谭,春花似錦枷邪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至腹泌,卻和暖如春嘶卧,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凉袱。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工芥吟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人专甩。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓钟鸵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涤躲。 傳聞我的和親對象是個殘疾皇子棺耍,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

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

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復雜种樱,今天將帶大家一窺ios動畫全貌蒙袍。在這里你可以看...
    每天刷兩次牙閱讀 8,469評論 6 30
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫、插件嫩挤、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,059評論 4 62
  • 在iOS中隨處都可以看到絢麗的動畫效果害幅,實現(xiàn)這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌岂昭。在這里你可以看...
    F麥子閱讀 5,101評論 5 13
  • 今天打算執(zhí)行為期一個月的進餐減半計劃。今天的日期也比較好記叼风,2 月 22 號取董,拿來做二分之一的意思,不是兩倍的意思...
    小王加油啊閱讀 206評論 0 0
  • 十里桃花吐芬芳 一朵不慎落面上 驚喜怡然入花廊 月牙兒不禁掛眉梢 芳草落花吻纖足 融融春光潤鬢霜 吾意誤認是晨曉 ...
    恬淡人生888閱讀 127評論 0 1