美文网首页
CoreAnimation的粒子效果

CoreAnimation的粒子效果

作者: 王俏 | 来源:发表于2020-08-12 13:57 被阅读0次

    粒子效果

    效果1

    粒子效果1.gif

    代码实现

    #import "ViewController.h"
    
    @interface ViewController ()
    @property (nonatomic, strong) CAEmitterLayer * colorBallLayer;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        self.view.backgroundColor = [UIColor blackColor];
        [self setupEmitter];
    
    }
    - (void)setupEmitter{
        
        UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width, 50)];
        [self.view addSubview:label];
        label.textColor = [UIColor whiteColor];
        label.text = @"轻点或拖动来改变发射源位置";
        label.textAlignment = NSTextAlignmentCenter;
        
        
        /*
         emitterShape: 形状:
         1. 点;kCAEmitterLayerPoint .
         2. 线;kCAEmitterLayerLine
         3. 矩形框: kCAEmitterLayerRectangle
         4. 立体矩形框: kCAEmitterLayerCuboid
         5. 圆形: kCAEmitterLayerCircle
         6. 立体圆形: kCAEmitterLayerSphere
    
         emitterMode:
         kCAEmitterLayerPoints
         kCAEmitterLayerOutline
         kCAEmitterLayerSurface
         kCAEmitterLayerVolume
         
         */
     
         //1. 设置CAEmitterLayer
        CAEmitterLayer *colorBallLayer = [CAEmitterLayer layer];
        [self.view.layer addSublayer:colorBallLayer];
        self.colorBallLayer = colorBallLayer;
        
        colorBallLayer.emitterSize = self.view.frame.size;
        colorBallLayer.emitterShape = kCAEmitterLayerPoint;
        colorBallLayer.emitterMode = kCAEmitterLayerPoints;
        colorBallLayer.emitterPosition = CGPointMake(self.view.layer.bounds.size.width, 0.0f);
        
        //2.配置CAEmitterCell
        CAEmitterCell *colorBarCell = [CAEmitterCell emitterCell];
        colorBarCell.name = @"colorBarCell";
        colorBarCell.birthRate = 20.0f;
        colorBarCell.lifetime = 10.0f;
        colorBarCell.velocity = 40.0f;
        colorBarCell.velocityRange = 100.0f;
        colorBarCell.yAcceleration = 15.0f;
        colorBarCell.emissionLatitude = M_PI;
        colorBarCell.emissionRange = M_PI_4;
        colorBarCell.scale = 0.2;
        colorBarCell.scaleRange = 0.1;
        colorBarCell.scaleSpeed = 0.02;
        colorBarCell.contents = (id)[[UIImage imageNamed:@"circle_white"]CGImage];
        colorBarCell.color = [[UIColor colorWithRed:0.5 green:0.0f blue:0.5f alpha:1.0f]CGColor];
        colorBarCell.redRange = 1.0f;
        colorBarCell.greenRange = 1.0f;
        colorBarCell.alphaRange = 0.8f;
        colorBarCell.blueSpeed = 1.0f;
        colorBarCell.alphaSpeed = -0.1f;
        colorBallLayer.emitterCells = @[colorBarCell];
        
        
    }
    
    
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        
        CGPoint point = [self locationFromTouchEvent:event];
        [self setBallInPsition:point];
    }
    
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        CGPoint point = [self locationFromTouchEvent:event];
        [self setBallInPsition:point];
    }
    
    /**
     * 获取手指所在点
     */
    - (CGPoint)locationFromTouchEvent:(UIEvent *)event{
        UITouch * touch = [[event allTouches] anyObject];
        return [touch locationInView:self.view];
    }
    
    /**
     * 移动发射源到某个点上
     */
    - (void)setBallInPsition:(CGPoint)position{
        
     //基础动画
        CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"emitterCells.colorBallCell.scale"];
        //fromeValue
        anim.fromValue = @0.2f;
    
        //toValue
        anim.toValue = @0.5f;
    
        //duration
        anim.duration = 1.f;
    
        //线性变换
        anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    
        //用事务包装隐式动画
        [CATransaction begin];
        //设置是否禁止由该事务组内的属性更改而触发的操作
        [CATransaction setDisableActions:YES];
        //为colorBallLayer 添加动画
        [self.colorBallLayer addAnimation:anim forKey:nil];
        //为colorBallLayert指定位置添加动画效果
        [self.colorBallLayer setValue:[NSValue valueWithCGPoint:position] forKey:@"emitterPosition"];
    
        //提交动画
        [CATransaction commit];
        
      
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    @end
    

    效果2

    粒子效果2.gif

    代码实现

    
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (nonatomic, strong) CAEmitterLayer * rainLayer;
    @property (nonatomic, weak) UIImageView * imageView;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        [self setupUI];
        [self setupEmitter];
    }
    
    - (void)setupUI{
        
        // 背景图片
        UIImageView * imageView = [[UIImageView alloc]initWithFrame:self.view.frame];
        [self.view addSubview:imageView];
        self.imageView = imageView;
        imageView.image = [UIImage imageNamed:@"rain"];
        
        // 下雨按钮
        UIButton * startBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [self.view addSubview:startBtn];
        startBtn.frame = CGRectMake(20, self.view.bounds.size.height - 60, 80, 40);
        startBtn.backgroundColor = [UIColor whiteColor];
        [startBtn setTitle:@"雨停了" forState:UIControlStateNormal];
        [startBtn setTitle:@"下雨" forState:UIControlStateSelected];
        [startBtn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
        [startBtn setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
        [startBtn addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
        
        // 雨量按钮
        UIButton * rainBIgBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [self.view addSubview:rainBIgBtn];
        rainBIgBtn.tag = 100;
        rainBIgBtn.frame = CGRectMake(140, self.view.bounds.size.height - 60, 80, 40);
        rainBIgBtn.backgroundColor = [UIColor whiteColor];
        [rainBIgBtn setTitle:@"下大点" forState:UIControlStateNormal];
        [rainBIgBtn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
        [rainBIgBtn addTarget:self action:@selector(rainButtonClick:) forControlEvents:UIControlEventTouchUpInside];
        
        UIButton * rainSmallBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        [self.view addSubview:rainSmallBtn];
        rainSmallBtn.tag = 200;
        rainSmallBtn.frame = CGRectMake(240, self.view.bounds.size.height - 60, 80, 40);
        rainSmallBtn.backgroundColor = [UIColor whiteColor];
        [rainSmallBtn setTitle:@"太大了" forState:UIControlStateNormal];
        [rainSmallBtn setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
        [rainSmallBtn addTarget:self action:@selector(rainButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    }
    
    
    - (void)buttonClick:(UIButton *)sender{
        
        if (!sender.selected) {
            
            sender.selected = !sender.selected;
            NSLog(@"雨停了");
            
            // 停止下雨
            [self.rainLayer setValue:@0.f forKeyPath:@"birthRate"];
            
        }else{
            
            sender.selected = !sender.selected;
            NSLog(@"开始下雨了");
            
            // 开始下雨
            [self.rainLayer setValue:@1.f forKeyPath:@"birthRate"];
        }
    }
    
    - (void)rainButtonClick:(UIButton *)sender{
        
        NSInteger rate = 1;
        CGFloat scale = 0.05;
        if (sender.tag == 100) {
            
            NSLog(@"下大了");
            
            if (self.rainLayer.birthRate < 30) {
                [self.rainLayer setValue:@(self.rainLayer.birthRate + rate) forKeyPath:@"birthRate"];
                [self.rainLayer setValue:@(self.rainLayer.scale + scale) forKeyPath:@"scale"];
            }
            
        }else if (sender.tag == 200){
            
            NSLog(@"变小了");
            
            if (self.rainLayer.birthRate > 1) {
                [self.rainLayer setValue:@(self.rainLayer.birthRate - rate) forKeyPath:@"birthRate"];
                [self.rainLayer setValue:@(self.rainLayer.scale - scale) forKeyPath:@"scale"];
            }
        }
    }
    
    - (void)setupEmitter{
        
        // 1. 设置CAEmitterLayer
        CAEmitterLayer * rainLayer = [CAEmitterLayer layer];
        // 2.在背景图上添加粒子图层
        [self.imageView.layer addSublayer:rainLayer];
        self.rainLayer = rainLayer;
        
        //3.发射形状--线性
        rainLayer.emitterShape = kCAEmitterLayerLine;
        //发射模式
        rainLayer.emitterMode = kCAEmitterLayerSurface;
        //发射源大小
        rainLayer.emitterSize = self.view.frame.size;
        //发射源位置 y最好不要设置为0 最好<0
        rainLayer.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -10);
        
        // 2. 配置cell
        CAEmitterCell * snowCell = [CAEmitterCell emitterCell];
        //粒子内容
        snowCell.contents = (id)[[UIImage imageNamed:@"rain_white"] CGImage];
        //每秒产生的粒子数量的系数
        snowCell.birthRate = 25.f;
        //粒子的生命周期
        snowCell.lifetime = 20.f;
        //speed粒子速度.图层的速率。用于将父时间缩放为本地时间,例如,如果速率是2,则本地时间的进度是父时间的两倍。默认值为1。
        snowCell.speed = 10.f;
        //粒子速度系数, 默认1.0
        snowCell.velocity = 10.f;
        //每个发射物体的初始平均范围,默认等于0
        snowCell.velocityRange = 10.f;
        //粒子在y方向的加速的
        snowCell.yAcceleration = 1000.f;
        //粒子缩放比例: scale
        snowCell.scale = 0.1;
        //粒子缩放比例范围:scaleRange
        snowCell.scaleRange = 0.f;
        
        // 3.添加到图层上
        rainLayer.emitterCells = @[snowCell];
    }
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    @end
    
    

    效果3

    粒子效果3.gif
    #import <UIKit/UIKit.h>
    
    @interface CCLikeButton : UIButton
    
    @end
    
    #import "CCLikeButton.h"
    
    @interface CCLikeButton()
    
    @property(nonatomic,strong)CAEmitterLayer *explosionLayer;
    
    @end
    
    @implementation CCLikeButton
    - (void)awakeFromNib{
        [super awakeFromNib];
        //设置粒子效果
        [self setupExplosion];
    }
    
    - (instancetype)initWithFrame:(CGRect)frame{
        self = [super initWithFrame:frame];
        if (self) {
            [self setupExplosion];
        }
        return self;
    }
    
    //设置粒子
    - (void)setupExplosion{
        
        // 1. 粒子
        CAEmitterCell * explosionCell = [CAEmitterCell emitterCell];
        explosionCell.name = @"explosionCell";
        //透明值变化速度
        explosionCell.alphaSpeed = -1.f;
        //alphaRange透明值范围
        explosionCell.alphaRange = 0.10;
        //生命周期
        explosionCell.lifetime = 1;
        //生命周期range
        explosionCell.lifetimeRange = 0.1;
        //粒子速度
        explosionCell.velocity = 40.f;
        //粒子速度范围
        explosionCell.velocityRange = 10.f;
        //缩放比例
        explosionCell.scale = 0.08;
        //缩放比例range
        explosionCell.scaleRange = 0.02;
        //粒子图片
        explosionCell.contents = (id)[[UIImage imageNamed:@"spark_red"] CGImage];
        
        // 2.发射源
        CAEmitterLayer * explosionLayer = [CAEmitterLayer layer];
        [self.layer addSublayer:explosionLayer];
        self.explosionLayer = explosionLayer;
        //发射院尺寸大小
        self.explosionLayer.emitterSize = CGSizeMake(self.bounds.size.width + 40, self.bounds.size.height + 40);
        //emitterShape表示粒子从什么形状发射出来,圆形形状
        explosionLayer.emitterShape = kCAEmitterLayerCircle;
        //emitterMode发射模型,轮廓模式,从形状的边界上发射粒子
        explosionLayer.emitterMode = kCAEmitterLayerOutline;
        //renderMode:渲染模式
        explosionLayer.renderMode = kCAEmitterLayerOldestFirst;
        //粒子cell 数组
        explosionLayer.emitterCells = @[explosionCell];
    }
    
    
    -(void)layoutSubviews{
        // 发射源位置
        self.explosionLayer.position = CGPointMake(self.bounds.size.width * 0.5, self.bounds.size.height * 0.5);
        
        [super layoutSubviews];
    }
    
    /**
     * 选中状态 实现缩放
     */
    - (void)setSelected:(BOOL)selected{
        [super setSelected:selected];
        
        // 通过关键帧动画实现缩放
        CAKeyframeAnimation * animation = [CAKeyframeAnimation animation];
        // 设置动画路径
        animation.keyPath = @"transform.scale";
        
        if (selected) {
            // 从没有点击到点击状态 会有爆炸的动画效果
            animation.values = @[@1.5,@2.0, @0.8, @1.0];
            animation.duration = 0.5;
            //计算关键帧方式:
            animation.calculationMode = kCAAnimationCubic;
            //为图层添加动画
            [self.layer addAnimation:animation forKey:nil];
            
            // 让放大动画先执行完毕 再执行爆炸动画
            [self performSelector:@selector(startAnimation) withObject:nil afterDelay:0.25];
        }else{
            // 从点击状态normal状态 无动画效果 如果点赞之后马上取消 那么也立马停止动画
            [self stopAnimation];
        }
    }
    
    // 没有高亮状态
    - (void)setHighlighted:(BOOL)highlighted{
        
        [super setHighlighted:highlighted];
        
    }
    
    /**
     * 开始动画
     */
    - (void)startAnimation{
        
        // 用KVC设置颗粒个数
        [self.explosionLayer setValue:@1000 forKeyPath:@"emitterCells.explosionCell.birthRate"];
        
        // 开始动画
        self.explosionLayer.beginTime = CACurrentMediaTime();
        
        // 延迟停止动画
        [self performSelector:@selector(stopAnimation) withObject:nil afterDelay:0.15];
    }
    
    /**
     * 动画结束
     */
    - (void)stopAnimation{
        // 用KVC设置颗粒个数
        [self.explosionLayer setValue:@0 forKeyPath:@"emitterCells.explosionCell.birthRate"];
        //移除动画
        [self.explosionLayer removeAllAnimations];
    }
    
    
    - (void)drawRect:(CGRect)rect {
        
    }
    
    @end
    
    
    

    效果4

    粒子效果4.gif

    代码实现

    
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (nonatomic, strong) CAEmitterLayer * rainLayer;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        //PS.图片随便找的.想要更好看的.可以自己配图.
        //㊗️.大家端午安康--CC.
        
        //粽子雨
        //[self rainZongzi];
       
        //红包雨
        //[self hongBaoRain];
        
        //金币雨
        //[self jingbiRain];
        
        //综合效果
        [self allRain];
    }
    
    
    -(void)rainZongzi
    {
        
        //1. 设置CAEmitterLayer
        CAEmitterLayer * rainLayer = [CAEmitterLayer layer];
        
        //2.在背景图上添加粒子图层
        [self.view.layer addSublayer:rainLayer];
        self.rainLayer = rainLayer;
        
        //3.发射形状--线性
        rainLayer.emitterShape = kCAEmitterLayerLine;
        rainLayer.emitterMode = kCAEmitterLayerSurface;
        rainLayer.emitterSize = self.view.frame.size;
        rainLayer.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -10);
        
        //2. 配置cell
        CAEmitterCell * snowCell = [CAEmitterCell emitterCell];
        snowCell.contents = (id)[[UIImage imageNamed:@"zongzi2.jpg"] CGImage];
        snowCell.birthRate = 1.0;
        snowCell.lifetime = 30;
        snowCell.speed = 2;
        snowCell.velocity = 10.f;
        snowCell.velocityRange = 10.f;
        snowCell.yAcceleration = 60;
        snowCell.scale = 0.05;
        snowCell.scaleRange = 0.f;
        
        // 3.添加到图层上
        rainLayer.emitterCells = @[snowCell];
        
    }
    
    -(void)hongBaoRain
    {
        
        //1. 设置CAEmitterLayer
        CAEmitterLayer * rainLayer = [CAEmitterLayer layer];
        
        //2.在背景图上添加粒子图层
        [self.view.layer addSublayer:rainLayer];
        self.rainLayer = rainLayer;
        
        //3.发射形状--线性
        rainLayer.emitterShape = kCAEmitterLayerLine;
        rainLayer.emitterMode = kCAEmitterLayerSurface;
        rainLayer.emitterSize = self.view.frame.size;
        rainLayer.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -10);
        
        //2. 配置cell
        CAEmitterCell * snowCell = [CAEmitterCell emitterCell];
        snowCell.contents = (id)[[UIImage imageNamed:@"hongbao.png"] CGImage];
        snowCell.birthRate = 1.0;
        snowCell.lifetime = 30;
        snowCell.speed = 2;
        snowCell.velocity = 10.f;
        snowCell.velocityRange = 10.f;
        snowCell.yAcceleration = 60;
        snowCell.scale = 0.05;
        snowCell.scaleRange = 0.f;
        
        
        // 3.添加到图层上
        rainLayer.emitterCells = @[snowCell];
        
        
    }
    
    
    -(void)jingbiRain
    {
        
        //1. 设置CAEmitterLayer
        CAEmitterLayer * rainLayer = [CAEmitterLayer layer];
        
        //2.在背景图上添加粒子图层
        [self.view.layer addSublayer:rainLayer];
        self.rainLayer = rainLayer;
        
        //3.发射形状--线性
        rainLayer.emitterShape = kCAEmitterLayerLine;
        rainLayer.emitterMode = kCAEmitterLayerSurface;
        rainLayer.emitterSize = self.view.frame.size;
        rainLayer.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -10);
        
        //2. 配置cell
        CAEmitterCell * snowCell = [CAEmitterCell emitterCell];
        snowCell.contents = (id)[[UIImage imageNamed:@"jinbi.png"] CGImage];
        snowCell.birthRate = 1.0;
        snowCell.lifetime = 30;
        snowCell.speed = 2;
        snowCell.velocity = 10.f;
        snowCell.velocityRange = 10.f;
        snowCell.yAcceleration = 60;
        snowCell.scale = 0.1;
        snowCell.scaleRange = 0.f;
    
        // 3.添加到图层上
        rainLayer.emitterCells = @[snowCell];
        
        
    }
    
    -(void)allRain
    {
        
        //1. 设置CAEmitterLayer
        CAEmitterLayer * rainLayer = [CAEmitterLayer layer];
        
        //2.在背景图上添加粒子图层
        [self.view.layer addSublayer:rainLayer];
        self.rainLayer = rainLayer;
        
        //3.发射形状--线性
        rainLayer.emitterShape = kCAEmitterLayerLine;
        rainLayer.emitterMode = kCAEmitterLayerSurface;
        rainLayer.emitterSize = self.view.frame.size;
        rainLayer.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -10);
        
        //2. 配置cell
        CAEmitterCell * snowCell = [CAEmitterCell emitterCell];
        snowCell.contents = (id)[[UIImage imageNamed:@"jinbi.png"] CGImage];
        snowCell.birthRate = 1.0;
        snowCell.lifetime = 30;
        snowCell.speed = 2;
        snowCell.velocity = 10.f;
        snowCell.velocityRange = 10.f;
        snowCell.yAcceleration = 60;
        snowCell.scale = 0.1;
        snowCell.scaleRange = 0.f;
        
        CAEmitterCell * hongbaoCell = [CAEmitterCell emitterCell];
        hongbaoCell.contents = (id)[[UIImage imageNamed:@"hongbao.png"] CGImage];
        hongbaoCell.birthRate = 1.0;
        hongbaoCell.lifetime = 30;
        hongbaoCell.speed = 2;
        hongbaoCell.velocity = 10.f;
        hongbaoCell.velocityRange = 10.f;
        hongbaoCell.yAcceleration = 60;
        hongbaoCell.scale = 0.05;
        hongbaoCell.scaleRange = 0.f;
        
        CAEmitterCell * zongziCell = [CAEmitterCell emitterCell];
        zongziCell.contents = (id)[[UIImage imageNamed:@"zongzi2.jpg"] CGImage];
        zongziCell.birthRate = 1.0;
        zongziCell.lifetime = 30;
        zongziCell.speed = 2;
        zongziCell.velocity = 10.f;
        zongziCell.velocityRange = 10.f;
        zongziCell.yAcceleration = 60;
        zongziCell.scale = 0.05;
        zongziCell.scaleRange = 0.f;
        
        // 3.添加到图层上
        rainLayer.emitterCells = @[snowCell,hongbaoCell,zongziCell];
        
        
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    
    
    @end
    

    相关文章

      网友评论

          本文标题:CoreAnimation的粒子效果

          本文链接:https://www.haomeiwen.com/subject/mijnrktx.html