iOS动画 ---特殊Layer动画

2023-11-16

iOS动画 ---特殊Layer动画

iOS中有一些特殊的layer,也可以做一些动画效果,本文就补充两个可以做动画效果的layer: CAEmitterLayer 和 CAReplicatorLayer。

CAEmitterLayer

Emitter 发射器,因为可以用它来做爆炸、发射、下雪等效果。
比如,这个下雪效果:


下雪.gif
- (void)setEmitter
{
    CAEmitterLayer *snowEmitter = [CAEmitterLayer layer];
    //发射点的位置
    snowEmitter.emitterPosition = CGPointMake(self.view.bounds.size.width * 0.5, -30);
    //
    snowEmitter.emitterSize = CGSizeMake(self.view.bounds.size.width * 2.0, 0.0);
    snowEmitter.emitterShape = kCAEmitterLayerLine;
    snowEmitter.emitterMode = kCAEmitterLayerOutline;

    snowEmitter.shadowColor = [UIColor whiteColor].CGColor;
    snowEmitter.shadowOffset = CGSizeMake(0.0, 1.0);
    snowEmitter.shadowRadius = 0.0;
    snowEmitter.shadowOpacity = 1.0;

    CAEmitterCell *snowCell = [CAEmitterCell emitterCell];

    snowCell.birthRate = 1.0; //每秒出现多少个粒子
    snowCell.lifetime = 120.0; // 粒子的存活时间
    snowCell.velocity = -10; //速度
    snowCell.velocityRange = 10; // 平均速度
    snowCell.yAcceleration = 2;//粒子在y方向上的加速度
    snowCell.emissionRange = 0.5 * M_PI; //发射的弧度
    snowCell.spinRange = 0.25 * M_PI; // 粒子的平均旋转速度
    snowCell.contents = (id)[UIImage imageNamed:@"snow"].CGImage;
    snowCell.color = [UIColor colorWithRed:0.6 green:0.658 blue:0.743 alpha:1.0].CGColor;

    snowEmitter.emitterCells = @[snowCell];

    [self.view.layer insertSublayer:snowEmitter atIndex:0];
}

喷射效果:


喷射.gif


主要代码:

- (void)setEmitter
{
    CAEmitterLayer *snowEmitter = [CAEmitterLayer layer];
    //发射点的位置
    snowEmitter.emitterPosition = self.view.center;
    //
    snowEmitter.emitterSize = CGSizeMake(10.0, 0.0);
    snowEmitter.emitterShape = kCAEmitterLayerLine;
    snowEmitter.emitterMode = kCAEmitterLayerOutline;

    CAEmitterCell *snowCell = [CAEmitterCell emitterCell];

    snowCell.birthRate = 50.0;
    snowCell.lifetime = 10.0;
    snowCell.velocity = 40;
    snowCell.velocityRange = 10;
    snowCell.yAcceleration = 2;
    snowCell.emissionRange =  M_PI / 9;
    snowCell.scale = 0.1; //缩小比例
    snowCell.scaleRange = 0.08;// 平均缩小比例
    snowCell.contents = (id)[UIImage imageNamed:@"Sparkle"].CGImage;
    snowCell.color = [UIColor colorWithRed:0.6 green:0.658 blue:0.743 alpha:1.0].CGColor;

    snowEmitter.emitterCells = @[snowCell];

    [self.view.layer insertSublayer:snowEmitter atIndex:0];
}

烟花爆炸效果:


烟花.gif
- (void)fireworks
{
    CAEmitterLayer *emitter = [CAEmitterLayer layer];
    emitter.frame = self.view.bounds;
    [self.view.layer addSublayer:emitter];

    //configure emitter
    emitter.renderMode = kCAEmitterLayerAdditive;
    emitter.emitterPosition = self.view.center;
    emitter.emitterSize = CGSizeMake(25, 0);

    //create a particle template
    CAEmitterCell *cell = [[CAEmitterCell alloc] init];
    cell.contents = (id)[UIImage imageNamed:@"Sparkle"].CGImage;
    cell.birthRate = 150;
    cell.lifetime = 5.0;
    cell.alphaSpeed = -0.4;
    cell.velocity = 50;
    cell.velocityRange = 50;
    cell.scale = 0.1;
    cell.scaleRange = 0.08;
    cell.emissionRange = M_PI * 2.0;

    emitter.emitterCells = @[cell];
}

