iOS动画案例(1) 仿qq账号信息里的一个动画
受人所托,模仿qq账号信息里的一个动画,感觉挺有意思,也没感觉有多难,就开始做了,结果才发现学的数学知识都还给体育老师了,研究了大半天才做出来。
先看一下动画效果:

用到的知识点:
(1)三角函数
(2)CALayer
(3)CATransaction
(4)UIBezierPath
(5)CAKeyframeAnimation
(6)CAAnimationGroup

如图,这明显是一段圆弧,那么要确定这段一段圆弧的位置,就得确定这段圆弧的圆心和圆心角。我规定圆心在手机屏幕的左顶点,也就是(0,0),圆心角为60°。别问我为什么这么确定,我也是一点点尝试的。我们先设手机屏幕的宽度为 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的圆心角一样,设定为7.5°,那么弧AB、弧BC、弧CD的圆心角设定为相等,分别为(60 - 7.5 * 2)/ 3 = 15°。那么A点的坐标就等于(R * sin7.5,R * cos7.5°);B,C,D点的坐标一样用三角函数求,分别为(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];
// 设置按钮为圆
button.layer.cornerRadius = 25;
button.layer.borderColor = [UIColor greenColor].CGColor;
button.layer.masksToBounds = YES;
button.layer.borderWidth = 2.0f;
[self addSubview:button];
}
// 根据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];
//显式事务默认开启动画效果,kCFBooleanTrue关闭 保证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];
}
//关键帧动画效果
CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 动画轨迹
positionAnimation.path = movePath.CGPath;
// 动画完成之后是否删除动画效果
positionAnimation.removedOnCompletion = NO;
// 设置开始的时间
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];
// 执行完之后保存最新的状态
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];
}];
}
// 根据Index获得顺时针的弧度
- (float)getAnticlockwiseByIndex: (NSInteger)index {
return M_PI * (0.5 - (7.5 + 15 * index) / 180);
}
// 根据Index获得逆时针的弧度
- (float)getClockwiseAngleByIndex: (NSInteger)index {
index = 3 - index;
return M_PI * (30 + 7.5 + 15 * index) / 180;
}
这个动画的难点其实是确定四个按钮的坐标以及圆弧的半径,主要是学的数学都忘的差不多了,还好重新捡起来还算不难。GitHub下载地址,欢迎下载。
iOS动画案例(1) 仿qq账号信息里的一个动画的更多相关文章
- 删除QQ登录界面的QQ账号信息
删除QQ登录界面的QQ账号信息 .. ------------------- ------------------------ -------------------
- iOS天气动画、高仿QQ菜单、放京东APP、高仿微信、推送消息等源码
iOS精选源码 TYCyclePagerView iOS上的一个无限循环轮播图组件 iOS高仿微信完整项目源码 想要更简单的推送消息,看本文就对了 ScrollView嵌套ScrolloView解决方 ...
- jQuery实现的3个基础案例(仿QQ列表分组,二级联动下拉框,模拟员工信息管理系统)
1.仿QQ列表分组 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type&quo ...
- iOS仿QQ侧滑菜单、登录按钮动画、仿斗鱼直播APP、城市选择器、自动布局等源码
iOS精选源码 QQ侧滑菜单,右滑菜单,QQ展开菜单,QQ好友分组 登录按钮 3分钟快捷创建高性能轮播图 ScrollView嵌套ScrolloView(UITableView .UICollecti ...
- iOS动画案例(2) 仿网易新闻标题动画
由于产品的需要,做了一个和网易新闻标题类似的动画效果,现在新闻类的APP都是采用这样的动画效果,来显示更多的内容.先看一下动画效果: 由于这个动画效果在很多场合都有应用,所以我专门封装了一个控 ...
- iOS开发手记-仿QQ音乐播放器动态歌词的实现
最近朋友想做个音乐App,让我帮忙参考下.其中歌词动态滚动的效果,正好我之前也没做过,顺便学习一下,先来个预览效果. 实现思路 歌词常见的就是lrc歌词了,我们这里也是通过解析lrc歌词文件来获取其播 ...
- iOS动画案例(1)
受人所托,做一个类似于qq账号信息里的一个动画,感觉挺有意思,也没感觉有多难,就开始做了,结果才发现学的数学知识都还给体育老师了,研究了大半天才做出来. 先看一下动画效果: 用到的知识 ...
- 高仿QQ Xplan的H5页面
概述 这个h5的主要玩法很简单:地球自转的时候会播放背景音乐(比如海浪声),为了找到这个声音是从哪个地球上哪个地方传来的,需要长按下方的按钮,这时地球会自动转动到目标地点,然后镜头拉近,穿过云层,最后 ...
- 如何制作css3的3d动画——以骰子旋转为例,详解css3动画属性
首先先来看两个用css3实现的炫酷的3d动画效果 1 2 3 4 5 6 你没看错,这个炫酷的效果都是用css3实现的. 下面是动画实现所需要用到的几个css3属性. 1.perspective: ...
随机推荐
- CSU2188: Substring
Description FST 是一名可怜的 ACMer,他很强,但是经常 fst,所以 rating 一直低迷. 但是重点在于,他真的很强!他发明了一种奇特的加密方式,这种加密方式只有 ACMer ...
- centos passwo文件被删除
错误提示 该问题一般由/etc/passwd被清空,删除,移动,改名等造成,需要通过救援模式恢复,操作步骤如下 真实环境已经解决,这里使用vmware模拟.光盘启动,选择救援模式: 语言选择,键盘布局 ...
- PHP条件运算符的“坑”
今天遇到一个关于PHP 嵌套使用条件运算符(ternary expressions)的问题 现象 先来看一段C语言代码(test.c): #include<stdio.h> int mai ...
- c++中的三角函数
c++中想求cos或sin: 1.首先得包含头文件,include<math.h> 2.sin(),cos(),中是弧度数,即若是角度a,则应写成cou<<sin(a*pi/1 ...
- Xcode报referenced from错误的总结
一.库文件丢失 如果提示的文件是库文件,比如说是sdk的文件,有可能是就是丢失,或者没有引用到该工程. 1.点击这个.a库,或者framework,看右边的target里面是否引用到了当前的targe ...
- STM32F407 开发环境搭建 程序下载 个人笔记
详细资料: http://www.openedv.com/thread-13912-1-1.html 需要安装的软件: 1.keil(MDK,必选),用keygen破解 2.CH340驱动,(usb串 ...
- 数据结构-B+树
B+ 树是一种树数据结构,是一个n叉排序树,每个节点通常有多个孩子,一棵B+树包含根节点.内部节点和叶子节点.根节点可能是一个叶子节点,也可能是一个包含两个或两个以上孩子节点的节点. B+ 树通常用于 ...
- 【莫比乌斯反演+树状数组+分块求和】GCD Array
https://www.bnuoj.com/v3/contest_show.php?cid=9149#problem/I [题意] 给定长度为l的一个数组,初始值为0:规定了两种操作: [思路] 找到 ...
- hdu 361B
#include<stdio.h> int a[100100]; int main() { int n,i,k; while(scanf("%d%d",&n,& ...
- 欧拉 路径&&回路
不管 欧拉回路 还是 欧拉路径 无向图或者有向图(删除方向后)要联通 欧拉路径存在的判定条件 1 无向图 度数为奇数的点最多有两个 2 有向图 最多只能有两个点的入度不等于出度 ...