美文网首页
弹幕的实现

弹幕的实现

作者: 星星点灯0_0 | 来源:发表于2017-07-02 17:30 被阅读0次

前言

随着视频直播类app的崛起,为了增加用户的粘性以及趣味性,弹幕越来越受到视频类应用或者网站的青睐,下面是两种最常见的弹幕效果


弹幕.jpg
弹幕3.jpg

做为一个开发人员,看到这些酷炫的效果,有时候也难免会想一下这个是怎么实现的?
下面我们来分析一下这种实现
1.弹幕从右往左按照一定的轨迹移动
2.弹幕文字的内容长短不一需要计算
3.一个弹幕进入不久,另外一个弹幕紧接着要进入
4.停止时,需要清空数据,移除弹幕

技术实现:
弹幕可以写一个View类,上面可以添加Lable直接显示文字

1.弹幕移动时,我们需要计算弹幕需要移动的整个距离,计算弹幕运行的速度,并且文字越长运行的速度越快

  //根据定义的duration计算速度
    CGFloat wholeWidth = CGRectGetWidth(self.frame) + kWidth + 50;
    CGFloat speed = wholeWidth/Duration;
    //以及完全进入屏幕的时间
    CGFloat dur = (CGRectGetWidth(self.frame) + 50)/speed;
    
    
    __block CGRect frame = self.frame;
    if (self.moveBlock) {
        //弹幕开始进入屏幕
        self.moveBlock(Start);
    }
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(dur * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        //避免重复,通过变量判断是否已经释放了资源,释放后,不在进行操作
        if (self.bDealloc) {
            return;
        }
        //dur时间后弹幕完全进入屏幕
        if (self.moveBlock) {
            self.moveBlock(Enter);
        }
    });
    
    //弹幕动画移动,出了屏幕后从父视图上移除
    [UIView animateWithDuration:Duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        frame.origin.x = -CGRectGetWidth(frame);
        self.frame = frame;
    } completion:^(BOOL finished) {
        if (self.moveBlock) {
            self.moveBlock(End);
        }
        [self removeFromSuperview];
    }];

2.创建弹幕,处理弹幕在不同状态下的逻辑,这三总状态分别是弹幕开始,弹幕完全进入屏幕,弹幕完全离开屏幕

 //创建一个弹幕view
    BulletView *view = [[BulletView alloc] initWithContent:comment];
    //设置运行轨迹
    view.trajectory = trajectory;
    __weak BulletView *weakBulletView = view;
    __weak BulletManager *myself = self;
      view.moveBlock = ^(CommentMoveStatus status) {
        if (myself.bStopAnimation) {
            return ;
        }
        switch (status) {
            case Start:
                //弹幕开始……将view加入弹幕管理queue
                [self.bulletQueue addObject:weakBulletView];
                break;
            case Enter: {
                //弹幕完全进入屏幕,判断接下来是否还有内容,如果有则在该弹道轨迹对列中创建弹幕……
                NSString *comment = [myself nextComment];
                if (comment) {
                    [myself createBulletComment:comment trajectory:trajectory];
                } else {
                    //说明到了评论的结尾了
                }
                break;
            }
            case End: {
                //弹幕飞出屏幕后从弹幕管理queue中删除
                if ([myself.bulletQueue containsObject:weakBulletView]) {
                    [myself.bulletQueue removeObject:weakBulletView];
                }
                if (myself.bulletQueue.count == 0) {
                    //说明屏幕上已经没有弹幕评论了,循环开始
                    [myself start];
                }

3.当需要弹幕的时候初始化n条弹幕轨迹,我这里初始化3条,每展示一天弹幕,则从本地集合中删除展示的数据,直到所有的数据展示完

    NSMutableArray *arr = [NSMutableArray arrayWithArray:@[@(0), @(1), @(2)]];
    for (int i = 3; i > 0; i--) {
        NSString *comment = [self.tmpComments firstObject];
        if (comment) {
            [self.tmpComments removeObjectAtIndex:0];
            //随机生成弹道创建弹幕进行展示(弹幕的随机飞入效果)
            NSInteger index = arc4random()%arr.count;
            Trajectory trajectory = [[arr objectAtIndex:index] intValue];
            [arr removeObjectAtIndex:index];
            [self createBulletComment:comment trajectory:trajectory];
        } else {
            //当弹幕小于三个,则跳出
            break;
        }
    }

4.如果我们想要从弹幕父视图上查找被点击的视图,我们只需要给self.view添加手势,然后根据手势坐落在弹幕背景视图上的位置,可以查找出被点击的弹幕,从而获得弹幕上的内容

    CGPoint clickPoint =  [gesture locationInView:self];
    BulletView *bulletView = [self findClickBulletView:clickPoint];
    - (BulletView *)findClickBulletView:(CGPoint)point {
    BulletView *bulletView = nil;
    for (UIView *v in [self subviews]) {
        if ([v isKindOfClass:[BulletView class]]) {
            if ([v.layer.presentationLayer hitTest:point]) {
                bulletView = (BulletView *)v;
                break;
            }
        }
    }
    return bulletView;
}

![我的弹幕.png](https://img.haomeiwen.com/i5423128/9a366210619afe83.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

至此,大体功能上是实现了,但是要是面对直播中各种形形色色的弹幕,那肯定还是不够的,这里的demo仅供参考,如有需要,请戳这里~

相关文章

  • Flutter 实现虎牙/斗鱼 弹幕效果

    老孟导读:用Flutter实现弹幕功能,轻松实现虎牙、斗鱼的弹幕效果。 先来一张效果图: 实现原理 弹幕的实现原理...

  • 弹幕组件(一)

    弹幕组件 弹幕组件实现主要为DOM或Canvas实现。主要涉及基本思路。 弹幕组件的设计 弹幕组件可以基本拆分为背...

  • Android弹幕实现现状与原理浅析

    弹幕实现对比 目前的弹幕实现方案,主要有以下几种实现方式。 Android View实现 通过Android已有的...

  • 弹幕刷屏之术——Android无时间线弹幕实现

    弹幕刷屏之术——Android无时间线弹幕实现 标签(空格分隔): Android 今天我们来实现一种普通的弹幕,...

  • js实现简单弹幕并滚动

    1.首先创建弹幕框架 实现弹幕输入和显示 2.js实现输出

  • 弹幕的实现

    前言 随着视频直播类app的崛起,为了增加用户的粘性以及趣味性,弹幕越来越受到视频类应用或者网站的青睐,下面是两种...

  • 实现一个弹幕墙APP

    弹幕墙APP点这里 功能: 实现发射弹幕、清除弹幕、显示弹幕功能。扩展: 用野狗实时后端云来存储弹幕数据。 按照 ...

  • 弹幕的简单实现

    弹幕是即时出现大量评论的形式,因数量极多很像炮弹形成的幕布而得名。下面简单的实现一个弹幕。 弹幕的简单实现以及循环

  • 使用transition实现弹幕滚动效果

    想要实现比较理想的弹幕滚动效果还是有一定难度的。这里以vue为基础,讲一种实现弹幕滚动的方法,不考虑重叠,弹幕过长...

  • 使用canvas实现和HTML5 video交互的弹幕效果

    一、canvas实现弹幕性能较好 从技术实现成本角度讲,要实现弹幕效果,最简单的方法就是DOM+CSS3控制,如果...

网友评论

      本文标题:弹幕的实现

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