前几天突然想做一个像BiliBIli的弹幕系统,原来想法是视频外套一个div,然后div创建弹幕元素P标签飘过实现,后来发现太卡了,就用canvas实现,后来发现一个问题,

我的实现原理就是id为con的父元素div包住两个元素,一个是绘制弹幕的canvas,一个是video视频,

父元素相对定位,canvas和video绝对定位并且宽度都为100%;高度也为100%,这样父元素变大变小,这两个元素也会一起变。

但是我在video全屏的时候把canvas的z-index调到最大,还是无法覆盖住,后来才了解到video全屏的时候,层级比z-index本身还大,所以没有效果,那么怎么实现全屏呢?很简单,把你video的父元素全屏不就行了,这项层级就相同了,canvas就可以覆盖了。

文件头和style部分,

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, shrink-to-fit=no">
        <title>腾讯云视频全屏弹幕示例</title>
        <!--腾讯云点播需要的js和css,用户不用加 !-->
        <link href="http://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.css" rel="stylesheet">
        <script src="http://imgcache.qq.com/open/qcloud/video/tcplayer/lib/hls.min.0.8.8.js"></script>
        <script src="http://imgcache.qq.com/open/qcloud/video/tcplayer/tcplayer.min.js"></script>
         <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
        <!--腾讯云点播需要的js和css,用户不用加 !-->
    </head>
    <style type="text/css">
 *{
          margin: 0;
              padding: 0;
          }
          html,body{
              width: 100%;
              height: 100%;
          }
    .video-wrapper {
        position: relative;
        width: 640px;
        height:500px;
        margin: auto;
    }
    #canvasBarrage {
        position: absolute;
         width: 100%;
       height: 100%;
        z-index: 2147483647;
        pointer-events: none;
    }
#videoBarrage {
    position: absolute;
  background-color: black;
    width: 100%;
    height: 100%;
  outline: 1px solid #eee;
}

@keyframes bgColor {
        25% {
            background-color: darkred;
        }
        50% {
            background-color: darkgreen;
        }

100% {
            background-color: darkblue;
        }
    }
    </style>

body部分在下面。

</html>

body部分,实现原理就是id为con的父元素div包住两个元素,一个是绘制弹幕的canvas,一个是video视频,

父元素相对定位,canvas和video绝对定位并且宽度都为100%;高度也为100%,这样父元素变大变小,这两个元素也会一起变。

<body>
    <div id="con" class="video-wrapper">
        <canvas  id="canvasBarrage"></canvas>
         <video id="videoBarrage" preload="auto"></video>
    </div>
      <input id="input" name="value" required>
    <button id="submit" disabled>发送弹幕</button>
    <button  id ="full">全屏</button>

</body>

JS部分(我使用的是第三方的腾讯云点播,就是视频上传给腾讯云保管,可以节省服务器空间,当然你也可以使用html的video标签实现本地播放,都是一样的,只是相关的事件不一样,例如我的例子都是腾讯云点播文档的,可以改成你的就可以了,都是基于video标签播放的)

