实践-跑马灯效果及实现过程解析

前言

最近闲来无事,把自己之前做的一款跑马灯效果做个总结,也算温习了一下相关的知识。


效果

跑.gif

实现过程

  • 设置一个背景ViewA,背景的左右两端加上正方形的颜色渐变的图层。
  • 设置一个上面有gif 和 要显示的文字label的ViewB。
  • 把 ViewB加载在 VIewA上,给ViewB的layer 绘制动画轨迹(贝塞尔曲线),ViewB的layer 添加关键帧动画即可

Paste_Image.png

过程详解

在两段添加渐变图层是为了字体出现、消失时的颜渐隐效果。

  • 渐变图层
 #以下是渐变图层的实现方法
 CAGradientLayer *la = [[CAGradientLayer alloc]init];
 la.frame = gradientView.bounds;      
 [gradientView.layer addSublayer:la];
 NSMutableArray *marray = [NSMutableArray array];
  #colorArray 里是两个颜色 :第一个颜色为背景色,透明度为1,第二个颜色为背景色,透明度为0.这里转化为 CGColor。
  #必须为背景颜色,否则会有效果问题。
  for (UIColor *color in colorArray) {
       [marray addObject:(__bridge id)color.CGColor];
  }
 la.colors = marray;
 #// 设置渐变颜色方向,左上点为(0,0), 右下点为(1,1)
 la.startPoint = CGPointMake(0, 0.5);
 la.endPoint = CGPointMake(1, 0.5);
  • 移动的文字Label
#根据字符串长短,获取跟字符串等长的宽度,设置Label的宽度。默认的是一行铺开的长度。  
_marqueeLbl.font = fnt;
CGSize msgSize = [_marqueeLbl.text sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:fnt,NSFontAttributeName, nil]];
_marqueeLbl.frame = CGRectMake(0, 0, msgSize.width, h);
  • 移动操作
#使用CAKeyframeAnimation,push一个新的VC之后,pop返回时动画停止了,
#只有repeatCount设置为CGFLOAT_MAX, removedOnCompletion属性为 NO 这两个属性一起使用,就可以不出现这样 POP回来动画停止的现象了。
- (void)moveAction
{
    CGRect fr = self.marqueeLbl.frame;
    fr.origin.x = self.frame.size.width;
    self.marqueeLbl.frame = fr;
    
    CGPoint fromPoint = CGPointMake(self.frame.size.width + self.marqueeLbl.frame.size.width/2, self.frame.size.height/2);
    #绘制贝塞尔曲线轨迹,移动前viewB左侧在屏幕的右边,移动后,viewB右侧在屏幕的左边。
    UIBezierPath *movePath = [UIBezierPath bezierPath];
    [movePath moveToPoint:fromPoint];
    [movePath addLineToPoint:CGPointMake(-self.marqueeLbl.frame.size.width/2, self.frame.size.height/2)];

    #设置 “平移”动画
    CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    moveAnim.path = movePath.CGPath;
    #1.2设置动画执行完毕后,不删除动画
    moveAnim.removedOnCompletion  = NO;
    #设置动画的重复次数(设置为最大值)
     moveAnim.repeatCount=MAXFLOAT;
    #设置动画执行时间
    moveAnim.duration = self.marqueeLbl.frame.size.width * self.speedLevel * 0.01;
    # 对图层添加关键帧动画
     [self.marqueeLbl.layer addAnimation:moveAnim forKey:nil];
   }
  • 暂停、重新开始动画
#CALayer通过CAMediaTiming协议实现了一个有层级关系的时间系统.
#除了CALayer,CAAnimation也采纳了此协议,用来实现动画的时间系统. 
#在CA中,有一个Absolute Time(绝对时间)的概念,可以通过CACurrentMediaTime()获得,
#就和座标存在相对座标一样,不同的实现了CAMediaTiming协议的存在层级关系的对象也存在相对时间,经常需要进行时间的转换,
#CALayer提供了两个时间转换的方法:
           - (CFTimeInterval)convertTime:(CFTimeInterval)t fromLayer:(CALayer *)l;
           - (CFTimeInterval)convertTime:(CFTimeInterval)t toLayer:(CALayer *)l;
