為了達(dá)到好的用戶體驗(yàn)贞远,讓用戶在使用 App 交互的時(shí)候或者等待的時(shí)候視覺上有所沖擊,達(dá)到好的用戶體驗(yàn)笨忌,許多 App 都使用了各式各樣的動畫蓝仲,動畫的實(shí)現(xiàn)也無疑是開發(fā)者所必備的技能之一。
實(shí)現(xiàn) iOS 中動畫我們要了解三個(gè)類官疲,分別是CABasicAnimation袱结、UIBezierPath 與 CAShapeLayer。簡單說一下它們各自的功能途凫,或許我們都知道垢夹,在 UI 界面層中有一個(gè) layer 的層級,這個(gè) layer 展示的是我們界面上的各個(gè)所需要繪制的畫面维费,而我們的 UIView 實(shí)際上就是對 Layer 層的一個(gè)封裝果元,在圖形的展示基礎(chǔ)上增加了交互事件處理。而所有對畫面的操作實(shí)際都是來自 Layer 層犀盟,我們可以設(shè)置圓角(cornerradius)而晒、邊框(borderWidth) 等常用的屬性。所以動畫的繪畫過程實(shí)際上就是展示變換圖形的過程阅畴,這就自然而然的引出了相應(yīng)的 Layer 層倡怎。 CAShapeLayer 繼承自 CALayer,通過 CAShapeLayer 我們可以繪制自己想要的圖形贱枣,而 UIBezierPath 就是我們經(jīng)常說的貝塞爾曲線监署,通過設(shè)置相應(yīng)的參數(shù),我們可以繪制出各式各樣的圖形來纽哥。
說了那么多钠乏,其實(shí) CAShapeLayer 就是一個(gè)畫筆,而 UIBezierPath 實(shí)際上就是要畫筆所要畫的路徑春塌,通過路徑將圖形繪制出來晓避,而 CABasicAnimation 是來控制繪畫速度以及過程。他們?nèi)呔o密相關(guān)摔笤,不可分割够滑。為了便于理解,就以進(jìn)度條的案例來進(jìn)行說明吧吕世!
/**
* 創(chuàng)建 shapLayer
*
* @return layer 實(shí)例
*/
- (CAShapeLayer *)creatCycleView{
CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
//storkeWidth 的寬度的中點(diǎn)位于半徑的軌跡上彰触,繪制的時(shí)候由軌跡路線內(nèi)外擴(kuò)展繪制,
//所以真是繪制長度為真實(shí)長度減去軌跡長度的一半
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2.0, self.frame.size.height/2.0) radius:_radius ? _radius - _cycleWidth * 0.5 : _radius startAngle:0 endAngle:M_PI * 2 clockwise:YES];
layer.lineWidth = _cycleWidth ? _cycleWidth : DEFAULT_STORKE_WIDTH;
layer.path = [path CGPath];
return layer;
}
/**
* 創(chuàng)建圓環(huán)背景
*/
- (void)creatView{
//背景色
self.backgroundColor = [UIColor blackColor];
self.layer.cornerRadius = 6;
CAShapeLayer *backLayer = [self creatCycleView];
backLayer.strokeColor = _progressColor ? [_progressColor CGColor] : [[UIColor colorWithRed:59/255.0 green:59/255.0 blue:59/255.0 alpha:1]CGColor];
backLayer.fillColor = _progressBgColor ? [_progressBgColor CGColor] : [[UIColor clearColor]CGColor];
backShapeLayer = backLayer;
[self.layer addSublayer:backLayer];
CAShapeLayer *foreLayer = [self creatCycleView];
foreLayer.strokeColor = _progressColor ? [_progressColor CGColor] : [[UIColor whiteColor]CGColor];
foreLayer.fillColor = [[UIColor clearColor]CGColor];
foreLayer.strokeStart = 0;
foreLayer.strokeEnd = 0.3;
foreLayer.cornerRadius = 2;
//繪制線條的風(fēng)格
if (self.cycleWidth != self.radius) {
foreLayer.lineCap = kCALineCapRound;
}
foreShapeLayer = foreLayer;
[self.layer addSublayer:foreLayer];
}
通過 setter 方法設(shè)置進(jìn)度條的進(jìn)度:
- (void)setProgressValue:(float)progressValue{
_progressValue = progressValue;
foreShapeLayer.strokeEnd = progressValue;
//加載完成以后的回調(diào)
if (self.loadSuccessBlock && progressValue == 1) {
self.loadSuccessBlock(self);
}
}
而為了讓繪制的過程更為清晰命辖,我們設(shè)置了進(jìn)度條的動畫况毅,代碼如下:
/*
*添加動畫
*/
- (void)drawCycle{
//創(chuàng)建動畫實(shí)例
CABasicAnimation *drawCycleAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
drawCycleAnimation.duration = DRAW_AIMATION_TIME;
drawCycleAnimation.repeatCount = 1;
drawCycleAnimation.delegate = self;
//設(shè)置動畫內(nèi)容的起始值與結(jié)束值
drawCycleAnimation.fromValue = [NSNumber numberWithFloat:0.3];
drawCycleAnimation.toValue = [NSNumber numberWithFloat:1.0];
//動畫時(shí)間速度
drawCycleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[foreShapeLayer addAnimation:drawCycleAnimation forKey:@"drawCircleAnimation"];
//創(chuàng)建縮放動畫
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
basicAnimation.duration = DRAW_AIMATION_TIME;
basicAnimation.repeatCount = 1;
basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
CATransform3D startTransForm = CATransform3DMakeScale(0, 0, 1);
CATransform3D endTransForm = CATransform3DMakeRotation(0, 0, 0, 1);
basicAnimation.fromValue = [NSValue valueWithCATransform3D:startTransForm];
basicAnimation.toValue = [NSValue valueWithCATransform3D:endTransForm];
[foreShapeLayer addAnimation:basicAnimation forKey:@"startTransform"];
}
最終的效果如下:
怎么樣分蓖,是不是很有意思呢?感興趣的童鞋具體 demo 詳見 Git:
https://github.com/lccdl/LCCRepository/tree/master/LCProgressDemo