动画示例(六) 您所在的位置:网站首页 newimage/wcorner11.gif 动画示例(六)

动画示例(六)

2022-03-26 10:23| 来源: 网络整理| 查看: 265

版本记录 版本号 时间 V1.0 2017.12.13 前言

如果你细看了我前面写的有关动画的部分,就知道前面介绍了CoreAnimation、序列帧以及LOTAnimation等很多动画方式,接下来几篇我们就以动画示例为线索,进行动画的讲解。相关代码已经上传至GitHub - 刀客传奇。感兴趣的可以看我写的前面几篇。 1. 动画示例(一) —— 一种外扩的简单动画 2. 动画示例(二) —— 一种抖动的简单动画 3. 动画示例(三) —— 仿头条一种LOTAnimation动画 4. 动画示例(四) —— QuartzCore之CAEmitterLayer下雪❄️动画 5. 动画示例(五) —— QuartzCore之CAEmitterLayer烟花动画

功能要求

QuartzCore框架中CAEmitterLayer、CAReplicatorLayer和CAGradientLayer是很重要的三个类,特别是在做动画的时候很给力,这里就简单的实现基于它们三个的简单动画,这个动画不是我原创,下面给出链接,致敬原作者。 GitHub - YUAnimation

功能实现

首先看一下CAReplicatorLayer类的API

/* CoreAnimation - CAReplicatorLayer.h Copyright (c) 2008-2017, Apple Inc. All rights reserved. */ #import NS_ASSUME_NONNULL_BEGIN /* The replicator layer creates a specified number of copies of its * sublayers, each copy potentially having geometric, temporal and * color transformations applied to it. * * Note: the CALayer -hitTest: method currently only tests the first * instance of z replicator layer's sublayers. This may change in the * future. */ CA_CLASS_AVAILABLE (10.6, 3.0, 9.0, 2.0) @interface CAReplicatorLayer : CALayer /* The number of copies to create, including the source object. * Default value is one (i.e. no extra copies). Animatable. */ @property NSInteger instanceCount; /* Defines whether this layer flattens its sublayers into its plane or * not (i.e. whether it's treated similarly to a transform layer or * not). Defaults to NO. If YES, the standard restrictions apply (see * CATransformLayer.h). */ @property BOOL preservesDepth; /* The temporal delay between replicated copies. Defaults to zero. * Animatable. */ @property CFTimeInterval instanceDelay; /* The matrix applied to instance k-1 to produce instance k. The matrix * is applied relative to the center of the replicator layer, i.e. the * superlayer of each replicated sublayer. Defaults to the identity * matrix. Animatable. */ @property CATransform3D instanceTransform; /* The color to multiply the first object by (the source object). Defaults * to opaque white. Animatable. */ @property(nullable) CGColorRef instanceColor; /* The color components added to the color of instance k-1 to produce * the modulation color of instance k. Defaults to the clear color (no * change). Animatable. */ @property float instanceRedOffset; @property float instanceGreenOffset; @property float instanceBlueOffset; @property float instanceAlphaOffset; @end NS_ASSUME_NONNULL_END

接着再看一下类CAGradientLayer。

