使用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 相关文章推荐
javascript学习笔记(九)javascript中的原型(prototype)及原型链的继承方式
Apr 12 Javascript
5个书写JavaScript代码的坏习惯,看看你中枪了没?
Nov 06 Javascript
jQuery解析XML与传统JavaScript方法的差别实例分析
Mar 05 Javascript
js和jquery实现监听键盘事件示例代码
Jun 24 Javascript
jquery动态遍历Json对象的属性和值的方法
Jul 27 Javascript
jQuery实现弹出带遮罩层的居中浮动窗口效果
Sep 12 Javascript
js中小数向上取整数,向下取整数,四舍五入取整数的实现(必看篇)
Feb 13 Javascript
Bootstrap入门教程一Hello Bootstrap初识
Mar 02 Javascript
js获取指定时间的前几秒
Apr 05 Javascript
微信小程序button组件使用详解
Jan 31 Javascript
node.js制作一个简单的登录拦截器
Feb 10 Javascript
利用原生JS实现欢乐水果机小游戏
Apr 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
收音机鉴频器对声音的影响和频偏分析
2021/03/02 无线电
PHP实现发送邮件的方法(基于简单邮件发送类)
2015/12/17 PHP
php版微信返回用户text输入的方法
2016/11/14 PHP
PHP实现的统计数据功能详解
2016/12/06 PHP
PHP面向对象程序设计(OOP)之方法重写(override)操作示例
2018/12/21 PHP
PHP扩展Swoole实现实时异步任务队列示例
2019/04/13 PHP
asp 的 分词实现代码
2007/05/24 Javascript
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
jQuery与ExtJS之选择实例分析
2010/08/19 Javascript
js 创建快捷方式的代码(fso)
2010/11/19 Javascript
IE中document.createElement的iframe无法设置属性name的解决方法
2015/09/14 Javascript
Js实现简单的小球运动特效
2016/02/18 Javascript
javaScript数组迭代方法详解
2016/04/14 Javascript
轻松掌握JavaScript中的Math object数学对象
2016/05/26 Javascript
vue2.0开发实践总结之疑难篇
2016/12/07 Javascript
简单的渐变轮播插件
2017/01/12 Javascript
微信小程序webSocket的使用方法
2020/02/20 Javascript
TypeScript的安装、使用、自动编译的实现
2020/04/10 Javascript
详解element-ui 表单校验 Rules 配置 常用黑科技
2020/07/11 Javascript
如何使用RoughViz可视化Vue.js中的草绘图表
2021/01/30 Vue.js
[01:00:10]完美世界DOTA2联赛PWL S2 FTD vs Inki 第二场 11.21
2020/11/24 DOTA
Python ORM框架SQLAlchemy学习笔记之关系映射实例
2014/06/10 Python
举例讲解Python的lambda语句声明匿名函数的用法
2016/07/01 Python
关于Python中异常(Exception)的汇总
2017/01/18 Python
Python正则表达式教程之一:基础篇
2017/03/02 Python
Python实现TCP通信的示例代码
2019/09/09 Python
解决python-docx打包之后找不到default.docx的问题
2020/02/13 Python
UI自动化定位常用实现方法代码示例
2020/10/27 Python
Python+Opencv实现把图片、视频互转的示例
2020/12/17 Python
Html5 web本地存储实例详解
2016/07/28 HTML / CSS
英国的潮牌鞋履服饰商店:size?
2019/03/26 全球购物
中学生在校期间的自我评价分享
2013/11/13 职场文书
2014年勤工助学工作总结
2014/11/24 职场文书
文艺部部长竞选稿
2015/11/21 职场文书
Javascript中的解构赋值语法详解
2021/04/02 Javascript
浅谈Python中对象是如何被调用的
2022/04/06 Python