前端学习(2879)歌谣学习篇原生js和canvas实现弹幕功能

我是歌谣 放弃很难 坚持一定很酷
2021继续加油

目录结构

文件地址
源码地址后面可见
在这里插入图片描述

源码文件

index.css

body {
margin: 0;
}

.container {
width: 1000px;
margin: 0 auto;
}

.video-wrapper {
position: relative;
}

.video-wrapper video {
width: 100%;
}

.video-wrapper canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 563px;
}

.video-wrapper .tool-box {
height: 38px;
}

.video-wrapper input,
.video-wrapper button {
height: 100%;
margin-right: 15px;
vertical-align: middle;
outline: none;
border: none;
box-sizing: border-box;
border-radius: 5px;
}

.video-wrapper .danmu-input {
width: 300px;
border: 1px solid #ccc;
}

.video-wrapper .danmu-btn {
color: #fff;
background-color: orange;
}

danmu.js

import { getTextWidth, getTextPosition } from ‘./utils’;

class Danmu {
constructor (danmu, fCtx) {
this.content = danmu.content;
this.runTime = danmu.runTime;
this.danmu = danmu;
this.ctx = fCtx;
}

initialize () {
this.color = this.danmu.color || this.ctx.color;
this.speed = this.danmu.speed || this.ctx.speed;
this.fontSize = 30;
this.width = getTextWidth(this.content, this.fontSize);
getTextPosition(this.ctx.canvas, this.fontSize, this);
}

render () {
this.ctx.canvasCtx.font = this.fontSize + ‘px Microsoft Yahei’;
this.ctx.canvasCtx.fillStyle = this.color;
this.ctx.canvasCtx.fillText(this.content, this.X, this.Y);
}
}

export default Danmu;

index.js

import { isObject, isArray } from ‘./utils’;
import Danmu from ‘./Danmu’;

class VideoDanmu {
constructor (video, canvas, options) {
if (!video || !canvas || !options || !isObject(options)) return;
if (!options.danmuData || !isArray(options.danmuData)) return;

this.video = video;
this.canvas = canvas;
this.canvasCtx = canvas.getContext('2d');
this.canvas.width = video.offsetWidth;
this.canvas.height = video.offsetHeight;this.danmuPaused = true;Object.assign(this, options, {speed: 2,runTime: 0,color: '#fff'
});this.danmuPool = this.createDanmuPool();
this.render();

}

createDanmuPool () {
return this.danmuData.map(dm => new Danmu(dm, this));
}

render () {
this.clearRect();
this.renderDanmu();
!this.danmuPaused && requestAnimationFrame(this.render.bind(this));
}

renderDanmu () {
let currentTime = this.video.currentTime;

this.danmuPool.map((danmu) => {if (!danmu.stopRender && currentTime >= danmu.runTime) {if (!danmu.isInitialized) {danmu.initialize();danmu.isInitialized = true;}danmu.X -= danmu.speed;danmu.render();if (danmu.X <= danmu.width * -1) {danmu.stopRender = true;}}
})

}

reset () {
this.clearRect();
let currentTime = this.video.currentTime;

this.danmuPool.map((danmu) => {danmu.stopRender = false;if (currentTime <= danmu.runTime) {danmu.isInitialized = false;} else {danmu.stopRender = true;}
})

}

add (data) {
this.danmuPool.push(new Danmu(data, this));
}

clearRect () {
this.canvasCtx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}

export default VideoDanmu;


util.js

function isObject (value) {
const type = Object.prototype.toString.call(value);
return type === ‘[object Object]’;
}

function isArray (value) {
return Array.isArray(value);
}

function getTextWidth (content, fontSize) {
const _span = document.createElement(‘span’);
_span.innerText = content;
_span.style.fontSize = fontSize + ‘px’;
_span.style.position = ‘absolute’;
document.body.appendChild(_span);
let width = _span.offsetWidth;
document.body.removeChild(_span);
return width;
}

function getTextPosition (wrapper, fontSize, ctx) {
const X = wrapper.width;
let Y = wrapper.height * Math.random();

Y < fontSize && (Y = fontSize);
Y > wrapper.height - fontSize && (Y = wrapper.height - fontSize);

ctx.X = X;
ctx.Y = Y;
}

export {
isObject,
isArray,
getTextWidth,
getTextPosition
}

index.js

import VideoDanmu from ‘./danmu’;

const danmuData = [
{
content: ‘我真的好喜欢这首钢琴曲’,
runTime: 10,
speed: 2,
color: ‘red’
},
{
content: ‘这首钢琴曲是红猪里的一去不复返的时光’,
runTime: 0,
speed: 4,
color: ‘orange’
},
{
content: ‘久石让是我最崇拜的音乐家之一’,
runTime: 15,
speed: 4,
color: ‘green’
}
]

😭(doc) => {

const oDanmuVideo = doc.getElementById(‘J_danmuVideo’),
oDanmuCanvas = doc.getElementById(‘J_danmuCanvas’),
oDanmuBtn = doc.getElementsByClassName(‘danmu-btn’)[0],
oDanmuInput = doc.getElementsByClassName(‘danmu-input’)[0],
oColorInput = doc.getElementsByClassName(‘color-input’)[0];

const init = () => {
window.videoDanmu = new VideoDanmu(
oDanmuVideo,
oDanmuCanvas,
{
danmuData
}
)
bindEvent();
}

function bindEvent () {
oDanmuVideo.addEventListener(‘play’, handleVideoPlay, false);
oDanmuVideo.addEventListener(‘pause’, handleVideoPause, false);
oDanmuVideo.addEventListener(‘seeked’, handleVideoSeek, false);
oDanmuBtn.addEventListener(‘click’, handleToolClick, false);
}

function handleVideoPlay () {
videoDanmu.danmuPaused = false;
videoDanmu.render();
}

function handleVideoPause () {
videoDanmu.danmuPaused = true;
}

function handleVideoSeek () {
videoDanmu.reset();
}

function handleToolClick () {
if (videoDanmu.danmuPaused) return;

const inputValue = oDanmuInput.value.trim();if (!inputValue.length) return;const colorValue = oColorInput.value,runTime = oDanmuVideo.currentTime;const _data = {content: inputValue,color: colorValue,runTime
}videoDanmu.add(_data);
oDanmuInput.value = '';

}

init();

})(document);

