XZ_iOS之自定义弹幕的实现

来源:互联网 发布:wpf 漂亮界面 源码 编辑:程序博客网 时间:2024/05/17 21:44

实现的效果图
这里写图片描述

弹幕(barrage),顾名思义是指子弹多而形成的幕布,大量吐槽评论从屏幕飘过时效果看上去像是飞行射击游戏里的弹幕。——来自百度百科
弹幕的特点
1、弹幕可以循环播放
2、弹幕的速度不同
3、弹幕是随机出现的

弹幕的肢解分析
这里写图片描述

弹幕的自动追加的重要的三个节点
1、创建弹幕view开始的时间
2、弹幕view完全进入屏幕
3、弹幕view完全飞出屏幕

初始化弹幕,随机分配弹幕轨迹

// 弹道数组    NSMutableArray *trajectorys = [NSMutableArray arrayWithArray:@[@(0),@(1),@(2),@(3)]];    for (int i = 0; i < 4; i++) { // < trajectorys.count        if (self.bulletComments.count > 0) {            // 通过随机数获取弹幕的轨迹            NSInteger index = arc4random()%trajectorys.count;            int trajectory = [[trajectorys objectAtIndex:index] intValue];            [trajectorys removeObjectAtIndex:index];            // 从弹幕数组中逐一取出弹幕数据            NSString *comment = [self.bulletComments firstObject];            [self.bulletComments removeObjectAtIndex:0];            // 创建弹幕view            [self createBulletView:comment trajectory:trajectory];        }    }

根据弹幕内容和弹幕轨迹创建弹幕

// 初始化XZBulletView    XZBulletView *view = [[XZBulletView alloc] initWithComment:comment];    view.trajectory = trajectory;    [self.bulletViews addObject:view];    __weak typeof(view) weakView = view;    __weak typeof(self) weakSelf = self;    view.moveStatusBlock = ^(MoveStatus status){        if (self.bStopAnimation) { // 如果停止动画,直接return            return;        }        switch (status) {            case Start:            {                // 弹幕开始进入屏幕,将view加入到弹幕管理的变量中bulletViews                [weakSelf.bulletViews addObject:weakView];                break;            }            case Enter:            {                // 弹幕完全进入屏幕,判断是否还有其他内容,如果有则在该弹幕轨迹中创建一个弹幕                NSString *commentNext = [weakSelf nextComment];                if (commentNext) { // 创建新的弹幕                    [weakSelf createBulletView:commentNext trajectory:trajectory];                }                 break;            }            case End:            {                // 弹幕完全飞出屏幕后,从bulletViews中删除,释放资源                if ([weakSelf.bulletViews containsObject:weakView]) {                    [weakView stopAnimation];                    [weakSelf.bulletViews removeObject:weakView];                }                // 循环                if (weakSelf.bulletViews.count == 0) {                    // 说明屏幕上已经没有弹幕,开始循环滚动                    weakSelf.bStopAnimation = YES;                    [weakSelf start];                }                break;            }            default:                break;        }//        // 移出屏幕后销毁弹幕并释放资源//        [weakView stopAnimation];//        [weakSelf.bulletViews removeObject:weakView];    };    // 回调到controller    if (self.generateViewBlock) {        self.generateViewBlock(view);    }

开始弹幕,并在动画完成后,释放掉自己

// 根据弹幕长度执行动画效果    // 根据 v = s/t,时间相同情况下,距离越长,速度就越快;    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;    CGFloat duration = 4.0f;    CGFloat wholeWidth = screenWidth + CGRectGetWidth(self.bounds);    // 弹幕开始    if (self.moveStatusBlock) {        self.moveStatusBlock(Start);    }    // t = s / v;    CGFloat speed = wholeWidth / duration;    CGFloat enterDurartion = CGRectGetWidth(self.bounds) / speed;    // 弹幕的自动追加    [self performSelector:@selector(enterScreen) withObject:nil afterDelay:enterDurartion + 2];    // 因为要改变frame的值,所以要加__block    __block CGRect frame = self.frame;    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{        // 改变x坐标        frame.origin.x -= wholeWidth;        self.frame = frame;    } completion:^(BOOL finished) {        // 动画完成后,释放掉自己        [self removeFromSuperview];        // 回调:知道什么时候释放        if (self.moveStatusBlock) {            self.moveStatusBlock(End);        }    }];

下面附上实现的demo

原创粉丝点击