按钮点击效果:


按钮点击.gif


初始设置:

CAEmitterCell *emitterCell = [CAEmitterCell emitterCell];
    emitterCell.name = @"explosion";
    emitterCell.alphaRange = 0.2;
    emitterCell.alphaSpeed = -1.0;

    emitterCell.lifetime = 0.7;
    emitterCell.lifetimeRange = 0.2;
    emitterCell.birthRate = 0;
    emitterCell.velocity = 40;
    emitterCell.velocityRange = 10.0;
    emitterCell.scale = 0.05;
    emitterCell.scaleRange = 0.02;
    emitterCell.contents = (id)[UIImage imageNamed:@"Sparkle"].CGImage;

    _explosionLayer = [CAEmitterLayer layer];
    _explosionLayer.name = @"emitterLayer";
    _explosionLayer.emitterShape = kCAEmitterLayerCircle;
    _explosionLayer.emitterMode = kCAEmitterLayerOutline;
    _explosionLayer.emitterPosition = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
    _explosionLayer.emitterSize = CGSizeMake(25, 0);
    _explosionLayer.emitterCells = @[emitterCell];
    _explosionLayer.renderMode = kCAEmitterLayerOldestFirst;
    [self.layer addSublayer:_explosionLayer];

    self.emitterCells = @[emitterCell];

点击执行动画

- (void)startAnimate
{
    if (_animating) {
        return;
    }
    _animating = YES;
    [self performSelector:@selector(explode) withObject:nil afterDelay:0.2];
}

- (void)explode
{
    _explosionLayer.beginTime = CACurrentMediaTime();
    [_explosionLayer setValue:@500 forKeyPath:@"emitterCells.explosion.birthRate"];
    [self performSelector:@selector(stop) withObject:nil afterDelay:0.1];
}

- (void)stop
{
    _animating = NO;
    [_explosionLayer setValue:@0 forKeyPath:@"emitterCells.explosion.birthRate"];
}

CAReplicatorLayer

CAReplicatorLayer 可以多次拷贝某个layer,然后重新布局,实现动画效果。
多个视图绕Y轴旋转,可以做loading效果:


旋转.gif

主要代码:

- (void)setup
{
    CGFloat margin = 5.0;
    CGFloat width = self.layer.bounds.size.width;
    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];
    [self.layer addSublayer:replicatorLayer];

    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:@"scaleAnimation"];

}

水波纹效果,类似QQ语音通话和支付宝的咻咻咻


水波纹.gif
- (void)setup
{
    self.layer.backgroundColor = [UIColor clearColor].CGColor;
    CAShapeLayer *pulseLayer = [CAShapeLayer layer];
    pulseLayer.frame = self.layer.bounds;
    pulseLayer.path = [UIBezierPath bezierPathWithOvalInRect:pulseLayer.bounds].CGPath;
    pulseLayer.fillColor = [UIColor redColor].CGColor;
    pulseLayer.opacity = 0.0;

    CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
    replicatorLayer.frame = self.bounds;
    replicatorLayer.instanceCount = 8;
    replicatorLayer.instanceDelay = 0.5;
    [replicatorLayer addSublayer:pulseLayer];
    [self.layer addSublayer:replicatorLayer];

    CABasicAnimation *opacityAnima = [CABasicAnimation animationWithKeyPath:@"opacity"];
    opacityAnima.fromValue = @(0.3);
    opacityAnima.toValue = @(0.0);

    CABasicAnimation *scaleAnima = [CABasicAnimation animationWithKeyPath:@"transform"];
    scaleAnima.fromValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 0.0, 0.0, 0.0)];
    scaleAnima.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0.0)];

    CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
    groupAnima.animations = @[opacityAnima, scaleAnima];
    groupAnima.duration = 4.0;
    groupAnima.autoreverses = NO;
    groupAnima.repeatCount = HUGE;
    [pulseLayer addAnimation:groupAnima forKey:@"groupAnimation"];
}