<script>
        var canvasBarrage = function(canvas, data) {
        var currentTime ;//放在最前面定义视频时长变化赋值,这个是获取我视频播放的秒数
        var video = document.getElementById('videoBarrage');
            if (!canvas || !data || !data.length) {
                return;
            }
            if (typeof canvas == 'string') {
                canvas = document.querySelector(canvas);
                canvasBarrage(canvas, data);
                return;
            }
            var context = canvas.getContext('2d');
            canvas.width = canvas.clientWidth;
            canvas.height = canvas.clientHeight;
          function Barrage(obj, index) {
            // 随机x坐标也就是横坐标,对于y纵坐标,以及变化量speed
            this.x = canvas.width;
            this.y = canvas.height * Math.random();
            this.speed = 2;
            this.isShow = true;
            this.opacity = 0.8;
            this.text = obj.value || '';
            this.time = obj.time;
            this.color = obj.color || 'red';
            this.fontSize = obj.fontSize;
            console.log(this.fontSize)
        };
        
        Barrage.prototype.draw = function() {
            var text = this.text;
            // 根据此时x位置绘制文本
            context.strokeStyle = this.color;
            context.font = 'bold  '+this.fontSize+'px "microsoft yahei", sans-serif';
            context.fillStyle = 'rgba(255,255,255, '+this.opacity+'})';
            context.fillText(text, this.x, this.y);
            context.strokeText(text, this.x, this.y);
        }
          var store = {};
        data.forEach((item,i) => {
            store[i] = new Barrage(item, i);
        });
        // 绘制弹幕文本
        var drawAll = function() {
    for (var i in store) {
                var barrage = store[i];
                if (currentTime > barrage.time && barrage.isShow) {
                    barrage.x -= barrage.speed;
                    store[i].draw();
                }
            }
        }; 
        //这个是我使用了第三方技术腾讯云点播时要创建的video对象,不用使用,如果你只想用video标签实现本地播放,下面的播放器事件替换成你的video播放器事件就好了,例如<video>标签的播放暂停事件等.
    var player = TCPlayer("videoBarrage", { // player-container-id 为播放器容器ID,必须与html中一致
     fileID: "秘密哦", // 请传入需要播放的视频filID 必须
     appID: "秘密哦", // 请传入点播账号的appID 必须
     autoplay: false //是否自动播放
     //其他参数请在开发文档中查看
 });

//播放器事件

//这个是我腾讯云点播播放器的暂停事件,替换成你的
 player.on('pause', function(){
    isPause = true;  //isPause 就是弹幕播放时用来判断你的视频是否暂停了,暂停就不播放弹幕.,用来实现暂停弹幕不播放的效果的判断值
    });
    
    //这个是我腾讯云点播播放器的播放事件,替换成你的
    player.on('play', function(){
        isPause = false;//isPause 就是弹幕播放时用来判断你的视频是否暂停了,暂停就不播放弹幕.
        render();
        });
        
        
    function getreqfullscreen (root) {//获取全屏
    var root = document.documentElement
    return root.requestFullscreen || root.webkitRequestFullscreen || root.mozRequestFullScreen || root.msRequestFullscreen
        }
        var fullscreen = getreqfullscreen();
        document.getElementById('full').οnclick=function() {//全屏按钮点击事件
            fullscreen.call(document.getElementById("con"));//全屏id为con的元素,即video的父元素
        }
        //这个是我播放时长条改变事件,currentTime就是我的当前播放秒数
    player.on('timeupdate', function(){
         currentTime = Math.round(player.currentTime());
    });
 
 //这个是我的播放器长度条改变触发事件,
 player.on('seeked', function(){
     currentTime = Math.round(player.currentTime());
     console.log(currentTime)
     reset();//实现拖动视频条,弹幕也会改变
    });

var reset = function() {//重绘弹幕,实现拖动视频条,弹幕也会随之改变
                  context.clearRect(0, 0, canvas.width, canvas.height);
                    for (var i in store) {
                        var barrage = store[i];
                        if (currentTime > barrage.time) {//currentTime为播放器事时间,大于弹幕时间时,重新绘制弹幕,这样拖动视频条,弹幕也会重绘.
                            console.log('判断出来')
                            barrage.isShow = false;
                        } else {
                            store[i].x = canvas.width;
                        }
                    }
                }

//退出全屏事件
       function exitFullscreen() {
    var de = document;
    if (de.exitFullscreen) {
        de.exitFullscreen();
    } else if (de.mozCancelFullScreen) {
        de.mozCancelFullScreen();
    } else if (de.webkitCancelFullScreen) {
        de.webkitCancelFullScreen();
    }
}

var input = document.getElementById('input');
      var submitBtn = document.getElementById('submit');//发送弹幕
             var status =1;
             var status1 = 1;
             var video=document.getElementById("con");
             var canvas = document.getElementById('canvasBarrage');
             var Ba=document.getElementById('videoBarrage');
                $(document).keyup(function(e){
                var key =  e.which || e.keyCode;;
                if(key == 27){
                    console.log('退出全屏')
                    exitFullscreen();
                }
            });
     
      input.addEventListener('input', () => {//判断 弹幕不能空
          if (input.value.trim()) {
              submitBtn.disabled = false;
          } else {
              submitBtn.disabled = true;
          }
      });

submitBtn.addEventListener('click', (event) => {//发送按钮
        event.preventDefault();
      //把弹幕push进去到data里,data为弹幕组
        data.push({
            value: input.value,
            time: currentTime
        });
     
        input.value = '';
        submitBtn.disabled = true;
            console.log(data);
            render();
     });
    var render = function() {
        context.clearRect(0, 0, canvas.width, canvas.height);
        drawAll();
        if (!isPause) {
            requestAnimationFrame(render);
        }
    };
     var add = function(obj) {//暴露接口返回add,render
                store[Object.keys(store).length] = new Barrage(obj);
            };

return {
                    add,
                    render
     }
    var barrage = canvasBarrage('#canvasBarrage', data);
barrage.render();
    }

//弹幕组
var data = [{
            value: '我是第一秒',
            color: 'red',
            fontSize: 35,
             time: 1
        }, {
            value: '我是第二秒',
            color: 'blue',
            fontSize: 35,
             time: 2
        }, {
            value: '我是第三秒',
            color: 'yellow',
            fontSize: 35,
             time: 3
        }, {
            value: '我是第四秒',
            color: 'yellow',
            fontSize: 35,
             time: 4
        }, {
            value: '我是第五秒',
            color: 'yellow',
            fontSize: 35,
             time: 5
        }, {
            value: '我是第六秒',
            color: 'yellow',
            fontSize: 35,
             time: 6
        }, {
            value: '我是第七秒',
            color: 'yellow',
            fontSize: 35,
             time: 7
        }, {
            value: '我是第八秒',
            color: 'yellow',
            fontSize: 35,
             time: 8
        }]
    
     canvasBarrage('#canvasBarrage', data);

</script>

效果图

全屏

那么有人问了,你这没用啊,全屏按钮在外面,我想要的是视频里面有个全屏,

