飘屏,IM 动画队列的简单例子

飘屏,IM 动画队列的简单例子,第1张

简单介绍: IM 应用中,动画的成分比较重,

例如: 秀场应用

打赏主播,为了体现土豪,需要来一个游艇动画

因为秀场里面的动画,

是用户驱动的。

用户送了礼物,就得播放动画效果。

先送,先播放,

体现了队列的特性

本文介绍,屏幕上的飘屏动画

例如,游戏获奖等

本文来一个,简单的 demo,留言飘屏

类似d幕,比d幕简单

并,有些不同

基本实现: 分为动画视图,和动画队列视图 1, 动画视图 , FloatingView 动画, 从左往右拉,

动画使用 CAKeyframeAnimation

动画的使用,

放在动画视图 , FloatingView 的

- (void)layoutSubviews 方法中,

动画的驱动, 就是能够调用 - (void)layoutSubviews 的方法

[self setNeedsLayout];

也有 FloatingView 添加子视图,

( 第一次添加 UILabel )

为了配合,下面的动画队列视图,

使用 CAKeyframeAnimation 的代理方法,

动画开始:

- (void)animationDidStart:(CAAnimation *)anim;

动画结束:

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;

这样,对于动画队列,

一个结束了,就开始下一个动画

2, 动画队列视图 , FloatingLabel

继承自上面的动画视图,

实现了动画队列,和具体的动画视图 UILabel

动画队列的删

队列,关键在于增删

一个结束,就开始删


     // 当前队列有元素
     if (weakSelf.attributeArr.count) {
            // 删一个动画内容
            [weakSelf.attributeArr removeObject:weakSelf.attributeArr.firstObject];

            if (weakSelf.attributeArr.count != 0) {
                // 驱动动画

                [weakSelf addTrotAttribute:nil];

            }

        }

        // 移除id

        if (weakSelf.tipIdList.count) {
            // 删一个

            [weakSelf.tipIdList removeObjectAtIndex:0];

        }

        

        // 当无id时  说明已全部播放完
        // 动画队列结束

        if (weakSelf.tipIdList.count == 0) {

            dispatch_async(dispatch_get_main_queue(), ^{

                if (weakSelf.giftStopBlock) {

                    weakSelf.giftStopBlock();

                }

            });

        }
队列的元素添加

- (void)addTrotAttribute:(FloatingAttribute *)attribute {

    if (attribute) {
        // 添加动画内容

        [self.attributeArr addObject:attribute];

    }

    FloatingAttribute *trotingAtt = self.attributeArr[self.index];

    if (!_currentLabel) {
        // 第一次,创建展示的视图

        _currentLabel = [[UILabel alloc] init];

        _currentLabel.font = [UIFont systemFontOfSize:14];

        _currentLabel.textColor = UIColor.redColor;

        [self trotingWithAttribute:trotingAtt];

        [self addTrotView:_currentLabel];

    } else if (!self.isTroting) {
            // 状态管理
            // 当前没动画,才驱动新增加的

            [self trotingWithAttribute:trotingAtt];

            [self updateTroting];

    }

}
注意点: 1, 动画的时长控制

就是修改 CAKeyframeAnimation 实例的 duration 字段

计算逻辑


// 文本宽度
CGSize textSize = [att.text sizeWithAttributes:@{NSFontAttributeName: _currentLabel.font}];

    _currentLabel.frame = CGRectMake(0, 0, textSize.width, textSize.height);

    

    __weak typeof(self) weakSelf = self;

    [self troting:^{
        // 文本宽度 + 动画容器的宽度
        // 因为文本从容器的右边,整体移动到左边,消失
        // 速度是,一秒钟前进 40 个 pt
        

        CGSize trotContrinerSize = weakSelf.trotContaierView.frame.size;

            weakSelf.duration = (trotContrinerSize.width + textSize.width) / 40;

    }];
2, 动画停顿

文本的左边,从容器的右边出发,抵达容器的左边后,

停顿 3 秒


        // 容器宽度 + 文本宽度
        CGFloat len = (trotContainerSize.width + trotSize.width);
        // 开始在容器右边, 抵达容器左边,  抵达容器左边, 
        // 文本的右边, 从容器的左边消失

        self.flyingXAnimation.values = @[@(0), @(- trotContainerSize.width), @(- trotContainerSize.width), @(- len)];

        // 停顿三秒
        NSTimeInterval pause = 3.0;
        // 总的时间:每秒跑 40 个 pt + 停顿的时间

        NSTimeInterval total = _duration + pause;
        // 容器的宽度 / 总长度

        NSTimeInterval percent = trotContainerSize.width / len;

        NSTimeInterval widthTime = percent * _duration /total ;
        // 出发的时刻, 
        // 文本左边抵达,容器左边,开始停顿
        // 文本再次出发
        // 文本的右边,消失于容器的左边, 动画结束

        self.flyingXAnimation.keyTimes = @[@0, @(widthTime), @(pause / total + widthTime), @(1)];
github repo

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/994479.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存