# beginTime:  如果图层中的动画的beginTime为0,则beginTime会被设定为当前图层的当前时间,使得动画立即开始.
               #如果你想某个直接加入图层的动画稍后执行,可以通过手动设置这个动画的beginTime,
               #但需要注意的是这个beginTime需要为 CACurrentMediaTime()+延迟的秒数,因为beginTime是指其父级对象的时间线上的某个时间,
# timeOffset  :则是active local time的偏移量. 你将一个动画看作一个环,timeOffset改变的其实是动画在环内的起点,比如一个duration为5秒的动画,将timeOffset设置为2(或者7,模5为2),那么动画的运行则是从原来的2秒开始到5秒,
# speed属性   :用于设置当前对象的时间流相对于父级对象时间流的流逝速度, speed越大则说明时间流逝速度越快,那动画也就越快。
-(void)pauseLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
}

-(void)resumeLayer:(CALayer*)layer
{
    CFTimeInterval pausedTime = layer.timeOffset;
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    #不设置的话,不会从上次暂停的位置开始。
    layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime = timeSincePause;
}

layer时间详解

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏儿童编程

天干地支五行八卦的对应关系

19790
来自专栏Ken的杂谈

【系统设置】CentOS 修改机器名

18230
来自专栏FSociety

SQL中GROUP BY用法示例

GROUP BY我们可以先从字面上来理解,GROUP表示分组,BY后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,GROUP BY比较类...

5.2K20
来自专栏儿童编程

儿童创造力教育与编程教育的碰撞——MIT雷斯尼克教授最新理论梗概

儿童编程教育已经在我国各一线二线城市疯狂出现,颇有“烂大街”的趋势。我们不禁要问很多很多问题:

22370
来自专栏儿童编程

《动物魔法学校》儿童学编程Scratch之“外观”部分

导读:本文通过一个案例《动物魔法学校》来学习Scratch语言的“外观”部分。之后通过一系列其他功能的综合运用对作品功能进行了扩展。

19240
来自专栏儿童编程

一张图理清《梅花易数》梗概

学《易经》的目的不一定是为了卜卦,但是了解卜卦绝对能够让你更好地了解易学。今天用一张思维导图对《梅花易数》的主要内容进行概括,希望能够给学友们提供帮助。

32440
来自专栏haifeiWu与他朋友们的专栏

复杂业务下向Mysql导入30万条数据代码优化的踩坑记录

从毕业到现在第一次接触到超过30万条数据导入MySQL的场景(有点low),就是在顺丰公司接入我司EMM产品时需要将AD中的员工数据导入MySQL中,因此楼主负...

30140
来自专栏儿童编程

声音功能让儿童编程更有创造性

导读:Scratch中声音功能非常强大,除了常规的音效,你甚至可以模拟各种乐器的各个发音、设置节拍、休止……如果你愿意,甚至可以用它创作一个交响乐。我们可以引导...

13840
来自专栏儿童编程

我不是算命先生,却对占卜有了疑惑——如何论证“占卜前提”的正确与否

事出有因,我对《周易》感兴趣了很多年。只是觉得特别有趣,断断续续学习了一些皮毛。这几天又偶然接触到了《梅花易数》,觉得很是精彩,将五行八卦天干地支都串联了起来。...

15410
来自专栏儿童编程

什么样的人生才是有意义的人生——没有标准的标准答案

【导读】其实我们可以跳出这个小圈圈去更加科客观地看一下这个世界。在夜晚的时候我们仰望天空,浩瀚的宇宙中整个地球只是一粒浮尘,何况地球上一个小小的人类?在漫长的历...

1.8K50

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励