当前位置:首页 > Web开发 > 正文

Canvas + WebSocket + Redis 实现一个视频弹幕

11-11 Web开发

技术图片

原文出自:https://www.pandashen.com


页面布局

首先,我们需要实现页面布局,在根目录创建 index.html 布局中我们需要有一个 video 多媒体标签引入我们的本地视频,添加输入弹幕的输入框、确认发送的按钮、颜色选择器、字体大小滑动条,创建一个 style.css 来调整页面布局的样式,这里我们顺便创建一个 index.js 文件用于后续实现我们的核心逻辑,先引入到页面当中。

HTML 布局代码如下:

<!-- 文件:index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link href="http://www.mamicode.com/style.css"> <title>视频弹幕</title> </head> <body> <div> <h2>Canvas + WebSocket + Redis 实现视频弹幕</h2> <div> <canvas></canvas> <video src="http://www.mamicode.com/barrage.mp4" controls></video> </div> <!-- 输入弹幕内容 --> <input type="text"> <!-- 添加弹幕按钮 --> <button>发送</button> <!-- 选择文字颜色 --> <input type="color"> <!-- 调整字体大小 --> <input type="range" max="40" min="20"> </div> <script src="http://www.mamicode.com/index.js"></script> </body> </html>

CSS 样式代码如下:

/* 文件:style.css */ #cantainer { text-align: center; } #content { width: 640px; margin: 0 auto; position: relative; } #canvas { position: absolute; } video { width: 640px; height: 360px; } input { vertical-align: middle; }

布局效果如下图:

技术图片

定义接口,构造假数据

我们弹幕中的弹幕数据正常情况下应该是通过与后台数据交互请求回来,所以我们需要先定义数据接口,并构造假数据来实现前端逻辑。

数据字段定义:

value:表示弹幕的内容(必填)

time:表示弹幕出现的时间(必填)

speed:表示弹幕移动的速度(选填)

color:表示弹幕文字的颜色(选填)

fontSize:表示弹幕的字体大小(选填)

opacity:表示弹幕文字的透明度(选填)

上面的 value 和 time 是必填参数,其他的选填参数可以在前端设置默认值。

前端定义的假数据如下:

// 文件:index.js let data = [ { value: "这是第一条弹幕", speed: 2, time: 0, color: "red", fontSize: 20 }, { value: "这是第二条弹幕", time: 1 } ]; 实现前端弹幕的逻辑

我们希望是把弹幕封装成一个功能,只要有需要的地方就可以使用,从而实现复用,那么不同的地方使用这个功能通常的方式是 new 一个实例,传入当前使用该功能对应的参数,我们也使用这种方式来实现,所以我们需要封装一个统一的构造函数或者类,参数为当前的 canvas 元素、video 元素和一个 options 对象,options 里面的 data 属性为我们的弹幕数据,之所以不直接传入 data 是为了后续参数的扩展,严格遵循开放封闭原则,这里我们就统一使用 ES6 的 class 类来实现。

1、创建弹幕功能的类及基本参数处理

布局时需要注意 Canvas 的默认宽为 300px,高为 150px,我们要保证 Canvas 完全覆盖整个视频,需要让 Canvas 与 video 宽高相等。
因为我们不确定每一个使用该功能的视频的宽高都是一样的,所以 Canvas 画布的宽高并没有通过 CSS 来设置,而是通过 JS 在类创建实例初始化属性的时候动态设置。

// 文件:index.js class CanvasBarrage { constructor(canvas, video, options = {}) { // 如果没有传入 canvas 或者 video 直接跳出 if (!canvas || !video) return; this.canvas = canvas; // 当前的 canvas 元素 this.video = video; // 当前的 video 元素 // 设置 canvas 与 video 等高 this.canvas.width = video.clientWidth; this.canvas.height = video.clientHeight; // 默认暂停播放,表示不渲染弹幕 this.isPaused = true; // 没传参数的默认值 let defaultOptions = { fontSize: 20, color: "gold", speed: 2, opacity: 0.3, data: [] }; // 对象的合并,将默认参数对象的属性和传入对象的属性统一放到当前实例上 Object.assign(this, defaultOptions, options); } }

应该挂在实例上的属性除了有当前的 canvas 元素、video 元素、弹幕数据的默认选项以及弹幕数据之外,还应该有一个代表当前是否渲染弹幕的参数,因为视频暂停的时候,弹幕也是暂停的,所以没有重新渲染,因为是否暂停与弹幕是否渲染的状态是一致的,所以我们这里就用 isPaused 参数来代表当前是否暂停或重新渲染弹幕,值类型为布尔值。

2、创建构造每一条弹幕的类

温馨提示: 本文由杰米博客推荐,转载请保留链接: https://www.jmwww.net/file/web/10246.html