new API: switchVideo(video, danmaku), close: #11

This commit is contained in:
DIYgod 2016-10-08 11:15:01 +08:00
parent 20f0e6fc39
commit cc45df71bc
No known key found for this signature in database
GPG Key ID: F8797DD1088C6506
6 changed files with 152 additions and 55 deletions

View File

@ -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

View File

@ -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();

6
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.0.10",
"version": "1.0.11",
"description": "Wow, such a lovely HTML5 danmaku video player",
"main": "dist/DPlayer.min.js",
"scripts": {

View File

@ -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;