iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果
一、转盘(裁剪图片、自定义按钮、旋转)

1、裁剪图片
将一张大图片裁剪为多张

// CGImageCreateWithImageInRect:用来裁剪图片
// image:需要裁剪的图片
// rect:裁剪图片的尺寸,传递是像素
CGImageRef norImage = CGImageCreateWithImageInRect(norBigImage.CGImage, clipRect);
2、每次点击按钮立马变为选中状态,并且取消上次的按钮的选中状态
只要用个成员变量记录下状态就 ok
当然还要重写- (void)setHighlighted:(BOOL)highlighted

// 点击按钮的时候调用
- (void)btnClick:(UIButton *)btn
{
// 1.取消上一次按钮选中状态
_selectedBtn.selected = NO; // 2.让当前按钮选中
btn.selected = YES; // 3.记录当前选中的按钮
_selectedBtn = btn;
}
3、自定义按钮
由于裁剪出来的照片太大,导致达不到理想效果,这时需要对图片做一些调整就可以自定义按钮
为什么要自定义按钮:因为我想要修改按钮的内部子控件的frame
以后只要想修改系统自带控件内部子控件的位置,第一反应就是自定义控件
#import "WheelButton.h"
@implementation WheelButton
// 想要修改按钮内部UIImageView
// contentRect:按钮的bounds
// 什么时候调用:每次使用按钮内部UIImageView的时候就会调用这个方法判断下尺寸
// 作用:设置按钮内部UIImageView的frame
- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
CGFloat imageW = ;
CGFloat imageH = ;
CGFloat imageX = (contentRect.size.width - imageW) * 0.5;
CGFloat imageY = ; return CGRectMake(imageX, imageY, imageW, imageH);
}
// 设置按钮内部UILabel的frame
//- (CGRect)titleRectForContentRect:(CGRect)contentRect // 重写按钮的高亮的方法
// 目的:取消高亮状态时候做的事情,比如:让按钮暂时达不到选中状态
- (void)setHighlighted:(BOOL)highlighted
{
// [super setHighlighted:highlighted];
}
@end
4、旋转
// 点击开始选号的时候调用
- (IBAction)startPickerNum:(id)sender { // 快速的旋转,不需要与用户交互
CABasicAnimation *anim = [CABasicAnimation animation]; anim.keyPath = @"transform.rotation"; anim.toValue = @(M_PI * * );
anim.duration = 0.5; anim.delegate = self; [_centerView.layer addAnimation:anim forKey:nil];
}
由于用这种方式做出来的动画实际上位置并没有改变,呈现出来的只是一个假象而已,所以在点击按钮时,并不能准确的选中按钮
为了解决这个问题
添加一个定时器
@property (nonatomic, strong) CADisplayLink *link;
- (CADisplayLink *)link
{
if (_link == nil) {
_link = [CADisplayLink displayLinkWithTarget:self selector:@selector(timeChange)];
// 添加主运行循环
[_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}
return _link;
} // 1秒调用60次, 假设1秒转45° 45 / 60.0
- (void)timeChange
{
_centerView.transform = CGAffineTransformRotate(_centerView.transform, / 60.0 * M_PI / 180.0);
}
只要开启定时器那么转盘就在慢慢的转动(假设1秒转45°)
// 开始旋转按钮
- (void)startRotation
{
// 需要与用户交互,真实旋转
// 是否停止定时器旋转
self.link.paused = NO;
}
// 暂停旋转按钮
- (void)pauseRotation
{
self.link.paused = YES;
}
那么点击选号按钮时只要停止定时器旋转就可以
// 点击开始选号的时候调用
- (IBAction)startPickerNum:(id)sender { // 停止定时器旋转
self.link.paused = YES; // 快速的旋转,不需要与用户交互
CABasicAnimation *anim = [CABasicAnimation animation]; anim.keyPath = @"transform.rotation"; anim.toValue = @(M_PI * * );
anim.duration = 0.5; anim.delegate = self; [_centerView.layer addAnimation:anim forKey:nil];
}
5、根据之前的旋转的形变计算之前旋转的弧度
实现CAAnimationDelegate方法(分类:非正式协议)
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
// 恢复选中按钮之前位置 // 旋转度数:之前选中按钮旋转了多少度就反向旋转多少度 // 之前通过修改transform,之前的角度保存到按钮的transform属性里面
CGAffineTransform transform = self.selectedBtn.transform; // 计算下之前旋转的弧度
// 根据之前的旋转的形变计算之前旋转的弧度
CGFloat angle = atan2(transform.b, transform.a); // 反向旋转整个centerView
_centerView.transform = CGAffineTransformMakeRotation(-angle);
}
二、图片折叠
原理:
先设置两张图片,并且将空间的宽度和图片的宽度相等,高度等于图片的一半,使用下面的方法实现两张图片的快速合并
// 设置要显示的内容的范围
_topView.layer.contentsRect = CGRectMake(, , , 0.5);
// 设置锚点使之移动
_topView.layer.anchorPoint = CGPointMake(0.5, ); // 设置下部分显示内容的范围
_bottomView.layer.contentsRect = CGRectMake(, 0.5, , 0.5);
// 设置锚点使之移动
_bottomView.layer.anchorPoint = CGPointMake(0.5, );
从storyboard可以更直观的看到效果 将两张图片重合就可以达到想要的效果了