## 主文件
Document
发送弹幕
## 运行结果
![在这里插入图片描述](https://img-blog.csdnimg.cn/2021021714473891.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzM5MjQ4OQ==,size_16,color_FFFFFF,t_70)## 源码地址
[源码地址](https://gitee.com/geyaoisgeyao/small-cases-of-daily-learning/tree/master/)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/412210.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汤姆逊灯

由 MIT (Massachusetts Institute of Technology) 哲学教授在1954年提出&#xff1a;考虑一盏开关由一个复杂的定时器控制的灯。实验开始时&#xff0c;灯是开着的&#xff0c;并且正好开一分钟。这一分钟结束时定时器把灯关闭&#xff0c;这样持续半分钟。之后&#xff0c;又把…

python def函数_Python教程之Lambda表达式知识概述

在Python中&#xff0c;除了def之外&#xff0c;还提供了一种生成函数对象的表达式形式&#xff0c;即Lambda表达式&#xff0c;它可以创建小的匿名函数&#xff0c;起到一个函数速写的作用。接下来的好程序员Python学习课程就给大家分享Lambda表达式相关的知识点。Lambda表达式…

MySQL全文索引模糊查询_mysql全文索引之模糊查询

旧版的MySQL的全文索引只能用在MyISAM表格的char、varchar和text的字段上。不过新版的MySQL5.6.24上InnoDB引擎也加入了全文索引&#xff0c;所以具体信息大家可以随时关注官网&#xff0c;下面我来谈谈mysql全文索引的用法,网上很多啦&#xff0c;我只讲讲我所了解滴部分哈&am…

html中内容超出显示省略号的方法

html中内容超出显示省略号的方法 本博客主要介绍 前端开发中文本过多&#xff0c;以省略号显示。 效果如图&#xff1a; 单行&#xff1a; <!--单行--> <p class"pl">这个属性定义溢出元素内容区的内容会如何处理。如果值为 hidden&#xff0c;当点击hid…

vue 多选自动触发_Vue,初次邂逅(二)

一、前言二、Vue常用指令2.1 什么是指令&#xff1f;指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的预期值是&#xff1a;单个 JavaScript 表达式。指令的职责是&#xff0c;当表达式的值改变时&#xff0c;将其产生的连带影响&#xff0c;响应式地作用于 DOM。 例如…

string.Empty 和 并不总是可以互换的

在 C# 中&#xff0c;大多数情况下 "" 和 string.Empty 可以互换使用。比如&#xff1a;strings "";strings2 string.Empty;if(s string.Empty) { // }但是我发现有一种情况下只能是用常数形式&#xff1a; "", 而不能使用 string.Empty 这个静…

pythonweb服务器部署iis_IIS部署python Web(FLASK试例)

开发环境&#xff1a;python3.6 、win7、pycharm20171、安装及配置IIS控制面板中>-程序和功能>-打开或关闭WINDOWS功能配置Internet信息服务配置万维网服务2、安装URL重写组件下载安装Web平台安装程序 5.0 (WEB PLATFORM INSTALLER 5.0)安装URL Rewrite 2.03、安装wfastc…

WPF开源框架项目

好久博客未更新新博文了&#xff0c;今天介绍一个WPF开源框架MaterialDesignInXamlToolkit废话不多说先让我们来看看框架得几张截图 让我们一起来看看源代码得结构如下图 接下我们运行代码看看运行后得截图 通过查看源代码, 由于是基于原生得状态进行修改样式及动画达到, 所以引…

rust房屋建造蓝图_都说蓝图,而不是白图、红图,你知道为什么?

文学上喜欢把对未来的构想或计划&#xff0c;称为蓝图。蓝图(英文&#xff1a;blueprint)在工业上指“蓝图纸”(晒图纸的俗称)&#xff0c;因为图纸是蓝色的&#xff0c;所以被称为“蓝图”。也许是因其具有易于保存&#xff0c;不会模糊&#xff0c;不会掉色&#xff0c;不易玷…

洛谷P1085不高兴的津津

转载于:https://www.cnblogs.com/LITTLESUNwl/p/10417533.html

统计学习方法 学习笔记(五):支持向量机(下)

通过支持向量机&#xff08;上&#xff09;和支持向量机&#xff08;中&#xff09;的介绍&#xff0c;对支持向量机应该有点感性的认识啦&#xff01;在这个学习笔记中&#xff0c;来继续探寻带核函数的支持向量机&#xff08;解决如下图所示的问题&#xff09; 对解线性分类问…