关于这个很简单,你审查video标签下的全屏按钮在哪里,然后禁用video的全屏属性,然后在查找他的父元素,对其添加你的全屏按钮就可以了。我已经实现了。

canvas+html实现视频弹幕,可以全屏实现相关推荐

  1. 设置网页打开默认全屏_微信公众号里的视频不能进行全屏播放的解决方法

    我们手机版的微信视频,发现视频播放只能竖屏播放,点击右下角对放大按钮也是如此,网页版也是小窗口播放,而视频这样显示特别影响我们的观看感受, 下面说下微信公众号里的视频不能进行全屏播放的解决方法. 1. ...

  2. Chromium为视频标签 video 全屏播放的过程分析

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 在Chr ...

  3. Chromium为视频标签video全屏播放的过程分析

    在Chromium中,<video>标签有全屏和非全屏两种播放模式.在非全屏模式下,<video>标签播放的视频嵌入在网页中显示,也就是视频画面作为网页的一部分显示.在全屏模式 ...

  4. iOS12网页视频播放点击全屏按钮会导致闪退

    最近在app中有一个h5界面,是一个视频播放的列表,然后在iOS12的手机上发生了如下几个问题: 第一,自动全屏播放,这个问题历来就有,很好解决: 第二,全屏后取消全屏,状态栏消失: 第三,多个视频间 ...

  5. Android 使用WebView 实现播放爱奇艺视频,可全屏(使用的腾讯的X5内核) (一)

    项目中有个需求,播放爱奇艺的视频,百度了一通,可能是搜索词有问题,没找到解决方法,后来无意中发现微信可以播放,就想到是否可以使用微信的x5内核,一试发现可以实现.想要实现的效果如下,点击全屏后全屏播放 ...

  6. 手持弹幕(全屏文字滚动)

    手持弹幕(全屏文字滚动)效果测试(如图) 可以搜下小程序;滚屏神器 奉上小程序代码: wxml: <!--pages/02-23/demo1/newDanMu.wxml--> <vi ...

  7. Canvas + WebSocket实现视频弹幕

    页面布局 首先,我们需要实现页面布局,在根目录创建 index.html 布局中我们需要有一个 video 多媒体标签引入我们的本地视频,添加输入弹幕的输入框.确认发送的按钮.颜色选择器.字体大小滑动 ...

  8. android x5获取播放地址,Android 使用WebView 实现播放爱奇艺视频,可全屏(使用的腾讯的X5内核) (一)...

    Android 使用WebView 实现播放爱奇艺视频,可全屏(使用的腾讯的X5内核) (一) 发布时间:2018-06-27 18:30, 浏览次数:1438 , 标签: Android WebVi ...

  9. html5微信视频禁止自动全屏,关于HTML5 video标签在安卓版微信浏览器内被强行全屏播放的问题...

    最近在一个H5项目中,碰到了传说中的video标签在安卓版微信浏览器内被强行全屏播放问题.原计划在视频播放完毕后,页面出现video的ended事件时,应该显示分享和处于转化页的按钮,如图: 然而在这 ...

最新文章

  1. 移动IM开发指南3:如何优化登录模块
  2. UI Automation
  3. oracle 填入编号,sql – 带填充模式的Oracle to_char格式编号(FM0000)
  4. Hive Shell 常用命令
  5. ElasticSearch创建、修改、获取、删除、索引Indice mapping和Index Template案例
  6. CF888G XOR-MST 最小异或生成树
  7. python字符串格式化_Python3 字符串格式化
  8. 共享白板程序源代码_[源码和文档分享]QT实现的基于TCP Socket的共享白板
  9. 5-顺序表查找及插入问题
  10. 连续时间系统的s域分析(Matlab)
  11. 网易新闻 鸿蒙,本报记者体验华为首款鸿蒙产品
  12. 开源爬虫框架各有什么优缺点?
  13. 业务系统--业务架构转化成为IT应用的中间桥梁
  14. iOS 10 的一个重要更新-线程竞态检测工具 Thread Sanitizer
  15. java 经典算法(转)
  16. Mobicomm 2019
  17. cajviewer打不开,卸载重装也于事无补。一分钟解决,亲测有效。
  18. 关于互联网的那些小创意
  19. EXCEL实现表格动态求和与累计求和
  20. 从零开始一键安装TeslaMate

热门文章

  1. Argo CD系列视频图文版之安装 argocd 并运行示例
  2. 孤岛危机保存的文件在哪里?
  3. 如何使用ABP进行软件开发(2) 领域驱动设计和三层架构的对比
  4. 解决Teamviewer密码总是在变的问题
  5. mysql 事件统计_mysql事件统计之PERFORMANCE_SCHEMA基础详解
  6. FP7195转模拟恒流调光芯片在机器视觉光源的应用优势
  7. Jupyter 是什么
  8. 有关华为的七大猜想:或在国内屈居老二
  9. netty解决TCP粘包/拆包导致的半包读写问题的三种方案
  10. HDOJ 5128 The E-pang Palace