實現(xiàn)一個iOS漸變背景動畫效果的Switch

前言

在dribbble看到一個Switch動畫效果就手癢想實現(xiàn)奏候,下面就是我實現(xiàn)的思路。

源代碼

GitHub地址:VGGradientSwitch
如果覺得不錯段誊,歡迎點star棉钧。

設(shè)計圖

來自dribbble上的設(shè)計作者 Nick Buturishvili

image
image

效果圖

image

思路

  • 首先解刨一下設(shè)計圖
  1. 外觀和iOS原生UISwitch相同
  2. 觀察動圖發(fā)現(xiàn)Switch背景圖為漸變色,這也是這個開關(guān)設(shè)計的一大亮點
  3. 開關(guān)上的紐扣疯淫,打開時狀態(tài)是一個勾,關(guān)閉時是一個叉戳玫。
  4. 打開動畫熙掺,勾邊線放大移動邊做形變變成點再變換成叉放大后恢復(fù)原狀,背景顏色由青色轉(zhuǎn)換到橘黃色咕宿。
  5. 關(guān)閉動畫币绩,叉邊先放大移動邊做形變再變成勾放大后恢復(fù)原狀,背景顏色由橘黃色轉(zhuǎn)換到青色

實現(xiàn)

  • 漸變背景圖是通過CAGradientLayer實現(xiàn)府阀。通過設(shè)計圖取色拿到顏色十六進制(0x08ded6,0x18deb9,0xef9c29,0xe76b39)四個顏色,創(chuàng)建出一個switch3倍寬的漸變圖
    如圖:
    gradientBackground.png

代碼如下:

CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.locations = @[@0, @.33, @.63, @1];
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1, 0);
gradientLayer.frame = CGRectMake(0, 0, self.frame.size.width * 3, self.frame.size.height);
  • 邊框使用UIBezierPath設(shè)置一個圓角邊框
border.png
  • 勾缆镣、點和叉的實現(xiàn)使用到UIBezierPath提供path,然后CAShapeLayer創(chuàng)建试浙,勾圖形實現(xiàn)代碼如下:
UIBezierPath *tickPath = [UIBezierPath bezierPath];
[tickPath moveToPoint:CGPointMake(self.frame.size.width/8 * 3, self.frame.size.width/2)];
CGPoint p1 = CGPointMake(self.frame.size.width/2, self.frame.size.width/8 * 5);
[tickPath addLineToPoint:p1];
CGPoint p2 = CGPointMake(self.frame.size.width/8 * 6, self.frame.size.width/8 * 3);
[tickPath addLineToPoint:p2];

CAShapeLayer *layer = [[CAShapeLayer alloc] init];
layer.lineCap = kCALineCapRound;
layer.lineJoin = kCALineJoinRound;
layer.fillColor = [UIColor clearColor].CGColor;
layer.strokeColor = [UIColor whiteColor].CGColor;
layer.lineWidth = 2;
layer.path = tickPath.CGPath;
tick.png
  • 漸變背景顏色的動畫效果董瞻,筆者是將CAGradientLayer添加到一個UIView上然后直接使用,UIView的動畫方法然后做位移,代碼如下:
[UIView animateKeyframesWithDuration:.5 delay:.1 options:UIViewKeyframeAnimationOptionCalculationModePaced animations:^{
        self.gradientView.frame = CGRectMake(-self.frame.size.width *2, 0, self.frame.size.width *3, self.frame.size.height);
    } completion:^(BOOL finished) {
    
    }];
gradient_animation.gif
  • 圖形形變動畫主要利用Core Animation實現(xiàn),用到了CAKeyframeAnimation钠糊、CABasicAnimation挟秤、CAAnimationGroup

  • 勾->點動畫 先放大勾后然后做縮小形變成點

  • 點->勾動畫 做形變成勾后做放大

  • 動畫使用了"path"和"transform",形變動畫使用path提供路徑數(shù)組抄伍,這里提供原本勾的路徑和點的路徑這樣路徑就從勾形變到點
    代碼如下:

  • 放大動畫 使用CABasicAnimation

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
    CATransform3D tr = CATransform3DIdentity;
    tr = CATransform3DTranslate(tr, _rect.size.width/2, _rect.size.height/2, 0);
    tr = CATransform3DScale(tr, 1.2, 1.2, 1);
    tr = CATransform3DTranslate(tr, -_rect.size.width/2, -_rect.size.height/2, 0);
    animation.toValue = [NSValue valueWithCATransform3D:tr];
    animation.autoreverses = YES;
    animation.timingFunction  = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
  • 形變動畫 使用CAKeyframeAnimation具體的使用可以Google一下這里就不多贅言,values傳入的是勾的path和點path
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
    animation.values = values;
    animation.keyTimes = keyTimes;
    animation.beginTime = beginTime;
  • 使用CAAnimationGroup做組合動畫,組合動畫代理方法可以判斷組合動畫是否完成艘刚,<CAAnimationDelegate> 代碼如下:
     // scaleAnimation 放大 lineAnimation線條形變
    CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
    animationGroup.animations = @[scaleAnimation,lineAnimation];
    animationGroup.duration = .5;
    animationGroup.repeatCount = 1;
    animationGroup.removedOnCompletion = NO;
    animationGroup.fillMode = kCAFillModeForwards;
    animationGroup.timingFunction  = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animationGroup.delegate = self;
    
    // CAAnimationDelegate  動畫是否結(jié)束
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    }
1.gif
  • 剩下的就是移動這個按鈕然后由點形變成叉,這里就不再說明截珍,可以直接看GitHub代碼,以上就是分解動畫的一些思路和解決辦法攀甚,但是動畫要流暢和交互不違和還需要細微調(diào)整
  • 有什么代碼和實現(xiàn)的效果建議可以提issue給我,如果喜歡的話點一下 star 哦
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末岗喉,一起剝皮案震驚了整個濱河市秋度,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沈堡,老刑警劉巖静陈,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異诞丽,居然都是意外死亡鲸拥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門僧免,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刑赶,“玉大人,你說我怎么就攤上這事懂衩∽策叮” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵浊洞,是天一觀的道長牵敷。 經(jīng)常有香客問我,道長法希,這世上最難降的妖魔是什么枷餐? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮苫亦,結(jié)果婚禮上毛肋,老公的妹妹穿的比我還像新娘。我一直安慰自己屋剑,他們只是感情好润匙,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著唉匾,像睡著了一般孕讳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天厂财,我揣著相機與錄音油啤,去河邊找鬼。 笑死蟀苛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的逮诲。 我是一名探鬼主播帜平,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼梅鹦!你這毒婦竟也來了裆甩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤齐唆,失蹤者是張志新(化名)和其女友劉穎嗤栓,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箍邮,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡茉帅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锭弊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堪澎。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖味滞,靈堂內(nèi)的尸體忽然破棺而出樱蛤,到底是詐尸還是另有隱情,我是刑警寧澤剑鞍,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布昨凡,位于F島的核電站,受9級特大地震影響蚁署,放射性物質(zhì)發(fā)生泄漏便脊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一形用、第九天 我趴在偏房一處隱蔽的房頂上張望就轧。 院中可真熱鬧,春花似錦田度、人聲如沸妒御。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乎莉。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惋啃,已是汗流浹背哼鬓。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留边灭,地道東北人异希。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像绒瘦,于是被迫代替她去往敵國和親称簿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

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