前言
在dribbble看到一個Switch動畫效果就手癢想實現(xiàn)奏候,下面就是我實現(xiàn)的思路。
源代碼
GitHub地址:VGGradientSwitch
如果覺得不錯段誊,歡迎點star棉钧。
設(shè)計圖
來自dribbble上的設(shè)計作者 Nick Buturishvili

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