/* CoreAnimation - CAGradientLayer.h Copyright (c) 2008-2017, Apple Inc. All rights reserved. */ /* The gradient layer draws a color gradient over its background color, * filling the shape of the layer (i.e. including rounded corners). */ #import #import NS_ASSUME_NONNULL_BEGIN CA_CLASS_AVAILABLE (10.6, 3.0, 9.0, 2.0) @interface CAGradientLayer : CALayer /* The array of CGColorRef objects defining the color of each gradient * stop. Defaults to nil. Animatable. */ @property(nullable, copy) NSArray *colors; /* An optional array of NSNumber objects defining the location of each * gradient stop as a value in the range [0,1]. The values must be * monotonically increasing. If a nil array is given, the stops are * assumed to spread uniformly across the [0,1] range. When rendered, * the colors are mapped to the output colorspace before being * interpolated. Defaults to nil. Animatable. */ @property(nullable, copy) NSArray *locations; /* The start and end points of the gradient when drawn into the layer's * coordinate space. The start point corresponds to the first gradient * stop, the end point to the last gradient stop. Both points are * defined in a unit coordinate space that is then mapped to the * layer's bounds rectangle when drawn. (I.e. [0,0] is the bottom-left * corner of the layer, [1,1] is the top-right corner.) The default values * are [.5,0] and [.5,1] respectively. Both are animatable. */ @property CGPoint startPoint; @property CGPoint endPoint; /* The kind of gradient that will be drawn. Currently the only allowed * value is `axial' (the default value). */ @property(copy) NSString *type; @end /** `type' values. **/ CA_EXTERN NSString * const kCAGradientLayerAxial CA_AVAILABLE_STARTING (10.6, 3.0, 9.0, 2.0); NS_ASSUME_NONNULL_END

下面我们就看一下代码

