我是歌谣 放弃很难 坚持一定很酷
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);
## 主文件
## 运行结果
![在这里插入图片描述](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/)