實(shí)現(xiàn)一個(gè)iOS漸變背景動(dòng)畫(huà)效果的Switch

前言

在dribbble看到一個(gè)Switch動(dòng)畫(huà)效果就手癢想實(shí)現(xiàn),下面就是我實(shí)現(xiàn)的思路。

源代碼

GitHub地址:VGGradientSwitch
如果覺(jué)得不錯(cuò),歡迎點(diǎn)star。

設(shè)計(jì)圖

來(lái)自dribbble上的設(shè)計(jì)作者 Nick Buturishvili

image
image

效果圖

image

思路

  • 首先解刨一下設(shè)計(jì)圖
  1. 外觀和iOS原生UISwitch相同
  2. 觀察動(dòng)圖發(fā)現(xiàn)Switch背景圖為漸變色,這也是這個(gè)開(kāi)關(guān)設(shè)計(jì)的一大亮點(diǎn)
  3. 開(kāi)關(guān)上的紐扣,打開(kāi)時(shí)狀態(tài)是一個(gè)勾,關(guān)閉時(shí)是一個(gè)叉。
  4. 打開(kāi)動(dòng)畫(huà),勾邊線放大移動(dòng)邊做形變變成點(diǎn)再變換成叉放大后恢復(fù)原狀,背景顏色由青色轉(zhuǎn)換到橘黃色。
  5. 關(guān)閉動(dòng)畫(huà),叉邊先放大移動(dòng)邊做形變?cè)僮兂晒捶糯蠛蠡謴?fù)原狀,背景顏色由橘黃色轉(zhuǎn)換到青色

實(shí)現(xiàn)

  • 漸變背景圖是通過(guò)CAGradientLayer實(shí)現(xiàn)。通過(guò)設(shè)計(jì)圖取色拿到顏色十六進(jìn)制(0x08ded6,0x18deb9,0xef9c29,0xe76b39)四個(gè)顏色,創(chuàng)建出一個(gè)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è)置一個(gè)圓角邊框
border.png
  • 勾、點(diǎn)和叉的實(shí)現(xiàn)使用到UIBezierPath提供path,然后CAShapeLayer創(chuàng)建,勾圖形實(shí)現(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
  • 漸變背景顏色的動(dòng)畫(huà)效果,筆者是將CAGradientLayer添加到一個(gè)UIView上然后直接使用,UIView的動(dòng)畫(huà)方法然后做位移,代碼如下:
[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
  • 圖形形變動(dòng)畫(huà)主要利用Core Animation實(shí)現(xiàn),用到了CAKeyframeAnimationCABasicAnimation、CAAnimationGroup

  • 勾->點(diǎn)動(dòng)畫(huà) 先放大勾后然后做縮小形變成點(diǎn)

  • 點(diǎn)->勾動(dòng)畫(huà) 做形變成勾后做放大

  • 動(dòng)畫(huà)使用了"path"和"transform",形變動(dòng)畫(huà)使用path提供路徑數(shù)組,這里提供原本勾的路徑和點(diǎn)的路徑這樣路徑就從勾形變到點(diǎn)
    代碼如下:

  • 放大動(dòng)畫(huà) 使用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];
  • 形變動(dòng)畫(huà) 使用CAKeyframeAnimation具體的使用可以Google一下這里就不多贅言,values傳入的是勾的path和點(diǎn)path
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
    animation.values = values;
    animation.keyTimes = keyTimes;
    animation.beginTime = beginTime;
  • 使用CAAnimationGroup做組合動(dòng)畫(huà),組合動(dòng)畫(huà)代理方法可以判斷組合動(dòng)畫(huà)是否完成,<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  動(dòng)畫(huà)是否結(jié)束
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    }
1.gif
  • 剩下的就是移動(dòng)這個(gè)按鈕然后由點(diǎn)形變成叉,這里就不再說(shuō)明,可以直接看GitHub代碼,以上就是分解動(dòng)畫(huà)的一些思路和解決辦法,但是動(dòng)畫(huà)要流暢和交互不違和還需要細(xì)微調(diào)整
  • 有什么代碼和實(shí)現(xiàn)的效果建議可以提issue給我,如果喜歡的話點(diǎn)一下 star 哦
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,733評(píng)論 25 709
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫(huà)效果,實(shí)現(xiàn)這些動(dòng)畫(huà)的過(guò)程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫(huà)全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,686評(píng)論 6 30
  • 【麗平悟生活】 2017.9.25 夜 洞悉時(shí)代變化的思考: 2017已過(guò)大半,一路走來(lái),在觀察和思考中,我看到很...
    麗平悟生活閱讀 450評(píng)論 0 0
  • 東南西北展翅飛 心中充滿昂揚(yáng)氣 為求生活飛異地 苦難人生誰(shuí)來(lái)比 風(fēng)霜過(guò)后?;匚?但求平安回家里
    芬芳花草的香味閱讀 449評(píng)論 2 0
  • 概念梳理以及如何做到屏幕適配CSDN博客Blog dp 這個(gè)單位是安卓發(fā)明的么?為什么 px=dp*(dpi/16...
    白如白牙閱讀 326評(píng)論 0 0

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