使用canvas实现一个vue弹幕组件功能


Posted in Javascript onNovember 30, 2018

看B站时,对弹幕的实现产生了兴趣,一开始想到用css3动画去实现,后来感觉这样性能不是很好,查了下资料,发现可以用canvas实现,于是就摸索着写了一个简单的弹幕。

弹幕功能

  1. 支持动态添加弹幕
  2. 弹幕不重叠
  3. 自定义弹幕颜色

效果图

demo 

源码地址

使用canvas实现一个vue弹幕组件功能

前端框架选了比较熟悉的vuejs

弹幕滚动的基本思路就是通过定时器不断地改变弹幕的位置,时时重绘画布。

实现步骤

先加入一个canvas标签,这里有个注意点,关于设备像素比对canvas的影响,会出现绘图模糊。

<canvas width="600" height="600"></canvas> // 如果单纯这样写,canvas会出现模糊
<canvas width="600" height="600" style="width: 300px;height: 300px">
</canvas>
//为了不出现模糊,需要设置canvas的css宽高为上下文宽高的1/devicePixelRatio,
本文是对于devicePixelRatio:2的设备设置的,该值可从window.devicePixelRatio取得。
<canvas ref="hiddenCanvas" width="0" height="0" style="display: none">
</canvas> 
// 后面会用到

我们先定义一个数组来存放弹幕数据,一条弹幕信息,包括文本内容,x,y坐标位置,颜色,速度(可以是随机或者固定,为了计算简单,我们这里采用了固定的速度)

var dmArr = [];
var gap = 80; // 弹幕的上下间距
var hiddenCanvas = this.$refs.hiddenCanvas;
// 增加弹幕的方法
function pushDm(text, color) {
  let y = getY(); // 先确定跑道
  let x = 600; // 初始x坐标为canvas的右边界
  let delayWidth = 0; // 同跑道
  for (let i = 0, len = dmArr.length; i < len; i++) {
    let dm = dmArr[i];
    if (y === dm.y) { // 如果是同跑道,则往后排,设置一定的间隔,保证弹幕不会重叠;
      delayWidth += Math.floor(hiddenCanvas.getContext('2d').measureText(dm.text).width * 4 + 50);
    }  }
  dmArr.push({
    text: text,
    x: x + delayWidth,
    y: y,
    speed: 8,
    color: color || getColor()
  });
}
// 随机获得y坐标
function getY() {
  let range = Math.floor(600 / gap); // 跑道数量
  return Math.floor(Math.random() * range + 1) * gap;
}
// 随机获得颜色
function getColor() {
  return `${Math.floor(Math.random() * 16777215).toString(16)}`;
}
// 写一个for循环,初始化30条弹幕
for (let i = 0; i < 30; i++) {
  pushDm(`It's barrage ${i}`);
}

接下来设置一个20ms的定时器,实现弹幕滚动效果

var timer = null;
var ctx = this.$refs.canvas.getContext('2d');
function start(){
 timer = setInterval(() => {
  ctx.clearRect(0, 0, 600, 600); // 每次需要清空画布
  ctx.save();
  ctx.font = '30px Microsoft YaHei'; // 这里需要把字体大小设为需要显示的css大小的2倍(devicePixelRatio为2时)
  if (!dmArr.length) stop(); // 如果没有新弹幕了,就停止计时器
  for (let i = 0, len = this.dmArr.length; i < len; i++) {
    let dm = dmArr[i];
    let overRange = -ctx.measureText(dm.text).width * 2;
    dm.x -= dm.speed;
    if (dm.x < overRange) {
      dmArr.splice(i, 1); // 弹幕在画布中不可见时,从数组中移除该项
      continue;
    }
    ctx.fillStyle = `#${dm.color}`;
    ctx.fillText(dm.text, dm.x, dm.y);
  }
  ctx.restore();
 }, 20);
}
function stop() {
  clearInterval(timer);
  ctx.clearRect(0, 0, 600, 600);
}

我们还需要一个输入框,来实现手动添加弹幕功能

<input type="text" @keyup.enter="sent" v-model="dmInput" maxlength="20">

<button type="button" @click="sent">发表</button>
var dmInput = '';
var color = ''; // 可自定义弹幕的颜色
function sent() {
  if (!dmInput) return;
  stop();
  pushDm(dmInput, color);
  start();
  dmInput = '';
}

有待改进的地方和疑问?速度不恒定时,怎么保持弹幕不重叠视频弹幕是根据弹幕发送时间点来定位到视频的每一帧?如何实现?