效果图:

1、添加阴影效果
// 阴影效果,添加到底部
CAGradientLayer *layer = [CAGradientLayer layer];
_layer = layer; layer.frame = _bottomView.bounds; // 设置渐变颜色
layer.colors = @[(id)[UIColor clearColor].CGColor,(id)[UIColor blackColor].CGColor]; layer.opacity = ; // // 设置渐变的方向
// layer.startPoint = CGPointMake(0, 0);
// layer.endPoint = CGPointMake(1, 0);
//
// // 设置颜色渐变的开始位置
// layer.locations = @[@0.5]; [_bottomView.layer addSublayer:layer];
2、增加立体感
CATransform3D transform = CATransform3DIdentity;
// d:人的眼睛和屏幕的垂直距离
CGFloat d = ; // 设置形变的m34就可以增加立体感,立体感(近大远小)
transform.m34 = - / d; // 描述形变的旋转的度数
transform = CATransform3DRotate(transform, angle, , , ); // 开始旋转
_topView.layer.transform = transform;
3、还原形变动画
if (pan.state == UIGestureRecognizerStateEnded) {
// 还原
// Damping:值越小,弹簧效果越明显
// options:描述动画执行过程,匀速,快入快出
[UIView animateWithDuration: delay: usingSpringWithDamping:0.2 initialSpringVelocity: options:UIViewAnimationOptionCurveEaseInOut animations:^{
_topView.layer.transform = CATransform3DIdentity;
} completion:^(BOOL finished) {
}];
// 弹簧效果
// 上部分形变清空
// 阴影透明
_layer.opacity = ;
}
三、音量振动条

知识点:
复制层 CAReplicatorLayer
// 复制层:复制里面的子层
CAReplicatorLayer *repL = [CAReplicatorLayer layer];
repL.frame = _contentView.bounds; // instanceCount:表示复制层中有多少份子层,拷贝是instanceCount - 1份
repL.instanceCount = ; // 设置复制子层偏移量,每个子层都会相对上一次偏移
repL.instanceTransform = CATransform3DMakeTranslation(, , ); // 延迟每个子层的动画,相对于上一个子层延迟
repL.instanceDelay = 0.2; // 设置子层的颜色
repL.instanceColor = [UIColor colorWithWhite: alpha:0.8].CGColor; [_contentView.layer addSublayer:repL]; // 红色的图层
CALayer *layer = [CALayer layer]; layer.backgroundColor = [UIColor redColor].CGColor; // layer.frame = CGRectMake(0, 100, 30, 100); layer.anchorPoint = CGPointMake(, );
layer.position = CGPointMake(, );
layer.bounds = CGRectMake(, , , ); // 把红色图层添加到复制层中
[repL addSublayer:layer]; CABasicAnimation *anim = [CABasicAnimation animation]; anim.keyPath = @"transform.scale.y"; anim.toValue = @; anim.duration = 0.5; // 设置动画反转
anim.autoreverses = YES; anim.repeatCount = MAXFLOAT; [layer addAnimation:anim forKey:nil];
四、倒影

