博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
几个动画demo
阅读量:5264 次
发布时间:2019-06-14

本文共 13319 字,大约阅读时间需要 44 分钟。

一、点击扩散效果

  这个效果没什么难度,主要是加深对核心动画的理解和使用,但是还是有几个想说明的地方。先看一下效果,具体内容代码里有注释。

   

////  CircleButton.m//  UITest////  Created by 邓竹立 on 16/11/14.//  Copyright © 2016年 GiveMeFive. All rights reserved.//#import "CircleButton.h"#import "UIColor_Hex_Extension.h"@interface CircleButton ()
@property(nonatomic,weak)CALayer *animationLayer;@end@implementation CircleButton-(instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) { //即使做了UIControlEventTouchDown 事件,依旧可以响应UIControlEventTouchUpInside 无需担心 [self addTarget:self action:@selector(tapDown) forControlEvents:UIControlEventTouchDown]; } return self;}-(void)tapDown{ [self.animationLayer removeFromSuperlayer]; CALayer *layer = [CALayer layer]; self.animationLayer = layer; layer.frame = self.bounds; layer.cornerRadius = MIN(self.bounds.size.width/2, self.bounds.size.height/2); layer.backgroundColor = [UIColor colorWithHex:0x2381e5].CGColor; layer.masksToBounds = YES; [self.layer addSublayer:layer]; //添加核心动画 (pop 其实也很好用) CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; transformAnimation.fromValue = @1; transformAnimation.toValue = @1.6; transformAnimation.duration = 0.5; //注意使用opacity,不要用alpha CAKeyframeAnimation *alphaAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"]; alphaAnimation.values = @[@0,@.5,@0]; alphaAnimation.duration = 0.5; alphaAnimation.removedOnCompletion = NO; CAAnimationGroup *groupAnimation = [CAAnimationGroup animation]; groupAnimation.animations = @[alphaAnimation,transformAnimation]; groupAnimation.duration = 0.5; groupAnimation.repeatCount = 1; //项目中我一般不会这么做,我会采用关闭隐式动画的方式解决动画回归的问题,这种方式是偷懒的方式,因为真实的layer 并没有在你看到的地方 , 你所看到的是 layer.presentationLayer groupAnimation.removedOnCompletion = NO; groupAnimation.fillMode = kCAFillModeForwards; groupAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; /**注意:**/ //个人认为,下两行最危险。 因为addAnimation:会对groupAnimation做一次copy,如果你addAnimation后再对groupAnimation做任何修改是不起作用的 groupAnimation.delegate = self; [layer addAnimation:groupAnimation forKey:@"circle"]; self.userInteractionEnabled = NO; __weak typeof(self) weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ weakSelf.userInteractionEnabled = YES; });}-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ [self.animationLayer removeFromSuperlayer]; }@end

 二、图片轮播

  图片轮播已经老生常谈了,我在一个APP上看到这个效果还不错就试着写了下。代码没什么,主要是逻辑上的处理。

 

////  AnimationCycleScrollView.m//  UITest////  Created by 邓竹立 on 16/11/14.//  Copyright © 2016年 GiveMeFive. All rights reserved.//#import "AnimationCycleScrollView.h"#import "UIColor_Hex_Extension.h"@interface AnimationCycleScrollView ()
@property(nonatomic,weak)UIScrollView *backScrollView;@property(nonatomic,weak)UIScrollView *frontScrollView;@property(nonatomic,weak)UIView *panView;@property(nonatomic,weak)UIPageControl *pageControl;@property(nonatomic,assign)CGPoint startPoint;@property(nonatomic,strong)NSArray *images;@property(nonatomic,strong)NSArray* titleViews;@end@implementation AnimationCycleScrollView-(instancetype)initWithFrame:(CGRect)frame images:(NSArray *)images titleViews:(NSArray *)titleViews{ if (self = [super initWithFrame:frame]) { self.titleViews = titleViews; self.images = images; // 底层显示图片的scrollView UIScrollView *backScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; [self addSubview:backScrollView]; self.backScrollView = backScrollView; backScrollView.pagingEnabled = YES; backScrollView.contentSize = CGSizeMake((images.count+2)*frame.size.width, 0); backScrollView.showsVerticalScrollIndicator = NO; backScrollView.showsHorizontalScrollIndicator = NO; backScrollView.delegate = self; //顶层显示文字的scrollView UIScrollView *frontScrollView = [[UIScrollView alloc] init]; frontScrollView.frame = backScrollView.frame; frontScrollView.delegate = self; frontScrollView.pagingEnabled = YES; frontScrollView.contentSize = CGSizeMake((titleViews.count+2)*frame.size.width, 0); frontScrollView.showsHorizontalScrollIndicator = NO; frontScrollView.showsVerticalScrollIndicator = NO; [self addSubview:frontScrollView]; self.frontScrollView = frontScrollView; //手势view UIView *panView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)]; panView.backgroundColor = [UIColor clearColor]; [self addSubview:panView]; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; [panView addGestureRecognizer:pan]; self.panView = panView; UIPageControl *pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, frame.size.height - 30, frame.size.width, 20)]; self.pageControl = pageControl; pageControl.numberOfPages = images.count; pageControl.pageIndicatorTintColor = [UIColor whiteColor]; pageControl.currentPageIndicatorTintColor = [UIColor colorWithHex:0x2381e5]; pageControl.hidesForSinglePage = YES; pageControl.userInteractionEnabled = NO; [self addSubview:pageControl]; for (int i = 0; i
self.startPoint.x){ if (self.frontScrollView.contentOffset.x > self.frontScrollView.frame.size.width) { [UIView animateKeyframesWithDuration:0.7 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeCubicPaced animations:^{ weakSelf.frontScrollView.contentOffset = CGPointMake(weakSelf.frontScrollView.contentOffset.x - weakSelf.frontScrollView.frame.size.width, 0); }completion:^(BOOL finished) { weakSelf.pageControl.currentPage = weakSelf.frontScrollView.contentOffset.x/weakSelf.frontScrollView.frame.size.width -1 ; }]; [UIView animateKeyframesWithDuration:0.3 delay:0.2 options:UIViewKeyframeAnimationOptionCalculationModeDiscrete animations:^{ weakSelf.backScrollView.contentOffset = CGPointMake(weakSelf.backScrollView.contentOffset.x - weakSelf.backScrollView.frame.size.width, 0); }completion:nil]; }else{ [UIView animateKeyframesWithDuration:0.7 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeCubicPaced animations:^{ weakSelf.frontScrollView.contentOffset = CGPointMake(0, 0); }completion:^(BOOL finished) { weakSelf.frontScrollView.contentOffset = CGPointMake(weakSelf.frontScrollView.frame.size.width*(_titleViews.count), 0); weakSelf.pageControl.currentPage = _titleViews.count - 1; }]; [UIView animateKeyframesWithDuration:0.3 delay:0.2 options:UIViewKeyframeAnimationOptionCalculationModeDiscrete animations:^{ weakSelf.backScrollView.contentOffset = CGPointMake(0, 0); }completion:^(BOOL finished) { weakSelf.backScrollView.contentOffset = CGPointMake(weakSelf.backScrollView.frame.size.width*(_images.count), 0); }]; } }}@end

 三、毛毛虫效果

这个也是在那个APP上看到的,不得不佩服国外的APP 交互就是比较新颖。国内的APP交互效果基本都千篇一律。

 

////  SectionSelectView.m//  UITest////  Created by 邓竹立 on 16/11/14.//  Copyright © 2016年 GiveMeFive. All rights reserved.//#import "SectionSelectView.h"#import "UIColor_Hex_Extension.h"@interface SectionSelectView ()@property(nonatomic,assign)NSInteger currentIndex;@property(nonatomic,weak)UIView *backView;@end@implementation SectionSelectView-(instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles icons:(NSArray *)icons currentIndex:(NSInteger)index{        if (self = [super initWithFrame:frame]) {                self.currentIndex = index;                CGFloat margin = 20;        CGFloat w = (frame.size.width - (titles.count+1)*margin)/titles.count;        CGFloat h = 40;                UIView * backView = [[UIView alloc] init];        backView.backgroundColor = [UIColor whiteColor];        backView.layer.cornerRadius = 20;        backView.clipsToBounds = YES;        [self addSubview:backView];        self.backView = backView;                for (int i = 0; i
self.currentIndex) { [UIView animateWithDuration:0.5 animations:^{ weakSelf.backView.frame = CGRectMake(currentButton.frame.origin.x, currentButton.frame.origin.y,sender.frame.origin.x+sender.frame.size.width - currentButton.frame.origin.x , sender.frame.size.height); [currentButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [sender setTitleColor:[UIColor colorWithHex:0x2381e5] forState:UIControlStateNormal]; }completion:^(BOOL finished) { [UIView animateWithDuration:0.5 animations:^{ weakSelf.backView.frame = sender.frame; }]; }]; }else{ [UIView animateWithDuration:0.5 animations:^{ weakSelf.backView.frame = CGRectMake(sender.frame.origin.x, sender.frame.origin.y, currentButton.frame.origin.x+currentButton.frame.size.width - sender.frame.origin.x, sender.frame.size.height); [currentButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [sender setTitleColor:[UIColor colorWithHex:0x2381e5] forState:UIControlStateNormal]; }completion:^(BOOL finished) { [UIView animateWithDuration:0.5 animations:^{ weakSelf.backView.frame = sender.frame; }]; }]; } self.currentIndex = sender.tag - 1000;}@end

 四、任意view 的扩散效果

个人认为这个效果不好看,原APP 中这个使用这种扩散(或收缩)来介绍某个功能的按钮。

////  UIView+CircleAlert.m//  UITest////  Created by 邓竹立 on 16/11/15.//  Copyright © 2016年 GiveMeFive. All rights reserved.//#import "UIView+CircleAlert.h"//#import 
@implementation UIView (CircleAlert)-(void)showCircleAlert{ UIWindow *keyWindow = nil; for (UIWindow *window in [UIApplication sharedApplication].windows) { if (window.rootViewController) { keyWindow = window; break; } } //截屏(我试过直接只用背景视图的Layer,但是对button 这类的View 不可用,打印发现,button.titleLabel 看不到) /* (lldb) po sender.layer
>; sublayers = (<_UILabelLayer: 0x60000008c1c0>); allowsGroupOpacity = YES; backgroundColor =
[
(kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 1 0 0 1 )> NSData *data = [NSKeyedArchiver archivedDataWithRootObject:sender.layer]; CALayer *layer = [NSKeyedUnarchiver unarchiveObjectWithData:data]; (lldb) po layer
); allowsGroupOpacity = YES; backgroundColor =
[
(kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)] ( 1 0 0 1 )> */ UIImageView *imageView = [[UIImageView alloc] init]; imageView.frame = keyWindow.bounds; imageView.image = [self shootScreenWithView:keyWindow]; //在真实的view 上盖一个半透明黑色layer; CALayer *blackLayer = [CALayer layer]; blackLayer.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5].CGColor; blackLayer.frame = keyWindow.layer.bounds; [keyWindow.layer addSublayer:blackLayer]; //把导出的盖在真实的View 上; [keyWindow addSubview:imageView]; //生成一个path 为圆的图层 作为Layer 的mask CAShapeLayer *shapeLayer = [CAShapeLayer layer]; UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:self.center radius:sqrt(pow(self.bounds.size.width, 2)+pow(self.bounds.size.height, 2))/2 startAngle:0 endAngle:2*M_PI clockwise:YES]; shapeLayer.path = path.CGPath; imageView.layer.mask = shapeLayer; //圆图层做放大动画 CGSize size = [UIScreen mainScreen].bounds.size; CGFloat maxR = sqrt(pow(size.width, 2)+pow(size.height, 2)); //添加动画 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"]; animation.fromValue = (__bridge id _Nullable)(path.CGPath); animation.toValue = (__bridge id _Nullable)([UIBezierPath bezierPathWithArcCenter:self.center radius:maxR startAngle:0 endAngle:2*M_PI clockwise:YES].CGPath); animation.duration = 1; animation.fillMode = kCAFillModeForwards; animation.removedOnCompletion = NO; [shapeLayer addAnimation:animation forKey:@"path"]; //动画完成 移除layer 和 view dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [imageView removeFromSuperview]; [blackLayer removeFromSuperlayer]; });}//截屏-(UIImage *)shootScreenWithView:(UIView*)view{ UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0); CGContextRef ctx=UIGraphicsGetCurrentContext(); [view.layer renderInContext: ctx]; UIImage *image=UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image;}@end

 代码写的比较暴力粗糙,如果有什么错误纰漏之处请联系我,QQ:395565391

转载于:https://www.cnblogs.com/dengzhuli/p/6202912.html

你可能感兴趣的文章
Jmeter接口压力测试,Java.net.BindException: Address already in use: connect
查看>>
Leetcode Balanced Binary Tree
查看>>
九.python面向对象(双下方法内置方法)
查看>>
go:channel(未完)
查看>>
[JS]递归对象或数组
查看>>
LeetCode(17) - Letter Combinations of a Phone Number
查看>>
Linux查找命令对比(find、locate、whereis、which、type、grep)
查看>>
路由器外接硬盘做nas可行吗?
查看>>
python:从迭代器,到生成器,再到协程的示例代码
查看>>
Java多线程系列——原子类的实现(CAS算法)
查看>>
在Ubuntu下配置Apache多域名服务器
查看>>
多线程《三》进程与线程的区别
查看>>
linux sed命令
查看>>
html标签的嵌套规则
查看>>
[Source] Machine Learning Gathering/Surveys
查看>>
HTML <select> 标签
查看>>
类加载机制
查看>>
tju 1782. The jackpot
查看>>
湖南多校对抗赛(2015.03.28) H SG Value
查看>>
hdu1255扫描线计算覆盖两次面积
查看>>