前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >实践-跑马灯效果及实现过程解析

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

作者头像
進无尽
发布2018-09-12 18:30:31
1K0
发布2018-09-12 18:30:31
举报
文章被收录于专栏:進无尽的文章進无尽的文章

前言

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


效果

跑.gif

实现过程

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

Paste_Image.png

过程详解

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

  • 渐变图层
代码语言:javascript
复制
 #以下是渐变图层的实现方法
 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
代码语言:javascript
复制
#根据字符串长短,获取跟字符串等长的宽度,设置Label的宽度。默认的是一行铺开的长度。  
_marqueeLbl.font = fnt;
CGSize msgSize = [_marqueeLbl.text sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:fnt,NSFontAttributeName, nil]];
_marqueeLbl.frame = CGRectMake(0, 0, msgSize.width, h);
  • 移动操作
代码语言:javascript
复制
#使用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];
   }
  • 暂停、重新开始动画
代码语言:javascript
复制
#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时间详解

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.01.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 效果
  • 实现过程
  • 过程详解
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档