弹幕实现
更新日期:
好久不写博客了,罪过罪过,这几个月真是忙成狗了。最近做业务的时候需要实现个简单的弹幕效果,发现一些比较有意思的玩法,这边记录一下。
思考-如何实现弹幕
我们先抛开弹幕,来看看现实生活中的一个场景。
什么场景呢,就是一台舞台剧的拍摄过程。
我们先看看拍一个舞台剧需要准备哪些东西:
- 首先需要一个舞台
- 还需要有个剧本,剧本规定了这个剧该怎么演
- 然后需要一大堆演员,每个演员要自己化妆,确定自己什么时候上场
- 再然后需要个导演,导演负责整个流程的控制叫演员上场表演
首先我们需要知道,一场舞台剧是分好几个场次的。有的演员在第一场,有的演员在第二场,每个演员的身份装扮也都是不同的。
在开场之前,需要做些前期准备,比如舞台装扮,还有跟演员说戏。
什么是说戏呢?
导演会先让演员看剧本,先装扮好。然后跟演员说:那个xxx你是第二场上,xxx第一场。到时我会提醒你们第几场开始了,你们要注意听。
说完戏之后,舞台剧就开始演了。
每开始一个场次,导演就喊:第xx场开始了,这个场次的演员注意上场。然后演员听到后就会找到时机上场。
整个舞台剧就这样按流程表演了。
为什么要说这个例子呢,因为我发现,弹幕跟这个就是一回事。
每一条弹幕其实就是一个演员,我们再搞一个调度者导演,来控制弹幕的出场。导演的说戏其实就是每个演员添加针对导演的事件监听。
开始动手实现
为了方便,下面所有代码基于jQuery实现
我们先确定需要的元素:
1.我们需要个舞台
1 2 3 4 5 6 7 8 | <div id="J_stage"></div> <script type="text/javascript"> //舞台是全局变量 var stage = $('#J_stage'); </script> |
2.我们需要个剧本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | var playList = [{ //从何时开始 time:0, //经过的时间 duration:4292, //舞台偏移的高度 top:10, //弹幕文字大小 size:16, //弹幕颜色 color:'#000', //内容 text:'前方高能注意' },{ //从何时开始 time:100, //经过的时间 duration:4192, //舞台偏移的高度 top:100, //弹幕文字大小 size:14, //弹幕颜色 color:'#333', //内容 text:'我就是路过看看。。' },{ //从何时开始 time:170, //经过的时间 duration:6192, //舞台偏移的高度 top:130, //弹幕文字大小 size:16, //弹幕颜色 color:'#00ff00', //内容 text:'我就静静的看着你装逼。。' },{ //从何时开始 time:1000, //经过的时间 duration:5992, //舞台偏移的高度 top:150, //弹幕文字大小 size:20, //弹幕颜色 color:'#ff0000', //内容 text:'我和我的小伙伴都惊呆了~~' }] //弹幕的总时间(演出总时间) var Time = 9000; //检测时间间隔(每一场的时间) var CheckTime = 1000; //总场数 var PlayCount = Math.ceil(Time / CheckTime); |
剧本很简单,包括演出的总时间,每一场的时间,还有具体的每个演员的表演内容,规定了每个演员的入场时间(time),表演的时间(duration),还有入场的位置(top),还有演员的妆容(size,color,text)
3.我们还需要演员
作为一名合格的演员,需要具备那些素质呢?
我们创建个演员的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | //构造函数,传递一个剧本片段 var Actor = function(play){ //保存剧本的副本 this.play = play; //给自己化妆 this.appearance = this.makeUp(); //自己走上舞台旁边准备上场 this.appearance.hide().appendTo(stage); } //演员化妆,也就是最终呈现的样子 Actor.prototype.makeUp = function() { var appearance = $('<div style="min-width:400px;font-size:'+this.play.size +';color:'+this.play.color+';">'+this.play.text+'</div>'); return appearance; } //演员上场飘过 Actor.prototype.animate = function() { var that = this; var appearance = that.appearance; var mywidth = appearance.width(); //使用动画控制left appearance.animate({ left:-mywidth }, that.play.duration,'swing',function(){ appearance.hide(); }); } //演员开始表演 Actor.prototype.perform = function() { var that = this; var appearance = that.appearance; //准备入场,先隐藏在幕布后面 appearance.css({ position:'absolute', left: stage.width()+'px', top:that.play.top||0, zIndex:10, display:'block' }); //确定入场偏移时间,入场表演 //导演只会说第几场开始了,可不会还帮你具体到某个时间点,所以需要你自己计算好入场的时间。 var delayTime = that.play.time - (that.play.session-1) * CheckTime; //演员需要修正自己上场的时间 setTimeout(function(){ that.animate(); },delayTime) } |
演员类还是比较简单,构造函数调用后演员自己会化好妆等待入场。并且暴露出表演的方法perform。每个演员需要监听导演。当导演说了某个场次开始后,记得关注,入场表演即可。
4.好了我们还需要个导演,非常重要的调度者
导演需要具有事件机制,也就是我们常说的观察者模式,因为我们使用了jQuery,所以有现成的可以用:
1 2 | //这样我们就得到了一个支持事件机制的对象。 var director = $({}); |
这样所有的元素都已经齐全了,下面我们开始进行戏剧的前期准备过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | //准备舞台(这个上面其实已经说了) var stage = $('#J_stage'); stage.css({ position:'relative', overflow:'hidden' }) //导演开始说戏过剧本 //整理playList列表,组装事件 $.each(playList,function(k,play){ //确定演员,确定场次 var session = Math.ceil(play.time / CheckTime); play.session = session; //剧本拿给演员,召唤一个演员 var actor = new Actor(play); //演员针对导演添加监听。 //等导演说了这个场次后,就开始叫演员表演 director.on(session+'start',function(){ actor.perform(); }) }) |
说戏也说完了,下面就开始正式表演啦:
1 2 3 4 5 6 7 8 9 10 11 12 13 | currentSession = 0; setInterval(function(){ //第xx场开始表演 director.trigger(currentSession+'start'); //从头再来一遍 if (currentSession === PlayCount) { currentSession = 0; }else{ currentSession++; } },CheckTime); |
最终结果如下:
结语
其实可做的事情还很多,后来还增加了不少功能,比如弹幕的停止,继续。以及其他一些高级功能,但是受限于篇幅,就不往下扩展了。写在端午节晚上,明天还要继续苦逼的加班,anyway端午节快乐。