animation.gif
- (void)setup
{
    CGFloat margin = 5.0;
    CGFloat cols = 3;
    CGFloat width = self.layer.bounds.size.width;
    CGFloat dotW = (width - margin * (cols - 1)) / cols;

    CAShapeLayer *dotLayer = [CAShapeLayer layer];
    dotLayer.frame = CGRectMake(0, 0, dotW, dotW);
    dotLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, dotW, dotW)].CGPath;
    dotLayer.fillColor = [UIColor redColor].CGColor;

    CAReplicatorLayer *replicatorLayerX = [CAReplicatorLayer layer];
    replicatorLayerX.frame = CGRectMake(0, 0, width, width);
    replicatorLayerX.instanceDelay = 0.3;
    replicatorLayerX.instanceCount = cols;
    [replicatorLayerX addSublayer:dotLayer];

    CATransform3D transform = CATransform3DTranslate(CATransform3DIdentity, dotW + margin, 0, 0);
    replicatorLayerX.instanceTransform = transform;
    transform = CATransform3DScale(transform, 1, -1, 0);

    CAReplicatorLayer *replicatorLayerY = [CAReplicatorLayer layer];
    replicatorLayerY.frame = CGRectMake(0, 0, width, width);
    replicatorLayerY.instanceDelay = 0.3;
    replicatorLayerY.instanceCount = 3;
    [replicatorLayerY addSublayer:replicatorLayerX];

    CATransform3D transforY = CATransform3DTranslate(CATransform3DIdentity, 0, dotW + margin, 0);
    replicatorLayerY.instanceTransform = transforY;


    [self.layer addSublayer:replicatorLayerY];
