使用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 相关文章推荐
IE php关于强制下载文件的代码
Aug 23 Javascript
Confirmer JQuery确认对话框组件
Jun 09 Javascript
js中cookie的添加、取值、删除示例代码
Oct 21 Javascript
jquery validation验证身份证号,护照,电话号码,email(实例代码)
Nov 06 Javascript
JavaScript中数组成员的添加、删除介绍
Dec 30 Javascript
全面解析Bootstrap表单使用方法(表单控件)
Nov 24 Javascript
微信小程序 获取设备信息 API实例详解
Oct 02 Javascript
详解RequireJS按需加载样式文件
Apr 12 Javascript
JS+canvas绘制的动态机械表动画效果
Sep 12 Javascript
ES6的解构赋值实例详解
May 06 Javascript
vue移动端使用canvas签名的实现
Jan 15 Javascript
vue 把二维或多维数组转一维数组
Apr 24 Vue.js
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 rawurlencode与urlencode函数的深入分析
2013/06/08 PHP
PHP二维数组排序的3种方法和自定义函数分享
2014/04/09 PHP
微信公众号开发之通过接口删除菜单
2017/02/20 PHP
JavaScript高级程序设计
2006/12/29 Javascript
JQuery 无废话系列教程(二) jquery实战篇上
2009/06/23 Javascript
jQuery chili图片远处放大插件
2009/11/30 Javascript
jquery.validate使用攻略 第一部
2010/07/01 Javascript
三种动态加载js的jquery实例代码另附去除js方法
2014/04/30 Javascript
影响jQuery使用的14个方面
2014/09/01 Javascript
MVC Ajax Helper或Jquery异步加载部分视图
2015/11/29 Javascript
jQuery插件Validation快速完成表单验证的方式
2016/07/28 Javascript
详解JavaScript中this的指向问题
2017/01/20 Javascript
jQuery在header中设置请求信息的方法
2017/03/06 Javascript
js实现产品缩略图效果
2017/03/10 Javascript
详解Weex基于Vue2.0开发模板搭建
2017/03/20 Javascript
React 高阶组件入门介绍
2018/01/11 Javascript
vuex实现及简略解析(小结)
2019/03/01 Javascript
如何从头实现一个node.js的koa框架
2019/06/17 Javascript
koa2 从入门到精通(小结)
2019/07/23 Javascript
vue登录注册实例详解
2019/09/14 Javascript
[01:15:45]DOTA2上海特级锦标赛B组小组赛#1 Alliance VS Spirit第一局
2016/02/26 DOTA
低版本中Python除法运算小技巧
2015/04/05 Python
python利用拉链法实现字典方法示例
2017/03/25 Python
python之从文件读取数据到list的实例讲解
2018/04/19 Python
Pytorch mask_select 函数的用法详解
2020/02/18 Python
Django解决frame拒绝问题的方法
2020/12/18 Python
Python 利用argparse模块实现脚本命令行参数解析
2020/12/28 Python
CSS3实现粒子旋转伸缩加载动画
2016/04/22 HTML / CSS
JDBC操作数据库的基本流程是什么
2014/10/28 面试题
茶叶生产计划书
2014/01/10 职场文书
初中三年毕业生的自我评价分享
2014/02/14 职场文书
端午节演讲稿
2014/05/23 职场文书
群众路线党员个人剖析材料
2014/10/08 职场文书
2014年计划生育工作总结
2014/11/14 职场文书
MySQL表的增删改查(基础)
2021/04/05 MySQL
Windows server 2003卸载和安装IIS的图文教程
2022/07/15 Servers