使用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 控制CSS样式表
Aug 20 Javascript
一个可以兼容IE FF的加为首页与加入收藏实现代码
Nov 02 Javascript
Javascript 中介者模式实例
Dec 16 Javascript
jquery插件制作 手风琴Panel效果实现
Aug 17 Javascript
Shell脚本实现Linux系统和进程资源监控
Mar 05 Javascript
jquery解析json格式数据的方法(对象、字符串)
Nov 24 Javascript
js判断登陆用户名及密码是否为空的简单实例
May 16 Javascript
JavaScript中的boolean布尔值使用学习及相关技巧讲解
May 26 Javascript
bootstrap组件之按钮式下拉菜单小结
Jan 19 Javascript
基于Axios 常用的请求方法别名(详解)
Mar 13 Javascript
vue实现全匹配搜索列表内容
Sep 26 Javascript
javascript设计模式 ? 组合模式原理与应用实例分析
Apr 14 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判断一个变量是否为整数、正整数的方法示例
2019/09/11 PHP
Thinkphp 框架配置操作之配置加载与读取配置实例分析
2020/05/15 PHP
JQuery 解析多维的Json数据格式
2009/11/02 Javascript
基于jquery的复制网页内容到WORD的实现代码
2011/02/16 Javascript
ExtJS中文乱码之GBK格式编码解决方案及代码
2013/01/20 Javascript
js动态生成指定行数的表格
2013/07/11 Javascript
escape函数解决js中ajax传递中文出现乱码问题
2014/10/30 Javascript
jQuery制作拼图小游戏
2015/01/12 Javascript
jquery实现简单文字提示效果
2015/12/02 Javascript
JavaScript模块化开发之SeaJS
2015/12/13 Javascript
javascript基本数据类型及类型检测常用方法小结
2016/12/14 Javascript
js实现类似iphone的网页滑屏解锁功能示例【附源码下载】
2019/06/10 Javascript
vue实现二级导航栏效果
2019/10/19 Javascript
Selenium执行Javascript脚本参数及返回值过程详解
2020/04/01 Javascript
js实现搜索提示框效果
2020/09/05 Javascript
pymongo给mongodb创建索引的简单实现方法
2015/05/06 Python
整理Python 常用string函数(收藏)
2016/05/30 Python
Python异常处理操作实例详解
2018/08/28 Python
Python3内置模块之base64编解码方法详解
2019/07/13 Python
Python测试模块doctest使用解析
2019/08/10 Python
8段用于数据清洗Python代码(小结)
2019/10/31 Python
如何在python中实现随机选择
2019/11/02 Python
基于Python爬取股票数据过程详解
2020/10/21 Python
纯CSS3实现Material Design效果
2017/03/09 HTML / CSS
华为python面试题
2016/05/03 面试题
大学团支书的自我评价分享
2013/12/14 职场文书
八年级语文教学反思
2014/02/11 职场文书
火车的故事教学反思
2014/02/11 职场文书
2014老师三严三实对照检查材料思想汇报
2014/09/18 职场文书
医院党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
2014年学生会生活部工作总结
2014/11/07 职场文书
2014年资料员工作总结
2014/11/18 职场文书
十八大观后感
2015/06/12 职场文书
MySQL锁机制
2021/04/05 MySQL
Pandas自定义选项option设置
2021/07/25 Python
浅析python中特殊文件和特殊函数
2022/02/24 Python