iOS動畫案例(1) 類似于qq賬號信息里的一個動畫效果
受人所托,做一個類似于qq賬號信息里的一個動畫,感覺挺有意思,也沒感覺有多難,就開始做了,結(jié)果才發(fā)現(xiàn)學(xué)的數(shù)學(xué)知識都還給體育老師了,研究了大半天才做出來。
先看一下動畫效果:

用到的知識點:
(1)三角函數(shù)
(2)CALayer
(3)CATransaction
(4)UIBezierPath
(5)CAKeyframeAnimation
(6)CAAnimationGroup

如圖,這明顯是一段圓弧,那么要確定這段一段圓弧的位置,就得確定這段圓弧的圓心和圓心角。我規(guī)定圓心在手機屏幕的左頂點,也就是(0,0),圓心角為60°。別問我為什么這么確定,我也是一點點嘗試的。我們先設(shè)手機屏幕的寬度為 ScreenWidth,圓弧半徑為R;那么R = ScreenWidth/cos(60°);知道了這些開始畫圓弧。
// 屏幕的寬度 CGFloat width = [UIScreen mainScreen].bounds.size.width; // 圓半徑 float r = 2 * width / sqrt(3); // 畫曲線 UIColor *color = [UIColor redColor]; [color set]; UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0) radius:r startAngle:M_PI / 2 endAngle:M_PI / 6 clockwise:NO]; path.lineWidth = 1.0; path.lineCapStyle = kCGLineCapRound; path.lineJoinStyle = kCGLineJoinRound; [path stroke];
確定了圓心角和半徑就要確定ABCD四個點的坐標了,分別作為四張圖片的圓心。圓弧SA和圓弧DE的圓心角一樣,設(shè)定為7.5°,那么弧AB、弧BC、弧CD的圓心角設(shè)定為相等,分別為(60 - 7.5 * 2)/ 3 = 15°。那么A點的坐標就等于(R * sin7.5,R * cos7.5°);B,C,D點的坐標一樣用三角函數(shù)求,分別為(R * sin22.5,R * cos22.5°),(R * sin37.5,R * cos37.5°),(R * sin52.5,R * cos52.5°)。ABCD其實都是一個按鈕,下面開始放按鈕。
// 放圖片
for (int i = 0; i < 4; i++) {
// 一共四個按鈕 從左到右index分別為0,1,2,3
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = [self getButtonFrame:i];
button.tag = i + 1;
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[button setImage:[UIImage imageNamed:[NSString stringWithFormat:@"%d",i + 1]] forState:UIControlStateNormal];
// 設(shè)置按鈕為圓
button.layer.cornerRadius = 25;
button.layer.borderColor = [UIColor greenColor].CGColor;
button.layer.masksToBounds = YES;
button.layer.borderWidth = 2.0f;
[self addSubview:button];
}
// 根據(jù)Index確定按鈕的坐標
- (CGRect)getButtonFrame: (int) index {
float radians = M_PI * (7.5 + 15 * index) / 180;
CGFloat width = [UIScreen mainScreen].bounds.size.width;
float r = 2 * width / sqrt(3);
CGRect frame = CGRectMake(sin(radians) * r, cos(radians) * r, 50, 50);
frame.origin.x = frame.origin.x - 25;
frame.origin.y = frame.origin.y - 25;
return frame;
}
頭像默認放第一個。
self.head = [[UIImageView alloc] initWithFrame:[self getButtonFrame:0]]; self.head.image = [UIImage imageNamed:@"myHead"]; self.head.layer.borderColor = [UIColor greenColor].CGColor; self.head.layer.masksToBounds = YES; self.head.layer.cornerRadius = 25; self.head.layer.borderWidth = 2.0f; [self addSubview:self.head];
之后按鈕點擊之后,頭像移動到按鈕點擊的地方。
// 按鈕點擊事件
- (void)buttonClick:(UIButton *)button {
// 原來圖片所在按鈕的index
int preIndex = [self getPreviousIndexByFrame:self.head.frame];
int buttonIndex = (int)button.tag - 1;
// 點擊圖片所在按鈕 不做任何操作
if (preIndex == buttonIndex) {
return;
}
CGFloat width = [UIScreen mainScreen].bounds.size.width;
float r = 2 * width / sqrt(3);
//加入動畫效果
CALayer *transitionLayer = [[CALayer alloc] init];
//顯式事務(wù)默認開啟動畫效果,kCFBooleanTrue關(guān)閉 保證begin和commit 之間的屬性修改同時進行
transitionLayer.contents = self.head.layer.contents;
transitionLayer.borderColor = [UIColor greenColor].CGColor;
transitionLayer.masksToBounds = YES;
transitionLayer.cornerRadius = 25;
transitionLayer.borderWidth = 2.0f;
transitionLayer.frame = self.head.frame;
transitionLayer.backgroundColor=[UIColor blueColor].CGColor;
[self.layer addSublayer:transitionLayer];
self.head.hidden = YES;
UIBezierPath *movePath;
//路徑曲線 貝塞爾曲線
if (buttonIndex > preIndex) {
// 向上滑 逆時針
movePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0) radius:r startAngle:[self getAnticlockwiseByIndex:preIndex] endAngle:[self getAnticlockwiseByIndex:buttonIndex] clockwise:NO];
[movePath moveToPoint:transitionLayer.position];
}else {
// 向下滑 順時針
movePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0) radius:r startAngle:[self getClockwiseAngleByIndex:preIndex] endAngle:[self getClockwiseAngleByIndex:buttonIndex] clockwise:YES];
[movePath moveToPoint:transitionLayer.position];
}
//關(guān)鍵幀動畫效果
CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 動畫軌跡
positionAnimation.path = movePath.CGPath;
// 動畫完成之后是否刪除動畫效果
positionAnimation.removedOnCompletion = NO;
// 設(shè)置開始的時間
positionAnimation.beginTime = CACurrentMediaTime();
CGFloat time = 0.7;
if (labs(buttonIndex - preIndex) > 1) {
time = 0.4 * labs(buttonIndex - preIndex);
}
//動畫總時間
positionAnimation.duration = time;
// 動畫的方式 淡入淡出
positionAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
// 執(zhí)行完之后保存最新的狀態(tài)
positionAnimation.fillMode = kCAFillModeForwards;
// 動畫完成之后,是否回到原來的地方
positionAnimation.autoreverses= NO;
[transitionLayer addAnimation:positionAnimation forKey:@"opacity"];
[CATransaction setCompletionBlock:^{
[NSThread sleepForTimeInterval:time];
self.head.hidden = NO;
self.head.frame = button.frame;
[transitionLayer removeFromSuperlayer];
}];
}
// 根據(jù)Index獲得順時針的弧度
- (float)getAnticlockwiseByIndex: (NSInteger)index {
return M_PI * (0.5 - (7.5 + 15 * index) / 180);
}
// 根據(jù)Index獲得逆時針的弧度
- (float)getClockwiseAngleByIndex: (NSInteger)index {
index = 3 - index;
return M_PI * (30 + 7.5 + 15 * index) / 180;
}
這個動畫的難點其實是確定四個按鈕的坐標以及圓弧的半徑,主要是學(xué)的數(shù)學(xué)都忘的差不多了,還好重新?lián)炱饋磉€算不難。
以上所述是小編給大家介紹的iOS動畫案例(1) 類似于qq賬號信息里的一個動畫效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
iOS安全防護系列之ptrace反調(diào)試與匯編調(diào)用系統(tǒng)方法詳解
這篇文章主要給大家介紹了關(guān)于iOS安全防護系列之ptrace反調(diào)試與匯編調(diào)用系統(tǒng)方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧2018-07-07
iOS UICollectionView實現(xiàn)標簽選擇器
這篇文章主要為大家詳細介紹了iOS UICollectionView實現(xiàn)標簽選擇器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-04-04
iPhone/iPad開發(fā)通過LocalNotification實現(xiàn)iOS定時本地推送功能
這篇文章主要介紹了iPhone/iPad開發(fā)之通過LocalNotification實現(xiàn)iOS定時本地推送功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09
iOS輸入框的字數(shù)統(tǒng)計/最大長度限制詳解
在開發(fā)中經(jīng)常會遇到鍵盤輸入的字符長度的限制,下面這篇文章主要給大家介紹了關(guān)于iOS輸入框的字數(shù)統(tǒng)計/最大長度限制的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧2018-06-06