1. YUMainTableViewController.h #import @interface YUMainTableViewController : UITableViewController @end 2. YUMainTableViewController.m #import "YUMainTableViewController.h" #import "YUAnimationViewController.h" @interface YUMainTableViewController () { // 各种layer动画 NSArray *_layerTypes; } @end @implementation YUMainTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"三种特殊的layer动画"; _layerTypes = @[@"CAReplicatorLayer 复制层动画", @"CAEmitterLayer 粒子动画", @"CAGradientLayer 渐变动画"]; self.tableView.tableFooterView = [[UIView alloc] init]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _layerTypes.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellID = @"cellID"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; } cell.textLabel.text = _layerTypes[indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { YUAnimationViewController *animationCtrl = [[YUAnimationViewController alloc] init]; animationCtrl.layerType = indexPath.row; animationCtrl.title = _layerTypes[indexPath.row]; [self.navigationController pushViewController:animationCtrl animated:YES]; } @end 3. YUAnimationViewController.h #import #import "YUReplicatorAnimation.h" // layer类型 typedef NS_ENUM(NSUInteger, YULayerType){ YUCAReplicatorLayer, // 复制动画 YUCAEmitterLayer, // 粒子动画 YUCAGradientLayer, // 渐变动画 }; @interface YUAnimationViewController : UITableViewController @property (nonatomic, assign) YULayerType layerType; @property (nonatomic, assign) YUReplicatorLayerType replicatorLayerType; @end 4. YUAnimationViewController.m #import "YUAnimationViewController.h" #import "YULoadingLabel.h" #import "SnowView.h" @interface YUAnimationViewController () { // 各种CAReplicatorLayer的动画 NSArray *_animationTypes; } @property (nonatomic, strong) SnowView *snow; @end @implementation YUAnimationViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView.tableFooterView = [[UIView alloc] init]; } // 三种layer的动画 - (void)setLayerType:(YULayerType)layerType { switch (layerType) { case YUCAReplicatorLayer: { [self setupCAReplicatorLayerAnimation]; } break; case YUCAEmitterLayer: { [self setupCAEmitterLayer]; self.view.backgroundColor = [UIColor grayColor]; } break; case YUCAGradientLayer: { [self setupCAGradientLayer]; self.view.backgroundColor = [UIColor grayColor]; } break; default: break; } } #pragma mark ----------------------- 各种CAReplicatorLayer的动画 - (void)setReplicatorLayerType:(YUReplicatorLayerType)replicatorLayerType { CGFloat width = 100; CGRect viewframe = CGRectMake((kScreenWidth - width) / 2, 150, width, width); switch (replicatorLayerType) { case YUReplicatorLayerShake: viewframe = CGRectMake(80, 200, width, width); break; case YUReplicatorLayerHeart: viewframe = CGRectMake(0, 64, width, width); break; default: break; } UIView *aniView = [[UIView alloc] initWithFrame:viewframe]; [self.view addSubview:aniView]; [aniView.layer addSublayer: [YUReplicatorAnimation replicatorLayerWithType:replicatorLayerType]]; self.view.backgroundColor = [UIColor grayColor]; } - (void)setupCAReplicatorLayerAnimation { _animationTypes = @[@"波纹 animation", @"波浪 animation", @"三角形 animation", @"网格 animation", @"条形 animation", @"转圈 animation", @"心 animation", @"翻转 animation"]; } #pragma mark ----------------------- CAEmitterLayer 粒子动画 - (void)setupCAEmitterLayer { self.snow = [[SnowView alloc] initWithFrame:CGRectMake(100, 100, kScreenWidth / 2.f, kScreenWidth / 2.f)]; // self.snow.backgroundColor = [UIColor grayColor]; [self.view addSubview:self.snow]; self.snow.snowImage = [UIImage imageNamed:@"snow"]; self.snow.birthRate = 20.f; self.snow.gravity = 5.f; self.snow.snowColor = [UIColor whiteColor]; CALayer *layer = [CALayer layer]; layer.anchorPoint = CGPointMake(0, 0); // 重置锚点 layer.bounds = CGRectMake(0, 0, kScreenWidth / 2.f, kScreenWidth / 2.f); // 设置尺寸 UIImage *image = [UIImage imageNamed:@"alpha"]; if (image) { layer.contents = (__bridge id)(image.CGImage); } self.snow.layer.mask = layer; [self.snow showSnow]; } #pragma mark ----------------------- 渐变动画 - (void)setupCAGradientLayer { // CAGradientLayer 动画 YULoadingLabel *loadingLabel = [YULoadingLabel loadingLabel]; loadingLabel.frame = CGRectMake(100, 100, 200, 100); [loadingLabel showLoadingInView:self.view text:nil]; YULoadingLabel *loadingLabel2 = [YULoadingLabel loadingLabel]; loadingLabel.textColor = [UIColor redColor]; loadingLabel2.frame = CGRectMake(110, 200, 200, 100); [loadingLabel2 showLoadingInView:self.view text:@"加载动画"]; } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _animationTypes.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellID = @"cellID"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; } cell.textLabel.text = _animationTypes[indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { YUAnimationViewController *animationCtrl = [[YUAnimationViewController alloc] init]; animationCtrl.replicatorLayerType = indexPath.row; animationCtrl.title = _animationTypes[indexPath.row]; [self.navigationController pushViewController:animationCtrl animated:YES]; } @end 5. YUReplicatorAnimation.h #import // 动画类型 typedef NS_ENUM(NSUInteger, YUReplicatorLayerType){ YUReplicatorLayerCircle, YUReplicatorLayerWave, YUReplicatorLayerTriangle, YUReplicatorLayerGrid, YUReplicatorLayerShake, YUReplicatorLayerRound, YUReplicatorLayerHeart, YUReplicatorLayerTurn, }; @interface YUReplicatorAnimation : NSObject + (CALayer *)replicatorLayerWithType:(YUReplicatorLayerType)type; // 波纹 + (CALayer *)replicatorLayer_Circle; // 波浪 + (CALayer *)replicatorLayer_Wave; // 三角形 + (CALayer *)replicatorLayer_Triangle; // 网格 + (CALayer *)replicatorLayer_Grid; // 震东条 + (CALayer *)replicatorLayer_Shake; // 转圈动画 + (CALayer *)replicatorLayer_Round; // 心动画 + (CALayer *)replicatorLayer_Heart; @end 6. YUReplicatorAnimation.m #import "YUReplicatorAnimation.h" @implementation YUReplicatorAnimation + (CALayer *)replicatorLayerWithType:(YUReplicatorLayerType)type { CALayer *layer = nil; switch (type) { case YUReplicatorLayerCircle: { layer = [self replicatorLayer_Circle]; } break; case YUReplicatorLayerWave: { layer = [self replicatorLayer_Wave]; } break; case YUReplicatorLayerTriangle: { layer = [self replicatorLayer_Triangle]; } break; case YUReplicatorLayerGrid: { layer = [self replicatorLayer_Grid]; } break; case YUReplicatorLayerShake: { layer = [self replicatorLayer_Shake]; } break; case YUReplicatorLayerRound: { layer = [self replicatorLayer_Round]; } break; case YUReplicatorLayerHeart: { layer = [self replicatorLayer_Heart]; } break; case YUReplicatorLayerTurn: { layer = [self replicatorLayer_Turn]; } break; default: { layer = [self replicatorLayer_Circle]; } break; } return layer; } #pragma mark ----------------------- 复制层 // 圆圈动画 波纹 + (CALayer *)replicatorLayer_Circle{ CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.frame = CGRectMake(0, 0, 80, 80); shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 80, 80)].CGPath; shapeLayer.fillColor = [UIColor redColor].CGColor; shapeLayer.opacity = 0.0; CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; animationGroup.animations = @[[self alphaAnimation],[self scaleAnimation]]; animationGroup.duration = 4.0; animationGroup.autoreverses = NO; animationGroup.repeatCount = HUGE; [shapeLayer addAnimation:animationGroup forKey:@"animationGroup"]; CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer]; replicatorLayer.frame = CGRectMake(0, 0, 80, 80); replicatorLayer.instanceDelay = 0.5; replicatorLayer.instanceCount = 8; [replicatorLayer addSublayer:shapeLayer]; return replicatorLayer; } // 波动动画 + (CALayer *)replicatorLayer_Wave{ CGFloat between = 5.0; CGFloat radius = (100-2*between)/3; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.frame = CGRectMake(0, (100-radius)/2, radius, radius); shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, radius, radius)].CGPath; shapeLayer.fillColor = [UIColor redColor].CGColor; [shapeLayer addAnimation:[self scaleAnimation1] forKey:@"scaleAnimation"]; CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer]; replicatorLayer.frame = CGRectMake(0, 0, 100, 100); replicatorLayer.instanceDelay = 0.2; replicatorLayer.instanceCount = 3; replicatorLayer.instanceTransform = CATransform3DMakeTranslation(between*2+radius,0,0); [replicatorLayer addSublayer:shapeLayer]; return replicatorLayer; } // 三角形动画 + (CALayer *)replicatorLayer_Triangle{ CGFloat radius = 100/4; CGFloat transX = 100 - radius; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.frame = CGRectMake(0, 0, radius, radius); shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, radius, radius)].CGPath; shapeLayer.strokeColor = [UIColor redColor].CGColor; shapeLayer.fillColor = [UIColor redColor].CGColor; shapeLayer.lineWidth = 1; [shapeLayer addAnimation:[self rotationAnimation:transX] forKey:@"rotateAnimation"]; CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer]; replicatorLayer.frame = CGRectMake(0, 0, radius, radius); replicatorLayer.instanceDelay = 0.0; replicatorLayer.instanceCount = 3; CATransform3D trans3D = CATransform3DIdentity; trans3D = CATransform3DTranslate(trans3D, transX, 0, 0); trans3D = CATransform3DRotate(trans3D, 120.0*M_PI/180.0, 0.0, 0.0, 1.0); replicatorLayer.instanceTransform = trans3D; [replicatorLayer addSublayer:shapeLayer]; return replicatorLayer; } // 网格动画 + (CALayer *)replicatorLayer_Grid{ NSInteger column = 3; CGFloat between = 5.0; CGFloat radius = (100 - between * (column - 1))/column; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.frame = CGRectMake(0, 0, radius, radius); shapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, radius, radius)].CGPath; shapeLayer.fillColor = [UIColor redColor].CGColor; CAAnimationGroup *animationGroup = [CAAnimationGroup animation]; animationGroup.animations = @[[self scaleAnimation1], [self alphaAnimation]]; animationGroup.duration = 1.0; animationGroup.autoreverses = YES; animationGroup.repeatCount = HUGE; [shapeLayer addAnimation:animationGroup forKey:@"groupAnimation"]; CAReplicatorLayer *replicatorLayerX = [CAReplicatorLayer layer]; replicatorLayerX.frame = CGRectMake(0, 0, 100, 100); replicatorLayerX.instanceDelay = 0.3; replicatorLayerX.instanceCount = column; replicatorLayerX.instanceTransform = CATransform3DTranslate(CATransform3DIdentity, radius+between, 0, 0); [replicatorLayerX addSublayer:shapeLayer]; CAReplicatorLayer *replicatorLayerY = [CAReplicatorLayer layer]; replicatorLayerY.frame = CGRectMake(0, 0, 100, 100); replicatorLayerY.instanceDelay = 0.3; replicatorLayerY.instanceCount = column; replicatorLayerY.instanceTransform = CATransform3DTranslate(CATransform3DIdentity, 0, radius+between, 0); [replicatorLayerY addSublayer:replicatorLayerX]; return replicatorLayerY; } // 震动条动画 + (CALayer *)replicatorLayer_Shake{ CALayer *layer = [[CALayer alloc]init]; layer.frame = CGRectMake(0, 0, 10, 80); layer.backgroundColor = [UIColor redColor].CGColor; layer.anchorPoint = CGPointMake(0.5, 1); // 添加一个基本动画 [layer addAnimation:[self scaleYAnimation] forKey:@"scaleAnimation"]; CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer]; replicatorLayer.frame = CGRectMake(0, 0, 80, 80); replicatorLayer.instanceCount = 6; replicatorLayer.instanceTransform = CATransform3DMakeTranslation(45, 0, 0); replicatorLayer.instanceDelay = 0.2; replicatorLayer.instanceGreenOffset = -0.3; [replicatorLayer addSublayer:layer]; return replicatorLayer; } // 转圈动画 + (CALayer *)replicatorLayer_Round{ CALayer *layer = [[CALayer alloc]init]; layer.frame = CGRectMake(0, 0, 12, 12); layer.cornerRadius = 6; layer.masksToBounds = YES; layer.transform = CATransform3DMakeScale(0.01, 0.01, 0.01); layer.backgroundColor = [UIColor purpleColor].CGColor; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; animation.duration = 1; animation.repeatCount = MAXFLOAT; animation.fromValue = @(1); animation.toValue = @(0.01); [layer addAnimation:animation forKey:nil]; NSInteger instanceCount = 9; CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer]; replicatorLayer.frame = CGRectMake(0, 0, 50, 50); replicatorLayer.preservesDepth = YES; replicatorLayer.instanceColor = [UIColor whiteColor].CGColor; replicatorLayer.instanceRedOffset = 0.1; replicatorLayer.instanceGreenOffset = 0.1; replicatorLayer.instanceBlueOffset = 0.1; replicatorLayer.instanceAlphaOffset = 0.1; replicatorLayer.instanceCount = instanceCount; replicatorLayer.instanceDelay = 1.0/instanceCount; replicatorLayer.instanceTransform = CATransform3DMakeRotation((2 * M_PI) /instanceCount, 0, 0, 1); [replicatorLayer addSublayer:layer]; return replicatorLayer; } // 心动画 + (CALayer *)replicatorLayer_Heart{ CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer new]; replicatorLayer.frame = CGRectMake(0, 0, 200, 200); // replicatorLayer.backgroundColor = [UIColor colorWithWhite:0 alpha:0.75].CGColor; CALayer *subLayer = [CALayer new]; subLayer.bounds = CGRectMake(60, 105, 10, 10); subLayer.backgroundColor = [UIColor colorWithWhite:0.8 alpha:1.0].CGColor; subLayer.borderColor = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor; subLayer.borderWidth = 1.0; subLayer.cornerRadius = 5.0; subLayer.shouldRasterize = YES; subLayer.rasterizationScale = [UIScreen mainScreen].scale; [replicatorLayer addSublayer:subLayer]; CAKeyframeAnimation *move = [CAKeyframeAnimation animationWithKeyPath:@"position"]; move.path = [self heartPath]; move.repeatCount = INFINITY; move.duration = 6.0; // move.autoreverses = YES; [subLayer addAnimation:move forKey:nil]; replicatorLayer.instanceDelay = 6/50.0; replicatorLayer.instanceCount = 50; replicatorLayer.instanceColor = [UIColor orangeColor].CGColor; replicatorLayer.instanceGreenOffset = -0.03; return replicatorLayer; } // 翻转动画 + (CALayer *)replicatorLayer_Turn { CGFloat margin = 8.0; CGFloat width = 80; CGFloat dotW = (width - 2 * margin) / 3; CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.frame = CGRectMake(0, (width - dotW) * 0.5, dotW, dotW); shapeLayer.path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, dotW, dotW)].CGPath; shapeLayer.fillColor = [UIColor redColor].CGColor; CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer]; replicatorLayer.frame = CGRectMake(0, 0, width, width); replicatorLayer.instanceDelay = 0.1; replicatorLayer.instanceCount = 3; CATransform3D transform = CATransform3DMakeTranslation(margin + dotW, 0, 0); replicatorLayer.instanceTransform = transform; [replicatorLayer addSublayer:shapeLayer]; CABasicAnimation *basicAnima = [CABasicAnimation animationWithKeyPath:@"transform"]; basicAnima.fromValue = [NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, 0, 0, 1.0, 0)]; basicAnima.toValue = [NSValue valueWithCATransform3D:CATransform3DRotate(CATransform3DIdentity, M_PI, 0, 1.0, 0)]; basicAnima.repeatCount = HUGE; basicAnima.duration = 0.6; [shapeLayer addAnimation:basicAnima forKey:nil]; return replicatorLayer; } #pragma mark ----------------------- 基础动画 + (CGPathRef)heartPath { CGFloat W = 25; CGFloat marginX = 10; CGFloat marginY = 15/25.0 * W; CGFloat space = 5/25.0 * W; UIBezierPath *bezierPath = [UIBezierPath new]; [bezierPath moveToPoint:(CGPointMake(marginX + W * 2, W * 4 + space))]; [bezierPath addQuadCurveToPoint:CGPointMake(marginX, W * 2) controlPoint:CGPointMake(W, W * 4 - space)]; [bezierPath addCurveToPoint:CGPointMake(marginX + W * 2, W * 2) controlPoint1:CGPointMake(marginX, marginY) controlPoint2:CGPointMake(marginX + W * 2, marginY)]; [bezierPath addCurveToPoint:CGPointMake(marginX + W * 4, W * 2) controlPoint1:CGPointMake(marginX + W * 2, marginY) controlPoint2:CGPointMake(marginX + W * 4, marginY)]; [bezierPath addQuadCurveToPoint:CGPointMake(marginX + W * 2, W * 4 + space) controlPoint:CGPointMake(marginX * 2 + W * 3, W * 4 - space)]; [bezierPath closePath]; CGAffineTransform T = CGAffineTransformMakeScale(3.0, 3.0); return CGPathCreateCopyByTransformingPath(bezierPath.CGPath, &T); } + (CABasicAnimation *)scaleYAnimation{ CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale.y"]; anim.toValue = @0.1; anim.duration = 0.4; anim.autoreverses = YES;//往返都有动画 anim.repeatCount = MAXFLOAT;//执行次数 return anim; } + (CABasicAnimation *)alphaAnimation{ CABasicAnimation *alpha = [CABasicAnimation animationWithKeyPath:@"opacity"]; alpha.fromValue = @(1.0); alpha.toValue = @(0.0); return alpha; } + (CABasicAnimation *)scaleAnimation{ CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform"]; scale.fromValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 0.0, 0.0, 0.0)]; scale.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0.0)]; return scale; } + (CABasicAnimation *)scaleAnimation1{ CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform"]; scale.fromValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0.0)]; scale.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 0.2, 0.2, 0.0)]; scale.autoreverses = YES; scale.repeatCount = HUGE; scale.duration = 0.6; return scale; } + (CABasicAnimation *)rotationAnimation:(CGFloat)transX{ CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform"]; CATransform3D fromValue = CATransform3DRotate(CATransform3DIdentity, 0.0, 0.0, 0.0, 0.0); scale.fromValue = [NSValue valueWithCATransform3D:fromValue]; CATransform3D toValue = CATransform3DTranslate(CATransform3DIdentity, transX, 0.0, 0.0); toValue = CATransform3DRotate(toValue,120.0*M_PI/180.0, 0.0, 0.0, 1.0); scale.toValue = [NSValue valueWithCATransform3D:toValue]; scale.autoreverses = NO; scale.repeatCount = HUGE; scale.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; scale.duration = 0.8; return scale; } @end 7. YULoadingLabel.h #import #define kScreenWidth [UIScreen mainScreen].bounds.size.width #define kScreenHeight [UIScreen mainScreen].bounds.size.height @interface YULoadingLabel : UILabel // 创建Label + (YULoadingLabel *)loadingLabel; // 显示加载动画 - (void)showLoadingInView:(UIView *)view text:(NSString *)text; // 隐藏 - (void)hide; @end 8. YULoadingLabel.m #import "YULoadingLabel.h" @implementation YULoadingLabel + (YULoadingLabel *)loadingLabel { return [[self alloc] init]; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.textColor = [UIColor blueColor]; self.font = [UIFont systemFontOfSize:35]; self.text = @"timelyRain"; } return self; } - (void)showLoadingInView:(UIView *)view text:(NSString *)text { [view addSubview:self]; if (text) { self.text = text; } [self sizeToFit]; // 创建渐变效果的layer CAGradientLayer *graLayer = [CAGradientLayer layer]; graLayer.frame = self.bounds; graLayer.colors = @[(__bridge id)[[UIColor greenColor] colorWithAlphaComponent:0.3].CGColor, (__bridge id)[UIColor yellowColor].CGColor, (__bridge id)[[UIColor yellowColor] colorWithAlphaComponent:0.3].CGColor]; graLayer.startPoint = CGPointMake(0, 0.1);//设置渐变方向起点 graLayer.endPoint = CGPointMake(1, 0); //设置渐变方向终点 graLayer.locations = @[@(0.0), @(0.0), @(0.1)]; //colors中各颜色对应的初始渐变点 // 创建动画 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"locations"]; animation.duration = 1.0f; animation.toValue = @[@(0.9), @(1.0), @(1.0)]; animation.removedOnCompletion = NO; animation.repeatCount = HUGE_VALF; animation.fillMode = kCAFillModeForwards; [graLayer addAnimation:animation forKey:@"xindong"]; // 将graLayer设置成textLabel的遮罩 self.layer.mask = graLayer; } - (void)hide { [self removeFromSuperview]; } @end 9. EmitterLayerView.h #import typedef enum : NSUInteger { __SNOW = 0x11, __RAIN, __NONE, } EMitterType; @interface EmitterLayerView : UIView /** * 重写setter,getter方法,可以在程序中直接使用点语法 */ - (void)setEmitterLayer:(CAEmitterLayer *)layer; - (CAEmitterLayer *)emitterLayer; - (void)show; - (void)hide; - (void)configType:(EMitterType)type; @end 10.EmitterLayerView.m #import "EmitterLayerView.h" @interface EmitterLayerView () { CAEmitterLayer *_layer; } @end @implementation EmitterLayerView /** * 替换layer * * @return 替换当前view的layer */ + (Class)layerClass { return [CAEmitterLayer class]; } /** * 模拟setter,getter方法 * */ - (void)setEmitterLayer:(CAEmitterLayer *)layer { _layer = layer; } - (CAEmitterLayer *)emitterLayer { return _layer; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { _layer = (CAEmitterLayer *)self.layer; } return self; } - (void)show { } - (void)hide { } - (void)configType:(EMitterType)type { } @end 11. SnowView.h #import "EmitterLayerView.h" @interface SnowView : EmitterLayerView @property (nonatomic, strong) UIImage *snowImage; @property (nonatomic, assign) CGFloat lifetime; // 生命周期 @property (nonatomic, assign) CGFloat birthRate; // 出生率 @property (nonatomic, assign) CGFloat speed; // 雪花速率 @property (nonatomic, assign) CGFloat speedRange; // 速率变化范围 [speed - speedRange , speed + speedRange] @property (nonatomic, assign) CGFloat gravity; // 重力 @property (nonatomic, strong) UIColor *snowColor; // 雪花颜色 - (void)showSnow; - (void)show; - (void)hide; - (void)configType:(EMitterType)type; @end 12.SnowView.m #import "SnowView.h" @implementation SnowView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setup]; } return self; } - (void)setup { self.emitterLayer.emitterShape = kCAEmitterLayerLine; // 直线粒子发射器 self.emitterLayer.emitterMode = kCAEmitterLayerSurface; // ????? self.emitterLayer.emitterSize = self.frame.size; // 发射区域 self.emitterLayer.emitterPosition = CGPointMake(self.bounds.size.width / 2.f, - 5); // 发射中心点位置 } - (void)showSnow { if (_snowImage == nil) { return; } // 创建雪花类型的粒子 CAEmitterCell *snowflake = [CAEmitterCell emitterCell]; // 粒子的名字 snowflake.name = @"snow"; // 粒子参数的速度乘数因子 snowflake.birthRate = (_birthRate > 0 ? _birthRate : 1.f); // 粒子生命周期 snowflake.lifetime = (_lifetime > 0 ? _lifetime : 60); // 粒子速度 snowflake.velocity = (_speed > 0 ? _speed : 10.f); // 粒子的速度范围 snowflake.velocityRange = (_speedRange > 0 ? _speedRange : 10.f); // 粒子y方向的加速度分量(可以理解为重力) snowflake.yAcceleration = (_gravity != 0 ? _gravity : 2.f); // 每个发射的粒子的初始时候随机的角度 snowflake.emissionRange = 0.5 * M_PI; // 粒子旋转角度 snowflake.spinRange = 0.25 * M_PI; // 获取图片 snowflake.contents = (id)_snowImage.CGImage; // 设置雪花形状的粒子的颜色 snowflake.color = (_snowColor == nil ? [[UIColor whiteColor] CGColor] :_snowColor.CGColor); // 尺寸 snowflake.scale = 0.5f; // 尺寸变化范围 snowflake.scaleRange = 0.3f; // 添加粒子 self.emitterLayer.emitterCells = @[snowflake]; } - (void)configType:(EMitterType)type { if (type == __SNOW) { // 配置 self.birthRate = 5.f; self.snowImage = [UIImage imageNamed:@"snow"]; self.snowColor = [UIColor blackColor]; self.lifetime = 30.f; self.alpha = 0.f; UIImageView *snowAlpha = [[UIImageView alloc] initWithFrame:self.bounds]; snowAlpha.image = [UIImage imageNamed:@"alpha"]; self.maskView = snowAlpha; } } - (void)show { [self showSnow]; [UIView animateWithDuration:1.75f animations:^{ self.alpha = 0.5f; }]; } - (void)hide { [UIView animateWithDuration:0.75 animations:^{ self.alpha = 0.f; } completion:^(BOOL finished) { }]; } @end 功能效果

下面我们就看结果效果图。

后记

未完,待续~~~



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有