使用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 相关文章推荐
Jquery之美中不足小结
Feb 16 Javascript
jquery easyui中treegrid用法的简单实例
Feb 18 Javascript
jQuery焦点图切换简易插件制作过程全纪录
Aug 27 Javascript
jQuery仿Flash上下翻动的中英文导航菜单实例
Mar 10 Javascript
跟我学习javascript的prototype使用注意事项
Nov 17 Javascript
jquery捕捉回车键及获取checkbox值与异步请求的方法
Dec 24 Javascript
Angular 4.x 路由快速入门学习
May 03 Javascript
微信小程序之数据双向绑定与数据操作
May 12 Javascript
浅谈关于.vue文件中style的scoped属性
Aug 19 Javascript
React Native 通告消息竖向轮播组件的封装
Aug 25 Javascript
jQuery+ajax实现文件上传功能
Dec 22 jQuery
Vue Element UI自定义描述列表组件
May 18 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
10 个经典PHP函数
2013/10/17 PHP
解决nginx不支持thinkphp中pathinfo的问题
2015/07/21 PHP
PHP实现连接设备、通讯和发送命令的方法
2015/10/13 PHP
PHP实现的登录页面信息提示功能示例
2017/07/24 PHP
PHP使用HTML5 FormData对象提交表单操作示例
2019/07/02 PHP
在Laravel 中实现是否关注的示例
2019/10/22 PHP
php提高脚本性能的4个技巧
2020/08/18 PHP
jquery不会自动回收xmlHttpRequest对象 导致了内存溢出
2012/06/18 Javascript
30个经典的jQuery代码开发技巧
2014/12/15 Javascript
jquery实现仿JqueryUi可拖动的DIV实例
2015/07/31 Javascript
js console.log打印对像与数组用法详解
2016/01/21 Javascript
JavaScript通过使用onerror设置默认图像显示代替alt
2016/03/01 Javascript
Javascript随机标签云代码实例
2016/06/21 Javascript
js判断出两个字符串最大子串的函数实现方法
2016/11/01 Javascript
微信小程序 保留小数(toFixed)详细介绍
2016/11/16 Javascript
jquery实现轮播图效果
2017/02/13 Javascript
js实现一键复制功能
2017/03/16 Javascript
Node.js+Express+MySql实现用户登录注册功能
2017/07/10 Javascript
bootstrap-Treeview实现级联勾选
2017/11/23 Javascript
JavaScript表格隔行变色和Tab标签页特效示例【附jQuery版】
2019/07/11 jQuery
javascript设计模式 ? 享元模式原理与用法实例分析
2020/04/15 Javascript
零基础写python爬虫之使用urllib2组件抓取网页内容
2014/11/04 Python
Python同时向控制台和文件输出日志logging的方法
2015/05/26 Python
python logging 日志轮转文件不删除问题的解决方法
2016/08/02 Python
Python探索之URL Dispatcher实例详解
2017/10/28 Python
Python 实现字符串中指定位置插入一个字符
2018/05/02 Python
销售所有的狗狗产品:Dog.com
2016/10/13 全球购物
LACOSTE波兰官网:Polo衫、服装和鞋类
2020/09/29 全球购物
学生爱国演讲稿
2014/01/14 职场文书
《自然之道》教学反思
2014/02/11 职场文书
党员领导干部承诺书
2014/05/28 职场文书
公司慰问信范文
2015/03/23 职场文书
2015年创先争优活动总结
2015/03/27 职场文书
新教师教学工作总结
2015/08/12 职场文书
陶瓷类经典广告语集锦
2019/10/25 职场文书
华为HarmonyOS3.0强在哪? 看看鸿蒙3.0这7个小功能
2023/01/09 数码科技