移动web直播,canvas实现弹幕为什么会卡顿,如果同时获取到多条弹幕内容,如何决定每条弹幕内容的出场顺序呢?

如题:实现直播弹幕,如果使用websocket实现即时双向通信,同时获取到多条消息,如何决定每条弹幕内容的出场顺序呢?另外,使用canvas弹幕,速度过慢的时候,弹幕为什么会卡顿呢?
以熊猫直播为例,如何才能实现这种流畅无卡顿的弹幕
https://m.panda.tv/room.html?...
图片描述

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">

    <title>Document</title>
    <script type="text/javascript" src="./jquerymin.js"></script>
    <script type="text/javascript" src="./jquery.barrager.js"></script>
    <script type="text/javascript">


        $(function(){
            $('canvas').barrager([{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"这是我发的。。。"},{"msg":"这个插件真不错"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"}]);
            $('#qc').click(function(){
               $('canvas').barrager("clear");
            });
            $('#tj').click(function(){
                $('canvas').barrager([{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"这是我发的。。。"},{"msg":"这个插件真不错"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"}]);
            });
           setInterval(function(){
                $('canvas').barrager([{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"看着不错。。。。"},{"msg":"哈哈哈。。。。"},{"msg":"不错不错。。"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"},{"msg":"nihao"}]);
            },2000);
        })
    </script>

</head>
<body>
<button id="qc" type="button" style="width: 100px;height: 50px;font-size: 30px;">清除</button>
<button id="tj" type="button" style="width: 100px;height: 50px;font-size: 30px;">添加</button><br>
<canvas style="width: 750px;height: 410px;background:#000;">你的浏览器不支持canvas</canvas>


</body>
</html>

**jquery.barrager.js**

(function($) {
    function Barrager(dom) {
        this.canvas = dom.get(0);
        this.ctx = this.canvas.getContext("2d");
        this.msgs = new Array(300);
        this.width = 750;
        this.height = 410;
        this.canvas.width = this.width;
        this.canvas.height = this.height;
        this.font = "30px 黑体";
        this.ctx.font = this.font;
        this.colorArr = ["#000"];
        this.interval = "";
        this.draw = function() {
            if (this.interval != "") return;
            var _this = this;
            this.interval = setInterval(function() {
                _this.ctx.clearRect(0, 0, _this.width, _this.height);
                _this.ctx.save();
                for (var i = 0; i < _this.msgs.length; i++) {
                    if (!(_this.msgs[i] == null || _this.msgs[i] == "" || typeof(_this.msgs[i]) == "undefined")) {
                        if (_this.msgs[i].L == null || typeof(_this.msgs[i].L) == "undefined") {
                            _this.msgs[i].L = _this.width;
                            _this.msgs[i].T = parseInt(Math.random() * 700);
                            _this.msgs[i].S = parseInt(Math.random() * (10 - 4) + 4);
                            _this.msgs[i].C = _this.colorArr[Math.floor(Math.random() * _this.colorArr.length)];
                        } else {
                            if (_this.msgs[i].L < -200) {
                                _this.msgs[i] = null;
                            } else {
                                _this.msgs[i].L = parseInt(_this.msgs[i].L - _this.msgs[i].S);
                                _this.ctx.fillStyle = _this.msgs[i].C;
                                _this.ctx.fillText(_this.msgs[i].msg, _this.msgs[i].L, _this.msgs[i].T);
                                _this.ctx.restore();
                            }
                        }
                    }
                }
            }, 240);
        };
        this.putMsg = function(datas) {
            for (var j = 0; j < datas.length; j++) {
                for (var i = 0; i < this.msgs.length; i++) {
                    if (this.msgs[i] == null || this.msgs[i] == "" || typeof(this.msgs[i]) == "undefined") {
                        this.msgs[i] = datas[j];
                        break;
                    }
                }
            }
            this.draw();
        };
        this.clear = function() {
            clearInterval(this.interval);
            this.interval = "";
            this.ctx.clearRect(0, 0, this.width, this.height);
            this.ctx.save();
            for (var i = 0; i < this.msgs.length; i++) {
                this.msgs[i] = null;
            }
        };
    }

    $.fn.barrager = function(para) {
        if (typeof(para) == "string") {
            try {
                var api = $(this).data('barrager_api');
                api[para].apply(api);
            } catch (e) {}
        } else if (typeof para == 'object' || !para) {
            $this = $(this);
            if ($this.data('barrager_api') != null && $this.data('barrager_api') != '') {
                var api = $this.data('barrager_api');
                api.putMsg(para);
            } else {
                var api = new Barrager($this);
                $this.data('barrager_api', api);
                api.putMsg(para);
            }
        } else {
            $.error('Method ' + method + ' does not exist on jQuery.barrager');
        }
        return this;
    }
})(jQuery);
阅读 3.9k
3 个回答
this.interval = setInterval(function() {
    _this.ctx.clearRect(0, 0, _this.width, _this.height);
    _this.ctx.save();
    //....
}, 240);

这个插件每个弹幕都用一个定时器做,弹幕多了定时器也就多了就会变得很卡。另外,熊猫直播的弹幕是用flash做的。
每条弹幕内容的出场顺序就以后端传过来的顺序为准。

如果使用websocket实现即时双向通信,同时获取到多条消息,如何决定每条弹幕内容的出场顺序呢?

不用关心顺序,只用关心布局好就可以了。

另外,使用canvas弹幕,速度过慢的时候,弹幕为什么会卡顿呢?以熊猫直播为例,如何才能实现这种流畅无卡顿的弹幕

在字幕不是非常非常非常多的情况下,这里的优化与 canvas 无关。你给的地址,人家是直接用的 css 动画。

不要用setInterval 用requestAnimationFrame 试试,240ms能不卡吗

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题