separate danamku module; fix some minor mistakes

This commit is contained in:
DIYgod 2017-08-15 11:21:23 +08:00
parent 7a8a2ac7ba
commit f4d186f6ec
No known key found for this signature in database
GPG Key ID: EC0B76A252D3EF67
7 changed files with 393 additions and 331 deletions

2
dist/DPlayer.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
{
"name": "dplayer",
"version": "1.5.2",
"version": "1.6.0",
"description": "Wow, such a lovely HTML5 danmaku video player",
"main": "dist/DPlayer.min.js",
"style": "dist/DPlayer.min.css",

View File

@ -5,6 +5,7 @@ import svg from './svg';
import handleOption from './option';
import i18n from './i18n';
import html from './html';
import Danmaku from './danmaku';
let index = 0;
@ -63,6 +64,40 @@ class DPlayer {
this.element.innerHTML = html.main(option, index, this.tran);
if (this.option.danmaku) {
this.danmaku = new Danmaku({
container: this.element.getElementsByClassName('dplayer-danmaku')[0],
opacity: localStorage.getItem('danmaku-opacity') || 0.7,
callback: () => {
this.element.getElementsByClassName('dplayer-danloading')[0].style.display = 'none';
// autoplay
if (this.option.autoplay && !isMobile) {
this.play();
}
else if (isMobile) {
this.pause();
}
},
error: (msg) => {
this.notice(msg);
},
apiBackend: this.option.apiBackend,
borderColor: this.option.theme,
height: this.arrow ? 24 : 30,
time: () => this.video.currentTime,
api: {
id: this.option.danmaku.id,
address: this.option.danmaku.api,
token: this.option.danmaku.token,
maximum: this.option.danmaku.maximum,
addition: this.option.danmaku.addition,
user: this.option.danmaku.user,
}
});
}
// arrow style
this.arrow = this.element.offsetWidth <= 500;
if (this.arrow) {
@ -121,8 +156,6 @@ class DPlayer {
let lastPlayPos = 0;
let currentPlayPos = 0;
let bufferingDetected = false;
this.danmakuTime = false;
this.playedTime = false;
window.requestAnimationFrame = (() =>
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
@ -158,28 +191,19 @@ class DPlayer {
clearInterval(this.checkLoading);
};
this.playedTime = false;
this.animationFrame = () => {
if (this.playedTime) {
this.updateBar('played', this.video.currentTime / this.video.duration, 'width');
this.element.getElementsByClassName('dplayer-ptime')[0].innerHTML = utils.secondToTime(this.video.currentTime);
this.trigger('playing');
}
if (this.danmakuTime && this.option.danmaku && showdan && this.dan) {
let item = this.dan[this.danIndex];
const danmakus = [];
while (item && this.video.currentTime > parseFloat(item.time)) {
danmakus.push(item);
item = this.dan[++this.danIndex];
}
this.pushDanmaku(danmakus);
}
this.requestID = window.requestAnimationFrame(this.animationFrame);
window.requestAnimationFrame(this.animationFrame);
};
this.requestID = window.requestAnimationFrame(this.animationFrame);
window.requestAnimationFrame(this.animationFrame);
this.setTime = (type) => {
if (!type) {
this.danmakuTime = true;
this.playedTime = true;
setCheckLoadingTime();
}
@ -192,7 +216,6 @@ class DPlayer {
};
this.clearTime = (type) => {
if (!type) {
this.danmakuTime = false;
this.playedTime = false;
clearCheckLoadingTime();
}
@ -328,7 +351,6 @@ class DPlayer {
/**
* setting
*/
this.danOpacity = localStorage.getItem('DPlayer-opacity') || 0.7;
const settingHTML = html.setting(this.tran);
// toggle setting box
@ -361,7 +383,6 @@ class DPlayer {
});
this.loop = this.option.loop;
const danContainer = this.element.getElementsByClassName('dplayer-danmaku')[0];
let showdan = true;
const settingEvent = () => {
// loop control
@ -391,30 +412,15 @@ class DPlayer {
showDanToggle.checked = !showDanToggle.checked;
if (showDanToggle.checked) {
showdan = true;
if (this.option.danmaku) {
for (let i = 0; i < this.dan.length; i++) {
if (this.dan[i].time >= this.video.currentTime) {
this.danIndex = i;
break;
}
this.danIndex = this.dan.length;
}
if (!this.paused) {
this.setTime('danmaku');
}
this.danmaku.seek();
if (!this.paused) {
this.danmaku.play();
}
}
else {
showdan = false;
if (this.option.danmaku) {
this.clearTime('danmaku');
danContainer.innerHTML = '';
this.danTunnel = {
right: {},
top: {},
bottom: {}
};
}
this.danmaku.pause();
this.danmaku.clear();
}
closeSetting();
});
@ -434,14 +440,14 @@ class DPlayer {
}
});
if (this.option.danmaku) {
if (this.danmaku) {
// danmaku opacity
bar.danmakuBar = this.element.getElementsByClassName('dplayer-danmaku-bar-inner')[0];
const danmakuBarWrapWrap = this.element.getElementsByClassName('dplayer-danmaku-bar-wrap')[0];
const danmakuBarWrap = this.element.getElementsByClassName('dplayer-danmaku-bar')[0];
const danmakuSettingBox = this.element.getElementsByClassName('dplayer-setting-danmaku')[0];
const dWidth = 130;
this.updateBar('danmaku', this.danOpacity, 'width');
this.updateBar('danmaku', this.danmaku.opacity(), 'width');
const danmakuMove = (event) => {
const e = event || window.event;
@ -449,12 +455,7 @@ class DPlayer {
percentage = percentage > 0 ? percentage : 0;
percentage = percentage < 1 ? percentage : 1;
this.updateBar('danmaku', percentage, 'width');
const items = this.element.getElementsByClassName('dplayer-danmaku-item');
for (let i = 0; i < items.length; i++) {
items[i].style.opacity = percentage;
}
this.danOpacity = percentage;
localStorage.setItem('DPlayer-opacity', this.danOpacity);
this.danmaku.opacity(percentage);
};
const danmakuUp = () => {
document.removeEventListener('mouseup', danmakuUp);
@ -468,12 +469,7 @@ class DPlayer {
percentage = percentage > 0 ? percentage : 0;
percentage = percentage < 1 ? percentage : 1;
this.updateBar('danmaku', percentage, 'width');
const items = this.element.getElementsByClassName('dplayer-danmaku-item');
for (let i = 0; i < items.length; i++) {
items[i].style.opacity = percentage;
}
this.danOpacity = percentage;
localStorage.setItem('DPlayer-opacity', this.danOpacity);
this.danmaku.opacity(percentage);
});
danmakuBarWrapWrap.addEventListener('mousedown', () => {
document.addEventListener('mousemove', danmakuMove);
@ -489,22 +485,7 @@ class DPlayer {
this.element.getElementsByClassName('dplayer-dtime')[0].innerHTML = this.video.duration ? utils.secondToTime(this.video.duration) : '00:00';
}
// danmaku
this.danTunnel = {
right: {},
top: {},
bottom: {}
};
const measureStyle = getComputedStyle(this.element.getElementsByClassName('dplayer-danmaku-item')[0], null);
const context = document.createElement('canvas').getContext('2d');
context.font = measureStyle.getPropertyValue('font-size') + ' ' + measureStyle.getPropertyValue('font-family');
this.danmakuMeasure = (text) => context.measureText(text).width;
if (this.option.danmaku) {
this.danIndex = 0;
this.readDanmaku();
}
else {
if (!this.danmaku) {
// autoplay
if (this.option.autoplay && !isMobile) {
this.play();
@ -525,47 +506,6 @@ class DPlayer {
const commentSettingBox = this.element.getElementsByClassName('dplayer-comment-setting-box')[0];
const commentSendIcon = this.element.getElementsByClassName('dplayer-send-icon')[0];
const htmlEncode = (str) => str.
replace(/&/g, "&amp;").
replace(/</g, "&lt;").
replace(/>/g, "&gt;").
replace(/"/g, "&quot;").
replace(/'/g, "&#x27;").
replace(/\//g, "&#x2f;");
const sendComment = () => {
commentInput.blur();
// text can't be empty
if (!commentInput.value.replace(/^\s+|\s+$/g, '')) {
this.notice(this.tran('Please input danmaku content!'));
return;
}
const danmakuData = {
token: this.option.danmaku.token,
player: this.option.danmaku.id,
author: this.option.danmaku.user,
time: this.video.currentTime,
text: commentInput.value,
color: this.element.querySelector('.dplayer-comment-setting-color input:checked').value,
type: this.element.querySelector('.dplayer-comment-setting-type input:checked').value
};
this.option.apiBackend.send(this.option.danmaku.api, danmakuData);
commentInput.value = '';
closeComment();
this.dan.splice(this.danIndex, 0, danmakuData);
this.danIndex++;
const danmaku = {
text: htmlEncode(danmakuData.text),
color: danmakuData.color,
type: danmakuData.type,
border: `2px solid ${this.option.theme}`
};
this.pushDanmaku(danmaku);
};
const closeCommentSetting = () => {
if (commentSettingBox.classList.contains('dplayer-comment-setting-open')) {
commentSettingBox.classList.remove('dplayer-comment-setting-open');
@ -630,6 +570,25 @@ class DPlayer {
}
});
const sendComment = () => {
commentInput.blur();
// text can't be empty
if (!commentInput.value.replace(/^\s+|\s+$/g, '')) {
this.notice(this.tran('Please input danmaku content!'));
return;
}
this.danmaku.send({
text: commentInput.value,
color: this.element.querySelector('.dplayer-comment-setting-color input:checked').value,
type: this.element.querySelector('.dplayer-comment-setting-type input:checked').value
}, () => {
commentInput.value = '';
closeComment();
});
};
commentInput.addEventListener('click', () => {
closeCommentSetting();
});
@ -646,22 +605,14 @@ class DPlayer {
/**
* full screen
*/
const resetAnimation = () => {
const danWidth = danContainer.offsetWidth;
const items = this.element.getElementsByClassName('dplayer-danmaku-item');
for (let i = 0; i < items.length; i++) {
items[i].style.transform = `translateX(-${danWidth}px)`;
}
};
this.element.addEventListener('fullscreenchange', () => {
resetAnimation();
this.danmaku.resetAnimation();
});
this.element.addEventListener('mozfullscreenchange', () => {
resetAnimation();
this.danmaku.resetAnimation();
});
this.element.addEventListener('webkitfullscreenchange', () => {
resetAnimation();
this.danmaku.resetAnimation();
});
// browser full screen
this.element.getElementsByClassName('dplayer-full-icon')[0].addEventListener('click', () => {
@ -690,7 +641,7 @@ class DPlayer {
document.webkitCancelFullScreen();
}
}
resetAnimation();
this.danmaku.resetAnimation();
});
// web full screen
this.element.getElementsByClassName('dplayer-full-in-icon')[0].addEventListener('click', () => {
@ -699,7 +650,7 @@ class DPlayer {
}
else {
this.element.classList.add('dplayer-fulled');
resetAnimation();
this.danmaku.resetAnimation();
}
});
@ -747,7 +698,7 @@ class DPlayer {
case 27:
if (this.element.classList.contains('dplayer-fulled')) {
this.element.classList.remove('dplayer-fulled');
resetAnimation();
this.danmaku.resetAnimation();
}
break;
}
@ -831,13 +782,7 @@ class DPlayer {
this.video.currentTime = time;
for (let i = 0; i < this.dan.length; i++) {
if (this.dan[i].time >= time) {
this.danIndex = i;
return;
}
this.danIndex = this.dan.length;
}
this.danmaku.seek();
}
/**
@ -875,7 +820,6 @@ class DPlayer {
this.video.pause();
this.clearTime();
this.element.classList.remove('dplayer-playing');
window.cancelAnimationFrame(this.requestID);
this.trigger('pause');
}
@ -914,198 +858,30 @@ class DPlayer {
}
}
/**
* Asynchronously read danmaku from all API endpoints
*/
_readAllEndpoints (endpoints, finish) {
const results = [];
let readCount = 0;
const cbk = (i) => (err, data) => {
++readCount;
if (err) {
if (err.response) {
this.notice(err.response.msg);
}
else {
this.notice('Request was unsuccessful: ' + err.status);
}
results[i] = [];
}
else {
results[i] = data;
}
if (readCount === endpoints.length) {
return finish(results);
}
};
for (let i = 0; i < endpoints.length; ++i) {
this.option.apiBackend.read(endpoints[i], cbk(i));
}
}
/**
* Read danmaku from API
*/
readDanmaku () {
let apiurl;
if (this.option.danmaku.maximum) {
apiurl = `${this.option.danmaku.api}?id=${this.option.danmaku.id}&max=${this.option.danmaku.maximum}`;
}
else {
apiurl = `${this.option.danmaku.api}?id=${this.option.danmaku.id}`;
}
const endpoints = (this.option.danmaku.addition || []).slice(0);
endpoints.push(apiurl);
this._readAllEndpoints(endpoints, (results) => {
this.danIndex = 0;
this.dan = [].concat.apply([], results).sort((a, b) => a.time - b.time);
this.element.getElementsByClassName('dplayer-danloading')[0].style.display = 'none';
// autoplay
if (this.option.autoplay && !isMobile) {
this.play();
}
else if (isMobile) {
this.pause();
}
});
}
/**
* Push a danmaku into DPlayer
*
* @param {Object Array} danmaku - {text, color, type}
* text - danmaku content
* color - danmaku color, default: `#fff`
* type - danmaku type, `right` `top` `bottom`, default: `right`
*/
pushDanmaku (danmaku) {
const danContainer = this.element.getElementsByClassName('dplayer-danmaku')[0];
const itemHeight = this.arrow ? 24 : 30;
const danWidth = danContainer.offsetWidth;
const danHeight = danContainer.offsetHeight;
const itemY = parseInt(danHeight / itemHeight);
const danItemRight = (ele) => {
const eleWidth = ele.offsetWidth || parseInt(ele.style.width);
const eleRight = ele.getBoundingClientRect().right || danContainer.getBoundingClientRect().right + eleWidth;
return danContainer.getBoundingClientRect().right - eleRight;
};
const danSpeed = (width) => (danWidth + width) / 5;
const getTunnel = (ele, type, width) => {
const tmp = danWidth / danSpeed(width);
for (let i = 0; ; i++) {
const item = this.danTunnel[type][i + ''];
if (item && item.length) {
for (let j = 0; j < item.length; j++) {
const danRight = danItemRight(item[j]) - 10;
if (danRight <= danWidth - tmp * danSpeed(parseInt(item[j].style.width)) || danRight <= 0) {
break;
}
if (j === item.length - 1) {
this.danTunnel[type][i + ''].push(ele);
ele.addEventListener('animationend', () => {
this.danTunnel[type][i + ''].splice(0, 1);
});
return i % itemY;
}
}
}
else {
this.danTunnel[type][i + ''] = [ele];
ele.addEventListener('animationend', () => {
this.danTunnel[type][i + ''].splice(0, 1);
});
return i % itemY;
}
}
};
if (Object.prototype.toString.call(danmaku) !== '[object Array]') {
danmaku = [danmaku];
}
const docFragment = document.createDocumentFragment();
for (let i = 0; i < danmaku.length; i++) {
if (!danmaku[i].type) {
danmaku[i].type = 'right';
}
if (!danmaku[i].color) {
danmaku[i].color = '#fff';
}
const item = document.createElement(`div`);
item.classList.add(`dplayer-danmaku-item`);
item.classList.add(`dplayer-danmaku-${danmaku[i].type}`);
item.innerHTML = danmaku[i].text;
item.style.opacity = this.danOpacity;
item.style.color = danmaku[i].color;
item.style.border = danmaku[i].border;
item.addEventListener('animationend', () => {
danContainer.removeChild(item);
});
const itemWidth = this.danmakuMeasure(danmaku[i].text);
// adjust
switch (danmaku[i].type) {
case 'right':
item.style.width = itemWidth + 1 + 'px';
item.style.top = itemHeight * getTunnel(item, danmaku[i].type, itemWidth) + 'px';
item.style.transform = `translateX(-${danWidth}px)`;
break;
case 'top':
item.style.top = itemHeight * getTunnel(item, danmaku[i].type) + 'px';
break;
case 'bottom':
item.style.bottom = itemHeight * getTunnel(item, danmaku[i].type) + 'px';
break;
default:
console.error(`Can't handled danmaku type: ${danmaku[i].type}`);
}
// move
item.classList.add(`dplayer-danmaku-move`);
// insert
docFragment.appendChild(item);
}
danContainer.appendChild(docFragment);
return docFragment;
}
/**
* Switch to a new video
*
* @param {Object} video - new video info
* @param {Object} danmaku - new danmaku info
*/
switchVideo (video, danmaku) {
switchVideo (video, danmakuAPI) {
this.video.poster = video.pic ? video.pic : '';
this.video.src = video.url;
this.pause();
if (danmaku) {
this.dan = [];
this.danIndex = 0;
if (danmakuAPI) {
this.element.getElementsByClassName('dplayer-danloading')[0].style.display = 'block';
this.updateBar('played', 0, 'width');
this.updateBar('loaded', 0, 'width');
this.element.getElementsByClassName('dplayer-ptime')[0].innerHTML = '00:00';
this.element.getElementsByClassName('dplayer-danmaku')[0].innerHTML = '';
this.danTuel = {
right: {},
top: {},
bottom: {}
};
this.option.danmaku = danmaku;
this.readDanmaku();
this.danmaku.reload({
id: danmakuAPI.id,
address: danmakuAPI.api,
token: danmakuAPI.token,
maximum: danmakuAPI.maximum,
addition: danmakuAPI.addition,
user: danmakuAPI.user,
});
}
}
@ -1148,19 +924,6 @@ class DPlayer {
flvPlayer.load();
}
// if (this.option.danmaku) {
// this.video.addEventListener('seeking', () => {
// for (let i = 0; i < this.dan.length; i++) {
// if (this.dan[i].time >= this.video.currentTime) {
// this.danIndex = i;
// return;
// }
// this.danIndex = this.dan.length;
// }
// });
// }
/**
* video events
*/
@ -1201,7 +964,7 @@ class DPlayer {
this.seek(0);
this.video.play();
}
this.danIndex = 0;
this.danmaku.danIndex = 0;
});
this.video.addEventListener('play', () => {

View File

@ -28,9 +28,12 @@ const SendXMLHttpRequest = (url, data, success, error, fail) => {
};
module.exports = {
send: (endpoint, danmakuData) => {
send: (endpoint, danmakuData, callback) => {
SendXMLHttpRequest(endpoint, danmakuData, (xhr, response) => {
console.log('Post danmaku: ', response);
if (callback) {
callback();
}
}, (xhr, response) => {
alert(response.msg);
}, (xhr) => {
@ -38,13 +41,13 @@ module.exports = {
});
},
read: (endpoint, cbk) => {
read: (endpoint, callback) => {
SendXMLHttpRequest(endpoint, null, (xhr, response) => {
cbk(null, response.danmaku);
callback(null, response.danmaku);
}, (xhr, response) => {
cbk({ status: xhr.status, response });
callback({ status: xhr.status, response });
}, (xhr) => {
cbk({ status: xhr.status, response: null });
callback({ status: xhr.status, response: null });
});
}
};

296
src/danmaku.js Normal file
View File

@ -0,0 +1,296 @@
class Danmaku {
constructor (options) {
this.options = options;
this.container = this.options.container;
this.danTunnel = {
right: {},
top: {},
bottom: {}
};
this.danIndex = 0;
this.dan = [];
this.show = true;
this._opacity = this.options.opacity;
this.load();
}
load () {
let apiurl;
if (this.options.api.maximum) {
apiurl = `${this.options.api.address}?id=${this.options.api.id}&max=${this.options.api.maximum}`;
}
else {
apiurl = `${this.options.api.address}?id=${this.options.api.id}`;
}
const endpoints = (this.options.api.addition || []).slice(0);
endpoints.push(apiurl);
this._readAllEndpoints(endpoints, (results) => {
this.dan = [].concat.apply([], results).sort((a, b) => a.time - b.time);
window.requestAnimationFrame(() => {
this.frame();
});
this.options.callback();
});
}
reload (newAPI) {
this.options.api = newAPI;
this.dan = [];
this.clear();
this.load();
}
/**
* Asynchronously read danmaku from all API endpoints
*/
_readAllEndpoints (endpoints, callback) {
const results = [];
let readCount = 0;
const cbk = (i) => (err, data) => {
++readCount;
if (err) {
if (err.response) {
this.options.error(err.response.msg);
}
else {
this.options.error('Request was unsuccessful: ' + err.status);
}
results[i] = [];
}
else {
results[i] = data;
}
if (readCount === endpoints.length) {
return callback(results);
}
};
for (let i = 0; i < endpoints.length; ++i) {
this.options.apiBackend.read(endpoints[i], cbk(i));
}
}
send (dan, callback) {
const danmakuData = {
token: this.options.api.token,
player: this.options.api.id,
author: this.options.api.user,
time: this.options.time(),
text: dan.text,
color: dan.color,
type: dan.type
};
this.options.apiBackend.send(this.options.api.address, danmakuData, callback);
this.dan.splice(this.danIndex, 0, danmakuData);
this.danIndex++;
const danmaku = {
text: this.htmlEncode(danmakuData.text),
color: danmakuData.color,
type: danmakuData.type,
border: `2px solid ${this.options.borderColor}`
};
this.draw(danmaku);
}
frame () {
if (this.dan.length && !this.paused) {
let item = this.dan[this.danIndex];
const dan = [];
while (item && this.options.time() > parseFloat(item.time)) {
dan.push(item);
item = this.dan[++this.danIndex];
}
this.draw(dan);
}
window.requestAnimationFrame(() => {
this.frame();
});
}
opacity (percentage) {
if (percentage !== undefined) {
const items = this.container.getElementsByClassName('dplayer-danmaku-item');
for (let i = 0; i < items.length; i++) {
items[i].style.opacity = percentage;
}
this._opacity = percentage;
localStorage.setItem('danmaku-opacity', this._opacity);
}
return this._opacity;
}
/**
* Push a danmaku into DPlayer
*
* @param {Object Array} dan - {text, color, type}
* text - danmaku content
* color - danmaku color, default: `#fff`
* type - danmaku type, `right` `top` `bottom`, default: `right`
*/
draw (dan) {
const itemHeight = this.options.height;
const danWidth = this.container.offsetWidth;
const danHeight = this.container.offsetHeight;
const itemY = parseInt(danHeight / itemHeight);
const danItemRight = (ele) => {
const eleWidth = ele.offsetWidth || parseInt(ele.style.width);
const eleRight = ele.getBoundingClientRect().right || this.container.getBoundingClientRect().right + eleWidth;
return this.container.getBoundingClientRect().right - eleRight;
};
const danSpeed = (width) => (danWidth + width) / 5;
const getTunnel = (ele, type, width) => {
const tmp = danWidth / danSpeed(width);
for (let i = 0; ; i++) {
const item = this.danTunnel[type][i + ''];
if (item && item.length) {
if (type !== 'right') {
continue;
}
for (let j = 0; j < item.length; j++) {
const danRight = danItemRight(item[j]) - 10;
if (danRight <= danWidth - tmp * danSpeed(parseInt(item[j].style.width)) || danRight <= 0) {
break;
}
if (j === item.length - 1) {
this.danTunnel[type][i + ''].push(ele);
ele.addEventListener('animationend', () => {
this.danTunnel[type][i + ''].splice(0, 1);
});
return i % itemY;
}
}
}
else {
this.danTunnel[type][i + ''] = [ele];
ele.addEventListener('animationend', () => {
this.danTunnel[type][i + ''].splice(0, 1);
});
return i % itemY;
}
}
};
if (Object.prototype.toString.call(dan) !== '[object Array]') {
dan = [dan];
}
const docFragment = document.createDocumentFragment();
for (let i = 0; i < dan.length; i++) {
if (!dan[i].type) {
dan[i].type = 'right';
}
if (!dan[i].color) {
dan[i].color = '#fff';
}
const item = document.createElement(`div`);
item.classList.add(`dplayer-danmaku-item`);
item.classList.add(`dplayer-danmaku-${dan[i].type}`);
if (dan[i].border) {
item.innerHTML = `<span style="border:${dan[i].border}">${dan[i].text}</span>`;
}
else {
item.innerHTML = dan[i].text;
}
item.style.opacity = this._opacity;
item.style.color = dan[i].color;
item.addEventListener('animationend', () => {
this.container.removeChild(item);
});
const itemWidth = this._measure(dan[i].text);
// adjust
switch (dan[i].type) {
case 'right':
item.style.width = itemWidth + 1 + 'px';
item.style.top = itemHeight * getTunnel(item, dan[i].type, itemWidth) + 'px';
item.style.transform = `translateX(-${danWidth}px)`;
break;
case 'top':
item.style.top = itemHeight * getTunnel(item, dan[i].type) + 'px';
break;
case 'bottom':
item.style.bottom = itemHeight * getTunnel(item, dan[i].type) + 'px';
break;
default:
console.error(`Can't handled danmaku type: ${dan[i].type}`);
}
// move
item.classList.add(`dplayer-danmaku-move`);
// insert
docFragment.appendChild(item);
}
this.container.appendChild(docFragment);
return docFragment;
}
play () {
this.paused = false;
}
pause () {
this.paused = true;
}
_measure (text) {
if (!this.context) {
const measureStyle = getComputedStyle(this.container.getElementsByClassName('dplayer-danmaku-item')[0], null);
this.context = document.createElement('canvas').getContext('2d');
this.context.font = measureStyle.getPropertyValue('font');
}
return this.context.measureText(text).width;
}
seek () {
for (let i = 0; i < this.dan.length; i++) {
if (this.dan[i].time >= this.options.time()) {
this.danIndex = i;
break;
}
this.danIndex = this.dan.length;
}
}
clear () {
this.danTunnel = {
right: {},
top: {},
bottom: {}
};
this.danIndex = 0;
this.options.container.innerHTML = '';
}
htmlEncode (str) {
return str.
replace(/&/g, "&amp;").
replace(/</g, "&lt;").
replace(/>/g, "&gt;").
replace(/"/g, "&quot;").
replace(/'/g, "&#x27;").
replace(/\//g, "&#x2f;");
}
resetAnimation () {
const danWidth = this.container.offsetWidth;
const items = this.container.getElementsByClassName('dplayer-danmaku-item');
for (let i = 0; i < items.length; i++) {
items[i].style.transform = `translateX(-${danWidth}px)`;
}
}
}
module.exports = Danmaku;

View File

@ -1,4 +1,4 @@
// eslint-disable-next-line
console.log(`\n %c DPlayer ${DPLAYER_VERSION} %c http://dplayer.js.org \n\n`, 'color: #fadfa3; background: #030307; padding:5px 0;', 'background: #fadfa3; padding:5px 0;');
console.log(`${'\n'} %c DPlayer ${DPLAYER_VERSION} %c http://dplayer.js.org ${'\n'}${'\n'}`, 'color: #fadfa3; background: #030307; padding:5px 0;', 'background: #fadfa3; padding:5px 0;');
module.exports = require('./DPlayer');