总结

以上所述是小编给大家介绍的使用canvas实现一个vue弹幕组件功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js中eval()函数和trim()去掉字符串左右空格应用
Feb 02 Javascript
jQuery写的日历(包括日历的样式及功能)
Apr 23 Javascript
JavaScript中变量声明有var和没var的区别示例介绍
Sep 15 Javascript
javascript自定义in_array()函数实现方法
Aug 03 Javascript
AngularJS 如何在控制台进行错误调试
Jun 07 Javascript
详解利用 Express 托管静态文件的方法
Sep 18 Javascript
vue 解决循环引用组件报错的问题
Sep 06 Javascript
KOA+egg.js集成kafka消息队列的示例
Nov 09 Javascript
jQuery实现文本显示一段时间后隐藏的方法分析
Jun 20 jQuery
layui动态渲染生成左侧3级菜单的方法(根据后台返回数据)
Sep 23 Javascript
ESLint 是如何检查 .vue 文件的
Nov 30 Vue.js
解决基于 keep-alive 的后台多级路由缓存问题
Dec 23 Javascript
VUE基于NUXT的SSR 服务端渲染
Nov 30 #Javascript
Nuxt.js开启SSR渲染的教程详解
Nov 30 #Javascript
基于JavaScript实现每日签到打卡轨迹功能
Nov 29 #Javascript
Next.js项目实战踩坑指南(笔记)
Nov 29 #Javascript
js canvas实现二维码和图片合成的海报
Nov 19 #Javascript
详解@angular/cli 改变默认启动端口两种方式
Nov 29 #Javascript
js实现每日签到功能
Nov 29 #Javascript
You might like
php strcmp使用说明
2010/04/22 PHP
php版微信公众平台入门教程之开发者认证的方法
2016/09/26 PHP
php中static和const关键字用法分析
2016/12/07 PHP
JavaScript与C# Windows应用程序交互方法
2007/06/29 Javascript
Javascript中的变量使用说明
2010/05/18 Javascript
解决JS浮点数运算出现Bug的方法
2013/03/12 Javascript
jquery中获取id值方法小结
2013/09/22 Javascript
JavaScript实现把rgb颜色转换成16进制颜色的方法
2015/06/01 Javascript
javascript实现全角半角检测的方法
2015/07/23 Javascript
js点击文本框弹出可选择的checkbox复选框
2016/02/03 Javascript
JS for循环中i++ 和 ++i的区别介绍
2016/07/20 Javascript
AngularJs 指令详解及示例代码
2016/09/01 Javascript
JavaScript实现DOM对象选择器
2016/09/24 Javascript
Angular实现下载安装包的功能代码分享
2017/09/05 Javascript
Three.js开发实现3D地图的实践过程总结
2017/11/20 Javascript
vue中实现移动端的scroll滚动方法
2018/03/03 Javascript
JavaScript常用截取字符串的三种方式用法区别实例解析
2018/05/15 Javascript
layui中使用jquery控制radio选中事件的示例代码
2018/08/15 jQuery
深入了解JavaScript 的 WebAssembly
2019/06/15 Javascript
解决vue初始化项目时,一直卡在Project description上的问题
2019/10/31 Javascript
node.js文件操作系统实例详解
2019/11/05 Javascript
详解JavaScript 作用域
2020/07/14 Javascript
解决vue项目input输入框双向绑定数据不实时生效问题
2020/08/05 Javascript
Vue+Spring Boot简单用户登录(附Demo)
2020/11/12 Javascript
使用Python对MySQL数据操作
2017/04/06 Python
pygame 精灵的行走及二段跳的实现方法(必看篇)
2017/07/10 Python
Python 实现网页自动截图的示例讲解
2018/05/17 Python
Python实现爬取亚马逊数据并打印出Excel文件操作示例
2019/05/16 Python
Python 画出来六维图
2019/07/26 Python
使用Python实现分别输出每个数组
2019/12/06 Python
详解opencv中画圆circle函数和椭圆ellipse函数
2019/12/27 Python
如何以Winsows Service方式运行JupyterLab
2020/08/30 Python
html5.2 dialog简介详解
2018/02/27 HTML / CSS
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的一样吗
2013/05/01 面试题
公司会计主管岗位责任制
2014/03/01 职场文书
CSS元素定位之通过元素的标签或者元素的id、class属性定位详解
2022/09/23 HTML / CSS