實現一個iOS漸變背景動畫效果的Switch

xbdq1824 7年前發布 | 14K 次閱讀 iOS開發 移動開發

前言

在dribbble看到一個Switch動畫效果就手癢想實現,下面就是我實現的思路。

源代碼

GitHub地址: VGGradientSwitch

如果覺得不錯,歡迎點star。

設計圖

來自dribbble上的設計作者 Nick Buturishvili

image

效果圖

image

思路

  • 首先解刨一下設計圖
  1. 外觀和iOS原生UISwitch相同
  2. 觀察動圖發現Switch背景圖為漸變色,這也是這個開關設計的一大亮點
  3. 開關上的紐扣,打開時狀態是一個勾,關閉時是一個叉。
  4. 打開動畫,勾邊線放大移動邊做形變變成點再變換成叉放大后恢復原狀,背景顏色由青色轉換到橘黃色。
  5. 關閉動畫,叉邊先放大移動邊做形變再變成勾放大后恢復原狀,背景顏色由橘黃色轉換到青色

實現

  • 漸變背景圖是通過 CAGradientLayer 實現。通過設計圖取色拿到顏色十六進制(0x08ded6,0x18deb9,0xef9c29,0xe76b39)四個顏色,創建出一個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 設置一個圓角邊框

border.png

  • 勾、點和叉的實現使用到 UIBezierPath 提供path,然后 CAShapeLayer 創建,勾圖形實現代碼如下:
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;</code></pre>

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) {

}];</code></pre> 

gradient_animation.gif

  • 圖形形變動畫主要利用 Core Animation 實現,用到了 CAKeyframeAnimation 、 CABasicAnimation 、 CAAnimationGroup
  • 勾->點動畫 先放大勾后然后做縮小形變成點
  • 點->勾動畫 做形變成勾后做放大
  • 動畫使用了"path"和"transform",形變動畫使用path提供路徑數組,這里提供原本勾的路徑和點的路徑這樣路徑就從勾形變到點

    代碼如下:

  • 放大動畫 使用 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  動畫是否結束
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    }

1.gif

  • 剩下的就是移動這個按鈕然后由點形變成叉,這里就不再說明,可以直接看GitHub代碼,以上就是分解動畫的一些思路和解決辦法,但是動畫要流暢和交互不違和還需要細微調整
  • 有什么代碼和實現的效果建議可以提issue給我,如果喜歡的話點一下 star 哦

 

來自:http://www.jianshu.com/p/2cbbf220ef07

 

 本文由用戶 xbdq1824 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!