CAReplicatorLayer *repL = (CAReplicatorLayer *)self.view.layer;
repL.instanceCount = ;
repL.instanceTransform = CATransform3DMakeRotation(M_PI, , , );
// 倒影效果
repL.instanceRedOffset -= 0.1;
repL.instanceBlueOffset -= 0.1;
repL.instanceGreenOffset -= 0.1;
repL.instanceAlphaOffset -= 0.1;
但是要自定义view 设置view里面根层的类型为CAReplicatorLayer
// 设置view里面根层的类型
+ (Class)layerClass
{
return [CAReplicatorLayer class];
}
五、粒子效果


注意点:
1、创建复制层
2、手动创建图层,将图层添加到复制层
3、创建帧动画,并给图层添加动画
#import "DrawView.h" @interface DrawView () @property (nonatomic, strong) UIBezierPath *path; @property (nonatomic, weak) CALayer *dotL; @end @implementation DrawView - (void)awakeFromNib
{
// 1、创建复制层
CAReplicatorLayer *repL = [CAReplicatorLayer layer]; repL.frame = self.bounds; repL.instanceCount = ; repL.instanceDelay = 0.3; [self.layer addSublayer:repL]; // 2、手动创建图层
CALayer *dotL = [CALayer layer]; _dotL = dotL; dotL.backgroundColor = [UIColor redColor].CGColor; dotL.frame = CGRectMake(-, , , ); dotL.cornerRadius = ; // 3、将图层添加到复制层
[repL addSublayer:dotL]; UIBezierPath *path = [UIBezierPath bezierPath]; _path = path;
} - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{ // 获取UITouch
UITouch *touch = [touches anyObject]; // 获取当前的触摸点
CGPoint curP = [touch locationInView:self]; [_path moveToPoint:curP]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// 获取UITouch
UITouch *touch = [touches anyObject]; // 获取当前的触摸点
CGPoint curP = [touch locationInView:self]; // 只是保存点路径
[_path addLineToPoint:curP]; // 重绘
[self setNeedsDisplay];
} - (void)drawRect:(CGRect)rect {
// Drawing code [_path stroke];
} // 开始动画的时候调用
- (void)startAnim
{
// 创建帧动画
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation]; anim.keyPath = @"position"; anim.duration = ; anim.path = _path.CGPath; anim.repeatCount = MAXFLOAT; // 给图层添加动画
[_dotL addAnimation:anim forKey:nil];
} // 重绘
- (void)reDraw
{
// 清除界面上的所有线,都是通过路径的点连接,移除路径中所有点
[_path removeAllPoints]; [self setNeedsDisplay]; // 移除图层中所有动画
[_dotL removeAllAnimations];
} @end
iOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果的更多相关文章
- iOS开发——UI进阶篇(八)pickerView简单使用,通过storyboard加载控制器,注册界面,通过xib创建控制器,控制器的view创建,导航控制器的基本使用
一.pickerView简单使用 1.UIPickerViewDataSource 这两个方法必须实现 // 返回有多少列 - (NSInteger)numberOfComponentsInPicke ...
- iOS开发——UI进阶篇(十七)CALayer,核心动画基本使用
一.CALayer简介 1.CALayer在iOS中,文本输入框.一个图标等等,这些都是UIView你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个其实UIView之所以 ...
- iOS开发——UI进阶篇(十六)Quartz2D实战小例子
一.画线 只有在drawRect中才能获取到跟view相关联的上下文 - (void)drawRect:(CGRect)rect {} 一条线 // 1.获取跟当前View相关联的layer上下文(画 ...
- iOS开发——UI进阶篇(十五)Quartz2D介绍
一.Quartz2D简介 1.什么是Quartz2DQuartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作绘制图形 : 线条\三角形\矩形\圆\弧等绘制文字绘 ...
- iOS开发——UI进阶篇(十二)事件处理,触摸事件,UITouch,UIEvent,响应者链条,手势识别
触摸事件 在用户使用app过程中,会产生各种各样的事件 一.iOS中的事件可以分为3大类型 触摸事件加速计事件远程控制事件 响应者对象在iOS中不是任何对象都能处理事件,只有继承了UIResponde ...
- iOS开发——UI进阶篇(三)自定义不等高cell,如何拿到cell的行高,自动计算cell高度,(有配图,无配图)微博案例
一.纯代码自定义不等高cell 废话不多说,直接来看下面这个例子先来看下微博的最终效果 首先创建一个继承UITableViewController的控制器@interface ViewControll ...
- iOS开发——UI进阶篇(十九)UISearchBar控件简介
最近用到搜索功能.总结一下 搜索,无疑可以使用UISearchBar控件! 那就先了解一下UISearchBar控件吧! UISearchBar控件就是要为你完成搜索功能的一个专用控件.它集成了很多你 ...
- iOS开发——UI进阶篇(十四)modal
一.modal与pushmodal从下面往上盖住原来的控制器,一般上一个控制器和下一个控制器没有什么关联时用modal,比如联系人的加号跳转页面,任何控制器都可以用modal push一般是上下文有关 ...
- iOS开发——UI进阶篇(十)导航控制器、微博详情页、控制器的View的生命周期
一.导航控制器出栈 1.initWithRootViewController本质 UIViewController *vc = [[OneViewController alloc] init]; // ...
随机推荐
- js 递归下的循环
的递归下的循环不能使用forEach 可以使用for代替 错误写法 // 获取完整名字 var getFullName = function(code, resultName) { if (code ...
- Win7系统开放C盘下文件夹Everyone权限
安装软件时遇到这样的情况:我就是管理员权限啊,怎么会安装有问题呢? 后来知道,用户名即使分配了你是管理员权限,有些文件还是有限制的(特别是C盘) 昨天遇到一个问题,有个文件夹里的隐藏文件就是无法显示, ...
- ORACLE ORA-01157: 无法标识/锁定数据文件
create undo tablespace MOZI datafile 'E:\oracle\product\10.2.0\oradata\orcl\MOZI.DBF' size 2048M ext ...
- 对象Clone
//================================================= // File Name : Clone_demo //-------------------- ...
- Unity multi_compile
http://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html http://forum.unity3d.com/threads/tuto ...
- GLSL Interface Block参考
http://www.opengl.org/wiki/Interface_Block_(GLSL) http://stackoverflow.com/questions/9916103/opengl- ...
- OC-方法的声明和实现、匿名对象
方法声明: 方法调用: *冒号也是方法名的一部分 *同一个类中不允许两个对象方法同名 练习 给Car类设计一个方法,用来和其他车比较车速,如果快返回1,慢返回-1,相同返回0 #import < ...
- ASP.NET MVC使用Bootstrap系列(5)——创建ASP.NET MVC Bootstrap Helpers
阅读目录 序言 内置的HTML Helpers 创建自定义的Helpers 使用静态方法创建Helpers 使用扩展方法创建Helpers 创建Fluent Helpers 创建自动闭合的Helper ...
- python快排算法
通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. ...
- [Angularjs]常见api函数
写在前面 在angularjs中提供了一些常用的函数,比如angular.lowercase(),angular.uppercase(),angular.isString(),angular.isNu ...