使用canvas实现一个vue弹幕组件功能
2018-12-31 21:29
956 查看
看B站时,对弹幕的实现产生了兴趣,一开始想到用css3动画去实现,后来感觉这样性能不是很好,查了下资料,发现可以用canvas实现,于是就摸索着写了一个简单的弹幕。
弹幕功能
支持动态添加弹幕
弹幕不重叠
自定义弹幕颜色
效果图
前端框架选了比较熟悉的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 = ''; }
有待改进的地方和疑问?速度不恒定时,怎么保持弹幕不重叠视频弹幕是根据弹幕发送时间点来定位到视频的每一帧?如何实现?
为了学习工作与休闲娱乐互不冲突,现新建圈【码农茶水铺】用于程序员生活,爱好,交友,求职招聘,吐槽等话题交流,希望各位大神工作之余到茶水铺来喝茶聊天。群号:582735936
在这里插入代码片阅读更多
相关文章推荐
- 使用canvas实现一个vue弹幕组件功能
- 使用canvas实现一个vue弹幕组件功能
- 使用Vue组件实现一个简单弹窗效果
- HTML使用Canvas实现弹幕功能
- 使用silverlight构建一个工作流设计器(十八)-持久化数据到数据库—服务器段功能实现
- 如何使用一个按钮实现两个功能
- 使用canvas实现仿新浪微博头像截取上传功能
- 使用excanvas.js实现拓扑功能
- Winform(C#.NET)自动更新组件的使用及部分功能实现(一点改进功能)
- 有段时间没有更新博客了,最近比较忙,今天和大家分享一个使用Swift实现的新特性功能吧
- vue2.0使用Sortable.js实现的拖拽功能
- 用Python 实现刷钻网上抢任务,并实现一个简单的限制使用时间的功能
- Flex中Tree组件实现导航树搜索定位功能及Tree组件的的使用要点
- 第一部分实现功能:使用一个TabControl和一个Memo和TDictionary类实现文本临时存储
- 一个使用微软Azure blob实现文件下载功能的实例-附带源文件
- 使用react context实现一个支持组件组合和嵌套的React Tab组件
- android 自定义view使用Canvas实现支付宝咻一咻功能
- 使用vue.js实现checkbox的全选和多个的删除功能
- 图片上传功能的实现(FileUpload组件的使用)
- 使用一个黑客的小伎俩来实现discuz!邀请功能刷分