new API: switchVideo(video, danmaku), close: #11
This commit is contained in:
parent
20f0e6fc39
commit
cc45df71bc
|
|
@ -71,6 +71,7 @@ var option = {
|
|||
+ `dp.pause()` // Pause
|
||||
+ `dp.toggle()` // Toggle between play and pause
|
||||
+ `dp.on(event, handler)` // Event binding
|
||||
+ `switchVideo(video, danmaku)` // Switch to a new video, the format of `video` and `danmaku` is the same as option
|
||||
+ `dp.dan` // Return danmaku info
|
||||
+ `dp.danIndex` // Return danmaku index
|
||||
+ `dp.video` // Return native video, most [native api](http://www.w3schools.com/tags/ref_av_dom.asp) are supported
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@
|
|||
<p>Made by <a href="https://www.anotherhome.net/" target="_blank">DIYgod</a>. Available on <a href="https://github.com/DIYgod/DPlayer" target="_blank">GitHub</a>. Licensed SATA.</p>
|
||||
<hr>
|
||||
<div class="dplayer"></div>
|
||||
<br>
|
||||
<button onclick="switchDPlayer()">Switch Video</button>
|
||||
</div>
|
||||
<script src="https://rawgit.com/mrdoob/stats.js/master/build/stats.min.js"></script>
|
||||
<script src="../dist/DPlayer.min.js"></script>
|
||||
|
|
@ -74,6 +76,32 @@
|
|||
maximum: 3000
|
||||
}
|
||||
});
|
||||
function switchDPlayer() {
|
||||
if (dp.option.danmaku.id !== '5rGf5Y2X55qu6Z2p') {
|
||||
dp.switchVideo({
|
||||
url: 'http://devtest.qiniudn.com/微小微-江南皮革厂倒闭了.mp4',
|
||||
pic: 'http://devtest.qiniudn.com/微小微-江南皮革厂倒闭了.jpg'
|
||||
},
|
||||
{
|
||||
id: '5rGf5Y2X55qu6Z2p',
|
||||
api: 'https://dplayer.daoapp.io/',
|
||||
token: 'tokendemo',
|
||||
maximum: 3000
|
||||
});
|
||||
}
|
||||
else {
|
||||
dp.switchVideo({
|
||||
url: 'http://devtest.qiniudn.com/若能绽放光芒.mp4',
|
||||
pic: 'http://devtest.qiniudn.com/若能绽放光芒.png'
|
||||
},
|
||||
{
|
||||
id: '9E2E3368B56CDBB4',
|
||||
api: 'https://dplayer.daoapp.io/',
|
||||
token: 'tokendemo',
|
||||
maximum: 3000
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// stats.js: JavaScript Performance Monitor
|
||||
var stats = new Stats();
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "dplayer",
|
||||
"version": "1.0.10",
|
||||
"version": "1.0.11",
|
||||
"description": "Wow, such a lovely HTML5 danmaku video player",
|
||||
"main": "dist/DPlayer.min.js",
|
||||
"scripts": {
|
||||
|
|
|
|||
168
src/DPlayer.js
168
src/DPlayer.js
|
|
@ -1,4 +1,4 @@
|
|||
console.log("\n %c DPlayer 1.0.10 %c http://dplayer.js.org \n\n","color: #fadfa3; background: #030307; padding:5px 0;","background: #fadfa3; padding:5px 0;");
|
||||
console.log("\n %c DPlayer 1.0.11 %c http://dplayer.js.org \n\n","color: #fadfa3; background: #030307; padding:5px 0;","background: #fadfa3; padding:5px 0;");
|
||||
|
||||
require('./DPlayer.scss');
|
||||
|
||||
|
|
@ -37,10 +37,12 @@ class DPlayer {
|
|||
`;
|
||||
};
|
||||
|
||||
this.option = option;
|
||||
|
||||
const isMobile = /mobile/i.test(window.navigator.userAgent);
|
||||
// compatibility: some mobile browsers don't suppose autoplay
|
||||
if (isMobile) {
|
||||
option.autoplay = false;
|
||||
this.option.autoplay = false;
|
||||
}
|
||||
|
||||
// default options
|
||||
|
|
@ -55,8 +57,8 @@ class DPlayer {
|
|||
preload: 'auto'
|
||||
};
|
||||
for (let defaultKey in defaultOption) {
|
||||
if (defaultOption.hasOwnProperty(defaultKey) && !option.hasOwnProperty(defaultKey)) {
|
||||
option[defaultKey] = defaultOption[defaultKey];
|
||||
if (defaultOption.hasOwnProperty(defaultKey) && !this.option.hasOwnProperty(defaultKey)) {
|
||||
this.option[defaultKey] = defaultOption[defaultKey];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,10 +81,10 @@ class DPlayer {
|
|||
'Danmaku': '弹幕'
|
||||
};
|
||||
const getTran = (text) => {
|
||||
if (option.lang === 'en') {
|
||||
if (this.option.lang === 'en') {
|
||||
return text;
|
||||
}
|
||||
else if (option.lang === 'zh') {
|
||||
else if (this.option.lang === 'zh') {
|
||||
return tranZH[text];
|
||||
}
|
||||
};
|
||||
|
|
@ -112,16 +114,16 @@ class DPlayer {
|
|||
}
|
||||
};
|
||||
|
||||
this.element = option.element;
|
||||
if (!option.danmaku) {
|
||||
this.element = this.option.element;
|
||||
if (!this.option.danmaku) {
|
||||
this.element.classList.add('dplayer-no-danmaku');
|
||||
}
|
||||
|
||||
if (isMobile) {
|
||||
this.element.innerHTML = `
|
||||
<div class="dplayer-video-wrap">
|
||||
<video class="dplayer-video" ${option.video.pic ? `poster="${option.video.pic}"` : ``} preload="${option.preload}" controls>
|
||||
<source src="${option.video.url}">
|
||||
<video class="dplayer-video" ${this.option.video.pic ? `poster="${this.option.video.pic}"` : ``} preload="${this.option.preload}" controls>
|
||||
<source src="${this.option.video.url}">
|
||||
</video>
|
||||
</div>`;
|
||||
return;
|
||||
|
|
@ -130,15 +132,13 @@ class DPlayer {
|
|||
this.element.innerHTML = `
|
||||
<div class="dplayer-mask"></div>
|
||||
<div class="dplayer-video-wrap">
|
||||
<video class="dplayer-video" ${option.video.pic ? `poster="${option.video.pic}"` : ``} ${option.screenshot ? `crossorigin="anonymous"` : ``} preload="${option.preload}">
|
||||
<source src="${option.video.url}">
|
||||
</video>
|
||||
<video class="dplayer-video" ${this.option.video.pic ? `poster="${this.option.video.pic}"` : ``} ${this.option.screenshot ? `crossorigin="anonymous"` : ``} preload="${this.option.preload}" src="${this.option.video.url}"></video>
|
||||
<div class="dplayer-danmaku">
|
||||
<div class="dplayer-danmaku-item dplayer-danmaku-item--demo"></div>
|
||||
</div>
|
||||
<div class="dplayer-bezel">
|
||||
<span class="dplayer-bezel-icon"></span>
|
||||
${option.danmaku ? `<span class="dplayer-danloading">${getTran('Danmaku is loading')}</span>` : ``}
|
||||
${this.option.danmaku ? `<span class="dplayer-danloading">${getTran('Danmaku is loading')}</span>` : ``}
|
||||
<span class="diplayer-loading-icon">
|
||||
<svg height="100%" version="1.1" viewBox="0 0 22 22" width="100%">
|
||||
<svg x="7" y="1">
|
||||
|
|
@ -181,8 +181,8 @@ class DPlayer {
|
|||
+ ` </button>
|
||||
<div class="dplayer-volume-bar-wrap">
|
||||
<div class="dplayer-volume-bar">
|
||||
<div class="dplayer-volume-bar-inner" style="width: 70%; background: ${option.theme};">
|
||||
<span class="dplayer-thumb" style="background: ${option.theme}"></span>
|
||||
<div class="dplayer-volume-bar-inner" style="width: 70%; background: ${this.option.theme};">
|
||||
<span class="dplayer-thumb" style="background: ${this.option.theme}"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -190,7 +190,7 @@ class DPlayer {
|
|||
<span class="dplayer-time"><span class="dplayer-ptime">0:00</span> / <span class="dplayer-dtime">0:00</span></span>
|
||||
</div>
|
||||
<div class="dplayer-icons dplayer-icons-right">
|
||||
${option.screenshot ? `
|
||||
${this.option.screenshot ? `
|
||||
<a href="#" class="dplayer-icon dplayer-camera-icon">`
|
||||
+ this.getSVG('camera')
|
||||
+ ` </a>
|
||||
|
|
@ -266,8 +266,8 @@ class DPlayer {
|
|||
<div class="dplayer-bar-wrap">
|
||||
<div class="dplayer-bar">
|
||||
<div class="dplayer-loaded" style="width: 0;"></div>
|
||||
<div class="dplayer-played" style="width: 0; background: ${option.theme}">
|
||||
<span class="dplayer-thumb" style="background: ${option.theme}"></span>
|
||||
<div class="dplayer-played" style="width: 0; background: ${this.option.theme}">
|
||||
<span class="dplayer-thumb" style="background: ${this.option.theme}"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -283,12 +283,12 @@ class DPlayer {
|
|||
this.video = this.element.getElementsByClassName('dplayer-video')[0];
|
||||
|
||||
// Support HTTP Live Streaming
|
||||
if (option.video.url.match(/(m3u8)$/i) && Hls.isSupported()) {
|
||||
if (this.option.video.url.match(/(m3u8)$/i) && Hls.isSupported()) {
|
||||
this.element.getElementsByClassName('dplayer-time')[0].style.display = 'none';
|
||||
const hls = new Hls();
|
||||
hls.attachMedia(this.video);
|
||||
hls.on(Hls.Events.MEDIA_ATTACHED, () => {
|
||||
hls.loadSource(option.video.url);
|
||||
hls.loadSource(this.option.video.url);
|
||||
hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
|
||||
console.log("manifest loaded, found " + data.levels.length + " quality level");
|
||||
});
|
||||
|
|
@ -396,7 +396,7 @@ class DPlayer {
|
|||
const pbar = this.element.getElementsByClassName('dplayer-bar-wrap')[0];
|
||||
let barWidth;
|
||||
|
||||
if (option.danmaku) {
|
||||
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) {
|
||||
|
|
@ -434,7 +434,7 @@ class DPlayer {
|
|||
this.element.getElementsByClassName('dplayer-ptime')[0].innerHTML = secondToTime(this.video.currentTime);
|
||||
this.trigger('playing');
|
||||
}, 100);
|
||||
if (option.danmaku) {
|
||||
if (this.option.danmaku) {
|
||||
danmakuTime = setInterval(() => {
|
||||
let item = this.dan[this.danIndex];
|
||||
while (item && this.video.currentTime >= parseFloat(item.time)) {
|
||||
|
|
@ -446,7 +446,7 @@ class DPlayer {
|
|||
};
|
||||
this.clearTime = () => {
|
||||
clearInterval(this.playedTime);
|
||||
if (option.danmaku) {
|
||||
if (this.option.danmaku) {
|
||||
clearInterval(danmakuTime);
|
||||
}
|
||||
};
|
||||
|
|
@ -649,7 +649,7 @@ class DPlayer {
|
|||
openSetting();
|
||||
});
|
||||
|
||||
let loop = option.loop;
|
||||
let loop = this.option.loop;
|
||||
const danContainer = this.element.getElementsByClassName('dplayer-danmaku')[0];
|
||||
let showdan = true;
|
||||
const settingEvent = () => {
|
||||
|
|
@ -682,7 +682,7 @@ class DPlayer {
|
|||
showDanToggle.checked = !showDanToggle.checked;
|
||||
if (showDanToggle.checked) {
|
||||
showdan = true;
|
||||
if (option.danmaku) {
|
||||
if (this.option.danmaku) {
|
||||
for (let i = 0; i < this.dan.length; i++) {
|
||||
if (this.dan[i].time >= this.video.currentTime) {
|
||||
this.danIndex = i;
|
||||
|
|
@ -701,14 +701,15 @@ class DPlayer {
|
|||
}
|
||||
else {
|
||||
showdan = false;
|
||||
if (option.danmaku) {
|
||||
if (this.option.danmaku) {
|
||||
clearInterval(danmakuTime);
|
||||
danContainer.innerHTML = `<div class="dplayer-danmaku-item dplayer-danmaku-item--demo"></div>`;
|
||||
let danTunnel = {
|
||||
this.danTunnel = {
|
||||
right: {},
|
||||
top: {},
|
||||
bottom: {}
|
||||
};
|
||||
this.itemDemo = this.element.getElementsByClassName('dplayer-danmaku-item')[0];
|
||||
}
|
||||
}
|
||||
closeSetting();
|
||||
|
|
@ -729,7 +730,7 @@ class DPlayer {
|
|||
}
|
||||
});
|
||||
|
||||
if (option.danmaku) {
|
||||
if (this.option.danmaku) {
|
||||
// danmaku opacity
|
||||
bar.danmakuBar = this.element.getElementsByClassName('dplayer-danmaku-bar-inner')[0];
|
||||
const danmakuBarWrapWrap = this.element.getElementsByClassName('dplayer-danmaku-bar-wrap')[0];
|
||||
|
|
@ -837,7 +838,7 @@ class DPlayer {
|
|||
let danWidth;
|
||||
let danHeight;
|
||||
let itemY;
|
||||
let danTunnel = {
|
||||
this.danTunnel = {
|
||||
right: {},
|
||||
top: {},
|
||||
bottom: {}
|
||||
|
|
@ -855,7 +856,7 @@ class DPlayer {
|
|||
const tmp = danWidth / danSpeed(width);
|
||||
|
||||
for (let i = 0; ; i++) {
|
||||
let item = danTunnel[type][i + ''];
|
||||
let item = this.danTunnel[type][i + ''];
|
||||
if (item && item.length) {
|
||||
for (let j = 0; j < item.length; j++) {
|
||||
const danRight = danItemRight(item[j]) - 10;
|
||||
|
|
@ -863,25 +864,25 @@ class DPlayer {
|
|||
break;
|
||||
}
|
||||
if (j === item.length - 1) {
|
||||
danTunnel[type][i + ''].push(ele);
|
||||
this.danTunnel[type][i + ''].push(ele);
|
||||
ele.addEventListener('animationend', () => {
|
||||
danTunnel[type][i + ''].splice(0, 1);
|
||||
this.danTunnel[type][i + ''].splice(0, 1);
|
||||
});
|
||||
return i % itemY;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
danTunnel[type][i + ''] = [ele];
|
||||
this.danTunnel[type][i + ''] = [ele];
|
||||
ele.addEventListener('animationend', () => {
|
||||
danTunnel[type][i + ''].splice(0, 1);
|
||||
this.danTunnel[type][i + ''].splice(0, 1);
|
||||
});
|
||||
return i % itemY;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const itemDemo = this.element.getElementsByClassName('dplayer-danmaku-item')[0];
|
||||
this.itemDemo = this.element.getElementsByClassName('dplayer-danmaku-item')[0];
|
||||
|
||||
const danmakuIn = (text, color, type) => {
|
||||
danWidth = danContainer.offsetWidth;
|
||||
|
|
@ -898,8 +899,8 @@ class DPlayer {
|
|||
});
|
||||
|
||||
// measure
|
||||
itemDemo.innerHTML = text;
|
||||
let itemWidth = itemDemo.offsetWidth;
|
||||
this.itemDemo.innerHTML = text;
|
||||
let itemWidth = this.itemDemo.offsetWidth;
|
||||
|
||||
// adjust
|
||||
switch (type) {
|
||||
|
|
@ -928,7 +929,7 @@ class DPlayer {
|
|||
};
|
||||
|
||||
// danmaku
|
||||
if (option.danmaku) {
|
||||
if (this.option.danmaku) {
|
||||
this.danIndex = 0;
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
|
|
@ -943,7 +944,7 @@ class DPlayer {
|
|||
this.element.getElementsByClassName('dplayer-danloading')[0].style.display = 'none';
|
||||
|
||||
// autoplay
|
||||
if (option.autoplay && !isMobile) {
|
||||
if (this.option.autoplay && !isMobile) {
|
||||
this.play();
|
||||
}
|
||||
else if (isMobile) {
|
||||
|
|
@ -957,18 +958,18 @@ class DPlayer {
|
|||
}
|
||||
};
|
||||
let apiurl;
|
||||
if (option.danmaku.maximum) {
|
||||
apiurl = `${option.danmaku.api}?id=${option.danmaku.id}&max=${option.danmaku.maximum}`;
|
||||
if (this.option.danmaku.maximum) {
|
||||
apiurl = `${this.option.danmaku.api}?id=${this.option.danmaku.id}&max=${this.option.danmaku.maximum}`;
|
||||
}
|
||||
else {
|
||||
apiurl = `${option.danmaku.api}?id=${option.danmaku.id}`;
|
||||
apiurl = `${this.option.danmaku.api}?id=${this.option.danmaku.id}`;
|
||||
}
|
||||
xhr.open('get', apiurl, true);
|
||||
xhr.send(null);
|
||||
}
|
||||
else {
|
||||
// autoplay
|
||||
if (option.autoplay && !isMobile) {
|
||||
if (this.option.autoplay && !isMobile) {
|
||||
this.play();
|
||||
}
|
||||
else if (isMobile) {
|
||||
|
|
@ -1006,8 +1007,8 @@ class DPlayer {
|
|||
}
|
||||
|
||||
const danmakuData = {
|
||||
token: option.danmaku.token,
|
||||
player: option.danmaku.id,
|
||||
token: this.option.danmaku.token,
|
||||
player: this.option.danmaku.id,
|
||||
author: 'DIYgod',
|
||||
time: this.video.currentTime,
|
||||
text: commentInput.value,
|
||||
|
|
@ -1031,7 +1032,7 @@ class DPlayer {
|
|||
}
|
||||
}
|
||||
};
|
||||
xhr.open('post', option.danmaku.api, true);
|
||||
xhr.open('post', this.option.danmaku.api, true);
|
||||
xhr.send(JSON.stringify(danmakuData));
|
||||
|
||||
commentInput.value = '';
|
||||
|
|
@ -1039,7 +1040,7 @@ class DPlayer {
|
|||
this.dan.splice(this.danIndex, 0, danmakuData);
|
||||
this.danIndex++;
|
||||
const item = danmakuIn(htmlEncode(danmakuData.text), danmakuData.color, danmakuData.type);
|
||||
item.style.border = `2px solid ${option.theme}`;
|
||||
item.style.border = `2px solid ${this.option.theme}`;
|
||||
};
|
||||
|
||||
const closeCommentSetting = () => {
|
||||
|
|
@ -1193,7 +1194,7 @@ class DPlayer {
|
|||
}
|
||||
}
|
||||
};
|
||||
if (option.hotkey) {
|
||||
if (this.option.hotkey) {
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
}
|
||||
|
||||
|
|
@ -1218,7 +1219,7 @@ class DPlayer {
|
|||
/**
|
||||
* Screenshot
|
||||
*/
|
||||
if (option.screenshot) {
|
||||
if (this.option.screenshot) {
|
||||
const camareIcon = this.element.getElementsByClassName('dplayer-camera-icon')[0];
|
||||
camareIcon.addEventListener('click', () => {
|
||||
const canvas = document.createElement("canvas");
|
||||
|
|
@ -1313,6 +1314,73 @@ class DPlayer {
|
|||
this.event[name].push(func);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a new video
|
||||
*
|
||||
* @param {Object} video - new video info
|
||||
* @param {Object} danmaku - new danmaku info
|
||||
*/
|
||||
switchVideo(video, danmaku) {
|
||||
this.video.src = video.url;
|
||||
this.video.poster = video.pic ? video.pic : '';
|
||||
this.video.currentTime = 0;
|
||||
this.pause();
|
||||
if (danmaku) {
|
||||
this.dan = [];
|
||||
this.danIndex = 0;
|
||||
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 = `<div class="dplayer-danmaku-item dplayer-danmaku-item--demo"></div>`;
|
||||
this.danTunnel = {
|
||||
right: {},
|
||||
top: {},
|
||||
bottom: {}
|
||||
};
|
||||
this.itemDemo = this.element.getElementsByClassName('dplayer-danmaku-item')[0];
|
||||
|
||||
const isMobile = /mobile/i.test(window.navigator.userAgent);
|
||||
this.option.danmaku = danmaku;
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
if (response.code !== 1) {
|
||||
alert(response.msg);
|
||||
}
|
||||
else {
|
||||
this.danIndex = 0;
|
||||
this.dan = response.danmaku.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log('Request was unsuccessful: ' + xhr.status);
|
||||
}
|
||||
}
|
||||
};
|
||||
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}`;
|
||||
}
|
||||
xhr.open('get', apiurl, true);
|
||||
xhr.send(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DPlayer;
|
||||
Loading…
Reference in New Issue