//    [self.layer addSublayer:replicatorLayerX];

    //添加动画
    CABasicAnimation *opacityAnima = [CABasicAnimation animationWithKeyPath:@"opacity"];
    opacityAnima.fromValue = @(0.3);
    opacityAnima.toValue = @(0.3);

    CABasicAnimation *scaleAnima = [CABasicAnimation animationWithKeyPath:@"transform"];
    scaleAnima.fromValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0.0)];
    scaleAnima.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 0.2, 0.2, 0.0)];

    CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
    groupAnima.animations = @[opacityAnima, scaleAnima];
    groupAnima.duration = 1.0;
    groupAnima.autoreverses = YES;
    groupAnima.repeatCount = HUGE;
    [dotLayer addAnimation:groupAnima forKey:@"groupAnimation"];
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS动画 ---特殊Layer动画 的相关文章

  • 解决pip更新问题.WARNING: You are using pip version 19.2.3, however version 20.2.1 is available.

    一开始遇到这个问题在网上找了很多发现解决不了问题的根本 一开始我以为是网络的问题 后来一直是这样 然后有大佬告诉我你可能python版本太高了 他说卸载了换3 7的 3 8的很多功能都用不了 不过这样是很麻烦的 因为之前也安装了一些库 如果
  • 云服务器上Wamp搭建网站

    说明 想要在云服务器搭建网站 且需要被外网访问浏览的苦逼程序员可以参考本文 前提是你已经购买好了服务器以及公网IP 近一个月买了3次服务器 使用wamp搭建了3次网站了 本以为最后一次会轻车熟路 但是东搞西搞还是花了1个多小时 看来还是要把
  • (附源码)python+mysql+基于协同过滤算法的书籍推荐 毕业设计101555

    摘 要 21世纪的今天 随着社会的不断发展与进步 人们对于信息科学化的认识 已由低层次向高层次发展 由原来的感性认识向理性认识提高 管理工作的重要性已逐渐被人们所认识 科学化的管理 使信息存储达到准确 快速 完善 并能提高工作管理效率 促进
  • “晓白”学python-科普篇(3)-那些和python相关的岗位之python-web开发工程师

    老袁啊 python有这么广泛的应用 那我学好python能不能找到一份和python相关的工作呢 晓白问道 老袁听了回答道 你这个问题太笼统了 实际上你想问的是两个问题 一个就是那个工作岗位和python是相关的 第二个就是这些工作岗位对
  • nginx 正向代理 配置 http 和 https

    nginx 正向代理 配置 http 和 https 应用场景 同学A 所在公司对外网有所限制 借助云服务器nginx正向代理 实现正常浏览公网资料 服务端 云服务器 安装nginx cd usr local wget http nginx
  • Vue3内置组件teleport详解

    teleport的作用 该组件可以将指定内容渲染到特定容器中 而不受 DOM 层级的限制应用场景 当蒙层内容在一个组件中时 蒙层内容是无法遮挡住全部内容的 因此 需要使用teleport将蒙层内容渲染到更全局的组件中 如果不使用telepo
  • python入门(二)——数据类型

    目录 一 数字类型 二 字符串 例题1 凯撒密码 例题2 星号三角形 三 time模块 人家说合格的程序员要养成经常写博客的习惯 嗯 我正在培养中 日积月累 希望自己能坚持下去 一 数字类型 1 整数 与往常的C C 等语言的不同是 pyt
  • python为什么没有指针_Python的指针:有什么意义?

    Python部落 python freelycode com 组织翻译 禁止转载 欢迎转发 目录为什么Python没有指针 Python中的对象 不可变对象和可变对象 了解变量C的变量 Python的名称 关于Python的预实现对象的注释
  • slect( )、poll( )、epoll( )函数详解

    1 slect 函数 1 1 函数原型 include
  • QT 手动建立 带参数的信号槽

    在QT中 如果直接使用UI 在控件上点击槽函数自动建立信号槽及槽函数是非常方便的 但是 有时候 我们会采用全代码 动态建立窗口和控件 这个时候就需要手动方式来建立控件的槽函数 方法如下 1 首先在window h头文件中添加 public
  • Java中多态的实现机制

    多态性是面向对象程序设计代码重用的一个重要机制 我们曾不只一次的提到Java多态性 在Java运行时多态性 继承和接口的实现一文中 我们曾详细介绍了Java实现运行时多态性的动态方法调度 今天我们再次深入Java核心 一起学习Java中多态
  • JavaScript 错误处理

    错误处理 一 What 什么是错误处理 错误是指导致系统不能按照用户意图工作的一切原因 事件 在程序设计过程中 由于某些错误的存在 致使程序无法正常运行 处理这些错误以使程序正确运行就称为错误处理 错误处理功能是衡量编译器性能的重要方面 它
  • elasticsearch 出现 cluster_block_exception read_only_allow_delete问题

    做爬虫的时候 只是简单的存入elasticsearch中 在测试服务器上结果发现老是插入不进去 提示的错误 logstash outputs elasticsearch retrying failed action with respons
  • java数组经典题目:数3退1;每数到3就退出一个人,求最后剩下一个人的编号;

    import java util Arrays public class Tes public static void main String args 数3退1 每数到3就退出一个人 求最后剩下一个人的下标 boolean people
  • 竞赛:STL之vector用法详解(关于vector这一篇就够了!)

    目录 前言 一 什么是vector 二 vector常见的函数 1 函数说明表 2 vector的存储和遍历 构造vector的四种方法 3 vector的插入 删除 insert的几种形式 erase的用法 4 begin函数和front
  • 【目标检测】Fast R-CNN详解

    前言 Fast R CNN是作者Ross Girshick继R CNN后的又一力作 同样使用VGG16作为网络的骨架 在训练速度比R CNN快了近9倍 测试速度快了213倍 在Pascal VOC数据集上accuracy从62 提升至66
  • Java8中Map的遍历方式总结

    public class LambdaMap private Map
  • 核方法计算

    什么是核方法 往简单里说 核方法是将一个低维的线性不可分的数据映射到一个高维的空间 并期望映射后的数据在高维空间里是线性可分的 我们以异或数据集为例 在二维空间中 异或数据集是线性不可分的 但是通过将其映射到三维空间 我们可以非常简单地让其
  • Unity—反向动力学IK

    每日一句 人生最精彩的不是实现梦想的瞬间 而是坚持梦想的过程 目录 定义 准备 API 设置IK 头部IK 设置人物的头部根据视角旋转 手脚IK 案例 脚步IK 定义 一般来说 骨骼动画都是传统的从父节点到子节点的带动方式 即正向动力学 I

随机推荐