您好,登錄后才能下訂單哦!
怎么在iOS中實現一個點贊動畫特效?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
動畫的基本使用
動畫的實現基本上是基于對View控件和View的layer屬性進行操作,對視圖進行移動,尺寸變換,透明度變換,旋轉等一系列操作。
關鍵幀動畫:
動畫的實現可以分為兩個部分,一部分是規定動畫的變化內容,比如view需要把scale從0變化到1,這個數字是相對值,即從尺寸為0變化到正常尺寸。另一個部分是規定動畫的漸變時間。這樣就實現了view在規定時間完成指定變化了,這個變化的過程也可以通過參數設置為非均勻變化的。上面的示例是關鍵幀動畫的實現,實現的方式是把動畫劃分為幾個部分,“第一幀”做一件事,“第二幀”再做另外一件事,這就使得變化連續且可控。Duration參數確定了時間,delay確定了延時多久執行,options確定了關鍵幀動畫布局子控件。completion的參數是一個block,其中的內容是在內容執行結束后才調用。這里做了3幀,前兩幀做了尺寸變為3倍然后恢復,后一幀使得其隱藏。結束后會調用block使其移除。
[UIView animateKeyframesWithDuration:self.animationDurtion * 4 delay:0.0 options:UIViewKeyframeAnimationOptionLayoutSubviews animations:^{ /*參數1:關鍵幀開始時間 參數2:關鍵幀占用時間比例 參數3:到達該關鍵幀時的屬性值 */ [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.5 * self.animationDurtion animations:^{ giveLikeView.transform = CGAffineTransformMakeScale(3, 3);; }]; [UIView addKeyframeWithRelativeStartTime:0.5 * self.animationDurtion relativeDuration:0.5 * self.animationDurtion animations:^{ giveLikeView.transform = CGAffineTransformIdentity; }]; [UIView addKeyframeWithRelativeStartTime:self.animationDurtion relativeDuration:self.animationDurtion * 3 animations:^{ giveLikeView.alpha = 0; }]; } completion:^(BOOL finished) { giveLikeView.hidden = YES; [giveLikeView removeFromSuperview]; }];
CAShapeLayer和UIBezierPath:
當不滿足于view的變化,還需要在view的表面繪制一些圖案,就要對layer進行操作,layer可以理解為是view的表面,每個view都有layer參數。UIBezierPath是貝塞爾曲線,它用于設置繪圖的路徑,沒有了它,layer的繪制也是無效的,因為沒有邊界呀。
如下代碼繪制了一個圓形的曲線,設置了它的中心,半徑,起始終止角這些屬性。
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(giveLikeView.bounds.size.width/2, giveLikeView.bounds.size.height/2) radius:giveLikeView.bounds.size.width startAngle:-1.57 endAngle:-1.57+3.14*2 clockwise:YES]; circleLayer.path = bezierPath.CGPath; [self.layer addSublayer:circleLayer];
在最后我們可以看到:circleLayer.path = bezierPath.CGPath; [self.layer addSublayer:circleLayer];
它的作用是設置layer的路徑,并把layer添加到view的表面。下面來看看layer的配置。
創建一個layer后設置它的frame和顏色以及邊界,線寬這些屬性。
CAShapeLayer *circleLayer = [[CAShapeLayer alloc] init]; circleLayer.frame = giveLikeView.frame; circleLayer.fillColor = [UIColor clearColor].CGColor; circleLayer.strokeColor = [UIColor redColor].CGColor; circleLayer.lineWidth = 1;
幾處聯系:把貝塞爾曲線和layer聯系起來,把layer和view的layer聯系起來。
為layer加動畫(動畫組):
先創建動畫組CAAnimationGroup,它可以容納若干動畫,然后創建若干CABasicAnimation基礎動畫。分別設置屬性,動畫組需要涉及的屬性有時間功能,kCAMediaTimingFunctionEaseIn表示逐漸加快,另外還有設置持續時間,設置kCAFillModeForwards表示動畫在結束后會保持,removedOnCompletion = NO表示最后不移除。在基礎動畫的設置中,一般設置在動畫組中的起始時間和持續時間,還有參數的變化。最后的 group.animations = @[scaleAnimtion,widthStartAnimtion,widthEndAnimtion];[circleLayer addAnimation:group forKey:nil];
兩句表示在動畫組中添加動畫然后為layer添加動畫組,這樣layer就有動畫特效了。
//動畫 CAAnimationGroup *group = [CAAnimationGroup animation]; group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; NSTimeInterval groupInterval = self.animationDurtion * 0.8; group.duration = groupInterval; group.fillMode = kCAFillModeForwards; group.removedOnCompletion = NO; CABasicAnimation * scaleAnimtion = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; scaleAnimtion.beginTime = 0; scaleAnimtion.duration = groupInterval * 0.8; scaleAnimtion.fromValue = @(0); scaleAnimtion.toValue = @(1); CABasicAnimation * widthStartAnimtion = [CABasicAnimation animationWithKeyPath:@"lineWidth"]; widthStartAnimtion.beginTime = 0; widthStartAnimtion.duration = groupInterval * 0.8; widthStartAnimtion.fromValue = @(1); widthStartAnimtion.toValue = @(2); CABasicAnimation * widthEndAnimtion = [CABasicAnimation animationWithKeyPath:@"lineWidth"]; widthEndAnimtion.beginTime = groupInterval * 0.8; widthEndAnimtion.duration = groupInterval * 0.2; widthEndAnimtion.fromValue = @(2); widthEndAnimtion.toValue = @(0); group.animations = @[scaleAnimtion,widthStartAnimtion,widthEndAnimtion]; [circleLayer addAnimation:group forKey:nil];
點贊動畫的實現原理
下面來介紹demo的實現原理。
controller的尺寸設置為全屏,在其上方也覆蓋一個全屏的view,再在view上添加點擊事件(手勢)。
- (void)addGesture { UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(creatOneHeart:)]; [self addGestureRecognizer:tap]; }
下面看看點擊后調用的方法:
這里每次點擊都會獲取點擊的位置然后去初始化一個愛心,這是異步任務,放在主隊列中執行。
- (void)creatOneHeart:(UITapGestureRecognizer *)sender { CGPoint point = [sender locationInView:self]; dispatch_async(dispatch_get_main_queue(),^{ [self initOneNewHeart:point]; }); }
這段代碼創建了視圖對象,這里自然用到了事先創建好的心形圖片。這里把創建的imageview存到隊列,顯示到view上,最后調用likeAction:方法執行動畫。
- (UIImageView *)createGiveLikeView { UIImageView *giveLikeView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; giveLikeView.backgroundColor = [UIColor clearColor]; UIImage *image = [UIImage imageNamed:@"icon_home_like_after"]; giveLikeView.userInteractionEnabled = YES; giveLikeView.tag = GiveType; giveLikeView.image = image; giveLikeView.hidden = NO; _giveLikeView = giveLikeView; return _giveLikeView; } - (void)initOneNewHeart:(CGPoint)point { UIImageView *giveLikeView = [self createGiveLikeView]; giveLikeView.center = point; [self.array addObject:giveLikeView]; [self addSubview:giveLikeView]; [self likeAction:giveLikeView]; }
我們看看giveLikeAction:這個方法,它包括執行心形的變化動畫和繪制六個輻射的三角形動畫,還有輻散的圓的動畫。
- (void)likeAction:(UIImageView *)giveLikeView { [self giveLikeAction:giveLikeView]; } - (void)giveLikeAction:(UIImageView *)giveLikeView { [self animtionChangeLikeType:giveLikeView]; [self createTrigonsAnimtion:giveLikeView]; [self createCircleAnimation:giveLikeView]; }
接下來直接看看輻散的三角形的動畫(愛心的變化動畫在上面已經涉及到了):
這段代碼跑了6個循環,做了6個三角形,它們分別有動畫效果。
shape.transform = CATransform3DMakeRotation(3.14 / 3 * i, 0, 0, 1);實現了旋轉。
[giveLikeView.layer addSublayer:shape];執行layer的添加。
因為在循環中,每個layer都有獨立的動畫,動畫組實現的效果是三角形從小變大,最后變成一條直線并消失。
下面的兩行代碼用到了__bridge,它的作用是實現類型的轉換,這里把CGPathRef類型“橋接”轉化為了id類型,如果沒有它,會報錯。
pathAnimation.fromValue = (__bridge id)startPath.CGPath;
pathAnimation.toValue = (__bridge id)endPath.CGPath;
- (void)createTrigonsAnimtion:(UIImageView *)giveLikeView { for(int i=0;i<6;i++) { //創建一個layer并設置位置和填充色 CAShapeLayer *shape = [[CAShapeLayer alloc] init]; shape.position = CGPointMake(giveLikeView.bounds.size.width/2, giveLikeView.bounds.size.height/2); shape.fillColor = [UIColor redColor].CGColor; //設置貝塞爾曲線,執行路徑 UIBezierPath *startPath = [[UIBezierPath alloc] init]; [startPath moveToPoint:CGPointMake(-2, 30)]; [startPath addLineToPoint:CGPointMake(2, 30)]; [startPath addLineToPoint:CGPointMake(0, 0)]; [startPath addLineToPoint:CGPointMake(-2, 30)]; shape.path = startPath.CGPath; //旋轉 shape.transform = CATransform3DMakeRotation(3.14 / 3 * i, 0, 0, 1); [giveLikeView.layer addSublayer:shape]; //動畫組 CAAnimationGroup *groupAnimation = [CAAnimationGroup animation]; groupAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; groupAnimation.duration = self.animationDurtion; groupAnimation.fillMode = kCAFillModeForwards; groupAnimation.removedOnCompletion = NO; //基礎動畫1 CABasicAnimation *scaleAnimtion = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; //縮放時間占20% scaleAnimtion.duration = self.animationDurtion * 0.2; scaleAnimtion.fromValue = @(0); scaleAnimtion.toValue = @(1); //繪制三角形結束 一條直線 UIBezierPath *endPath = [UIBezierPath bezierPath]; [endPath moveToPoint:CGPointMake(-2, 30)]; [endPath addLineToPoint:CGPointMake(2, 30)]; [endPath addLineToPoint:CGPointMake(0, 30)]; //基礎動畫2 CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"path"]; pathAnimation.beginTime = self.animationDurtion * 0.2; pathAnimation.duration = self.animationDurtion * 0.8; pathAnimation.fromValue = (__bridge id)startPath.CGPath; pathAnimation.toValue = (__bridge id)endPath.CGPath; groupAnimation.animations = @[scaleAnimtion,pathAnimation]; [shape addAnimation:groupAnimation forKey:nil]; } }
看完上述內容,你們掌握怎么在iOS中實現一個點贊動畫特效的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。