more events
This commit is contained in:
parent
97dfb6ae67
commit
e6652554cc
|
|
@ -88,6 +88,18 @@ summary {
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#events {
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
height: 120px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
#events p {
|
||||
margin: 0;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
/* github-corner */
|
||||
.github-corner:hover .octo-arm {
|
||||
animation: octocat-wave 560ms ease-in-out
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
<button class="btn" onclick="dp2.danmaku.hide()">danmaku.hide</button>
|
||||
<button class="btn" onclick="dp2.danmaku.show()">danmaku.show</button>
|
||||
<div id="dplayer2"></div>
|
||||
<div id="events"></div>
|
||||
<script>
|
||||
var dp2 = new DPlayer({
|
||||
element: document.getElementById('dplayer2'),
|
||||
|
|
@ -54,7 +55,8 @@
|
|||
video: {
|
||||
url: 'http://devtest.qiniudn.com/若能绽放光芒.mp4',
|
||||
pic: 'http://devtest.qiniudn.com/若能绽放光芒.png',
|
||||
type: 'auto'
|
||||
type: 'auto',
|
||||
thumbnails: 'http://devtest.qiniudn.com/thumbnails.jpg'
|
||||
},
|
||||
danmaku: {
|
||||
id: '9E2E3368B56CDBB4',
|
||||
|
|
@ -101,6 +103,29 @@
|
|||
});
|
||||
}
|
||||
}
|
||||
var events = [
|
||||
'abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'ended', 'error',
|
||||
'loadeddata', 'loadedmetadata', 'loadstart', 'mozaudioavailable', 'pause', 'play',
|
||||
'playing', 'ratechange', 'seeked', 'seeking', 'stalled',
|
||||
'volumechange', 'waiting',
|
||||
'screenshot',
|
||||
'thumbnails_show', 'thumbnails_hide',
|
||||
'danmaku_show', 'danmaku_hide', 'danmaku_clear',
|
||||
'danmaku_loaded', 'danmaku_send', 'danmaku_opacity',
|
||||
'contextmenu_show', 'contextmenu_hide',
|
||||
'notice_show', 'notice_hide',
|
||||
'quality_start', 'quality_end',
|
||||
'destroy',
|
||||
'resize',
|
||||
'fullscreen', 'fullscreen_cancel'
|
||||
];
|
||||
var eventsEle = document.getElementById('events');
|
||||
for (let i = 0; i < events.length; i++) {
|
||||
dp2.on(events[i], (info) => {
|
||||
eventsEle.innerHTML += '<p>Event: ' + events[i] + '</p>';
|
||||
eventsEle.scrollTop = eventsEle.scrollHeight;
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
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.8.1",
|
||||
"version": "1.9.0",
|
||||
"description": "Wow, such a lovely HTML5 danmaku video player",
|
||||
"main": "dist/DPlayer.min.js",
|
||||
"style": "dist/DPlayer.min.css",
|
||||
|
|
|
|||
118
src/DPlayer.js
118
src/DPlayer.js
|
|
@ -7,6 +7,7 @@ import i18n from './i18n';
|
|||
import html from './html';
|
||||
import Danmaku from './danmaku';
|
||||
import Thumbnails from './thumbnails';
|
||||
import Events from './events';
|
||||
|
||||
let index = 0;
|
||||
|
||||
|
|
@ -30,17 +31,7 @@ class DPlayer {
|
|||
|
||||
this.tran = new i18n(this.option.lang).tran;
|
||||
|
||||
// define DPlayer events
|
||||
const eventTypes = ['play', 'pause', 'canplay', 'playing', 'ended', 'error'];
|
||||
this.event = {};
|
||||
for (let i = 0; i < eventTypes.length; i++) {
|
||||
this.event[eventTypes[i]] = [];
|
||||
}
|
||||
this.trigger = (type) => {
|
||||
for (let i = 0; i < this.event[type].length; i++) {
|
||||
this.event[type][i]();
|
||||
}
|
||||
};
|
||||
this.events = new Events();
|
||||
|
||||
this.element = this.option.element;
|
||||
if (!this.option.danmaku) {
|
||||
|
|
@ -111,7 +102,8 @@ class DPlayer {
|
|||
maximum: this.option.danmaku.maximum,
|
||||
addition: this.option.danmaku.addition,
|
||||
user: this.option.danmaku.user,
|
||||
}
|
||||
},
|
||||
events: this.events
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -205,7 +197,6 @@ class DPlayer {
|
|||
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');
|
||||
}
|
||||
window.requestAnimationFrame(this.animationFrame);
|
||||
};
|
||||
|
|
@ -252,9 +243,7 @@ class DPlayer {
|
|||
this.isTimeTipsShow = true;
|
||||
this.mouseHandler = this.mouseHandler(pbar, pbarTimeTips).bind(this);
|
||||
pbar.addEventListener('mousemove', this.mouseHandler);
|
||||
pbar.addEventListener('mouseover', this.mouseHandler);
|
||||
pbar.addEventListener('mouseenter', this.mouseHandler);
|
||||
pbar.addEventListener('mouseout', this.mouseHandler);
|
||||
pbar.addEventListener('mouseleave', this.mouseHandler);
|
||||
|
||||
|
||||
|
|
@ -615,19 +604,13 @@ class DPlayer {
|
|||
* full screen
|
||||
*/
|
||||
this.element.addEventListener('fullscreenchange', () => {
|
||||
if (this.danmaku) {
|
||||
this.danmaku.resize();
|
||||
}
|
||||
this.resize();
|
||||
});
|
||||
this.element.addEventListener('mozfullscreenchange', () => {
|
||||
if (this.danmaku) {
|
||||
this.danmaku.resize();
|
||||
}
|
||||
this.resize();
|
||||
});
|
||||
this.element.addEventListener('webkitfullscreenchange', () => {
|
||||
if (this.danmaku) {
|
||||
this.danmaku.resize();
|
||||
}
|
||||
this.resize();
|
||||
});
|
||||
// browser full screen
|
||||
this.element.getElementsByClassName('dplayer-full-icon')[0].addEventListener('click', () => {
|
||||
|
|
@ -644,6 +627,8 @@ class DPlayer {
|
|||
else if (this.video.webkitEnterFullscreen) { // Safari for iOS
|
||||
this.video.webkitEnterFullscreen();
|
||||
}
|
||||
|
||||
this.events.trigger('fullscreen');
|
||||
}
|
||||
else {
|
||||
if (document.cancelFullScreen) {
|
||||
|
|
@ -655,10 +640,10 @@ class DPlayer {
|
|||
else if (document.webkitCancelFullScreen) {
|
||||
document.webkitCancelFullScreen();
|
||||
}
|
||||
|
||||
this.events.trigger('fullscreen_cancel');
|
||||
}
|
||||
if (this.danmaku) {
|
||||
this.danmaku.resize();
|
||||
}
|
||||
this.resize();
|
||||
});
|
||||
// web full screen
|
||||
this.element.getElementsByClassName('dplayer-full-in-icon')[0].addEventListener('click', () => {
|
||||
|
|
@ -667,9 +652,7 @@ class DPlayer {
|
|||
}
|
||||
else {
|
||||
this.element.classList.add('dplayer-fulled');
|
||||
if (this.danmaku) {
|
||||
this.danmaku.resize();
|
||||
}
|
||||
this.resize();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -721,9 +704,7 @@ class DPlayer {
|
|||
case 27:
|
||||
if (this.element.classList.contains('dplayer-fulled')) {
|
||||
this.element.classList.remove('dplayer-fulled');
|
||||
if (this.danmaku) {
|
||||
this.danmaku.resize();
|
||||
}
|
||||
this.resize();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -760,9 +741,14 @@ class DPlayer {
|
|||
}
|
||||
|
||||
mask.classList.add('dplayer-mask-show');
|
||||
|
||||
this.events.trigger('contextmenu_show');
|
||||
|
||||
mask.addEventListener('click', () => {
|
||||
mask.classList.remove('dplayer-mask-show');
|
||||
menu.classList.remove('dplayer-menu-show');
|
||||
|
||||
this.events.trigger('contextmenu_hide');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -788,8 +774,11 @@ class DPlayer {
|
|||
canvas.height = this.video.videoHeight;
|
||||
canvas.getContext('2d').drawImage(this.video, 0, 0, canvas.width, canvas.height);
|
||||
|
||||
camareIcon.href = canvas.toDataURL();
|
||||
const dataURL = canvas.toDataURL();
|
||||
camareIcon.href = dataURL;
|
||||
camareIcon.download = "DPlayer.png";
|
||||
|
||||
this.events.trigger('screenshot', dataURL);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -841,7 +830,6 @@ class DPlayer {
|
|||
if (this.danmaku) {
|
||||
this.danmaku.play();
|
||||
}
|
||||
this.trigger('play');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -864,7 +852,6 @@ class DPlayer {
|
|||
if (this.danmaku) {
|
||||
this.danmaku.pause();
|
||||
}
|
||||
this.trigger('pause');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -907,10 +894,8 @@ class DPlayer {
|
|||
/**
|
||||
* attach event
|
||||
*/
|
||||
on (event, callback) {
|
||||
if (typeof callback === 'function') {
|
||||
this.event[event].push(callback);
|
||||
}
|
||||
on (name, callback) {
|
||||
this.events.on(name, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -983,37 +968,30 @@ class DPlayer {
|
|||
* video events
|
||||
*/
|
||||
// show video time: the metadata has loaded or changed
|
||||
video.addEventListener('durationchange', () => {
|
||||
this.on('durationchange', () => {
|
||||
if (video.duration !== 1) { // compatibility: Android browsers will output 1 at first
|
||||
this.element.getElementsByClassName('dplayer-dtime')[0].innerHTML = utils.secondToTime(video.duration);
|
||||
}
|
||||
});
|
||||
|
||||
// show video loaded bar: to inform interested parties of progress downloading the media
|
||||
video.addEventListener('progress', () => {
|
||||
this.on('progress', () => {
|
||||
const percentage = video.buffered.length ? video.buffered.end(video.buffered.length - 1) / video.duration : 0;
|
||||
this.updateBar('loaded', percentage, 'width');
|
||||
});
|
||||
|
||||
// video download error: an error occurs
|
||||
video.addEventListener('error', () => {
|
||||
this.on('error', () => {
|
||||
this.tran && this.notice && this.notice(this.tran('This video fails to load'), -1);
|
||||
this.trigger && this.trigger('pause');
|
||||
});
|
||||
|
||||
// video can play: enough data is available that the media can be played
|
||||
video.addEventListener('canplay', () => {
|
||||
this.trigger('canplay');
|
||||
});
|
||||
|
||||
// video end
|
||||
this.ended = false;
|
||||
video.addEventListener('ended', () => {
|
||||
this.on('ended', () => {
|
||||
this.updateBar('played', 1, 'width');
|
||||
if (!this.loop) {
|
||||
this.ended = true;
|
||||
this.pause();
|
||||
this.trigger('ended');
|
||||
}
|
||||
else {
|
||||
this.seek(0);
|
||||
|
|
@ -1024,18 +1002,24 @@ class DPlayer {
|
|||
}
|
||||
});
|
||||
|
||||
video.addEventListener('play', () => {
|
||||
this.on('play', () => {
|
||||
if (this.paused) {
|
||||
this.play();
|
||||
}
|
||||
});
|
||||
|
||||
video.addEventListener('pause', () => {
|
||||
this.on('pause', () => {
|
||||
if (!this.paused) {
|
||||
this.pause();
|
||||
}
|
||||
});
|
||||
|
||||
for (let i = 0; i < this.events.videoEvents.length; i++) {
|
||||
video.addEventListener(this.events.videoEvents[i], () => {
|
||||
this.events.trigger(this.events.videoEvents[i]);
|
||||
});
|
||||
}
|
||||
|
||||
this.volume(localStorage.getItem('dplayer-volume') || this.option.volume, true, true);
|
||||
}
|
||||
|
||||
|
|
@ -1061,7 +1045,9 @@ class DPlayer {
|
|||
this.initVideo(this.video, this.quality.type || this.option.video.type);
|
||||
this.seek(this.prevVideo.currentTime);
|
||||
this.notice(`${this.tran('Switching to')} ${this.quality.name} ${this.tran('quality')}`, -1);
|
||||
this.video.addEventListener('canplay', () => {
|
||||
this.events.trigger('quality_start', this.quality);
|
||||
|
||||
this.on('canplay', () => {
|
||||
if (this.prevVideo) {
|
||||
if (this.video.currentTime !== this.prevVideo.currentTime) {
|
||||
this.seek(this.prevVideo.currentTime);
|
||||
|
|
@ -1075,6 +1061,8 @@ class DPlayer {
|
|||
this.prevVideo = null;
|
||||
this.notice(`${this.tran('Switched to')} ${this.quality.name} ${this.tran('quality')}`);
|
||||
this.switchingQuality = false;
|
||||
|
||||
this.events.trigger('quality_end');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -1110,14 +1098,14 @@ class DPlayer {
|
|||
|
||||
switch (e.type) {
|
||||
case 'mouseenter':
|
||||
case 'mouseover':
|
||||
this.thumbnails && this.thumbnails.show();
|
||||
break;
|
||||
case 'mousemove':
|
||||
this.thumbnails && this.thumbnails.show(tx);
|
||||
this.thumbnails && this.thumbnails.move(tx);
|
||||
timeTips.innerText = utils.secondToTime(time);
|
||||
this.timeTipsDisplay(true, timeTips);
|
||||
break;
|
||||
case 'mouseleave':
|
||||
case 'mouseout':
|
||||
this.thumbnails && this.thumbnails.hide();
|
||||
this.timeTipsDisplay(false, timeTips);
|
||||
break;
|
||||
|
|
@ -1142,11 +1130,10 @@ class DPlayer {
|
|||
}
|
||||
|
||||
initThumbnails () {
|
||||
this.thumbnails = new Thumbnails(this.element.getElementsByClassName('dplayer-bar-preview')[0], this.element.getElementsByClassName('dplayer-bar-wrap')[0].offsetWidth, this.option.video.thumbnails);
|
||||
this.thumbnails = new Thumbnails(this.element.getElementsByClassName('dplayer-bar-preview')[0], this.element.getElementsByClassName('dplayer-bar-wrap')[0].offsetWidth, this.option.video.thumbnails, this.events);
|
||||
|
||||
this.video.addEventListener('loadedmetadata', () => {
|
||||
this.on('loadedmetadata', () => {
|
||||
this.thumbnails.resize(160, 90);
|
||||
// this.thumbnails.resize(this.element.offsetWidth / 4, this.element.offsetHeight / 4);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1157,16 +1144,27 @@ class DPlayer {
|
|||
if (this.noticeTime) {
|
||||
clearTimeout(this.noticeTime);
|
||||
}
|
||||
this.events.trigger('notice_show', text);
|
||||
this.noticeTime = setTimeout(() => {
|
||||
noticeEle.style.opacity = 0;
|
||||
this.events.trigger('notice_hide');
|
||||
}, time);
|
||||
}
|
||||
|
||||
resize () {
|
||||
if (this.danmaku) {
|
||||
this.danmaku.resize();
|
||||
}
|
||||
this.events.trigger('resize');
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.pause();
|
||||
clearTimeout(this.hideTime);
|
||||
this.video.src = '';
|
||||
this.element.innerHTML = '';
|
||||
this.events.trigger('destroy');
|
||||
|
||||
for (const key in this) {
|
||||
if (this.hasOwnProperty(key) && key !== 'paused') {
|
||||
delete this[key];
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class Danmaku {
|
|||
this.dan = [];
|
||||
this.showing = true;
|
||||
this._opacity = this.options.opacity;
|
||||
this.events = this.options.events;
|
||||
|
||||
this.load();
|
||||
}
|
||||
|
|
@ -25,6 +26,7 @@ class Danmaku {
|
|||
}
|
||||
const endpoints = (this.options.api.addition || []).slice(0);
|
||||
endpoints.push(apiurl);
|
||||
this.events && this.events.trigger('danmaku_load_start', endpoints);
|
||||
|
||||
this._readAllEndpoints(endpoints, (results) => {
|
||||
this.dan = [].concat.apply([], results).sort((a, b) => a.time - b.time);
|
||||
|
|
@ -33,6 +35,8 @@ class Danmaku {
|
|||
});
|
||||
|
||||
this.options.callback();
|
||||
|
||||
this.events && this.events.trigger('danmaku_load_end');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +98,8 @@ class Danmaku {
|
|||
border: `2px solid ${this.options.borderColor}`
|
||||
};
|
||||
this.draw(danmaku);
|
||||
|
||||
this.events && this.events.trigger('danmaku_send', danmakuData);
|
||||
}
|
||||
|
||||
frame () {
|
||||
|
|
@ -119,6 +125,8 @@ class Danmaku {
|
|||
}
|
||||
this._opacity = percentage;
|
||||
localStorage.setItem('danmaku-opacity', this._opacity);
|
||||
|
||||
this.events && this.events.trigger('danmaku_opacity', this._opacity);
|
||||
}
|
||||
return this._opacity;
|
||||
}
|
||||
|
|
@ -285,6 +293,8 @@ class Danmaku {
|
|||
};
|
||||
this.danIndex = 0;
|
||||
this.options.container.innerHTML = '';
|
||||
|
||||
this.events && this.events.trigger('danmaku_clear');
|
||||
}
|
||||
|
||||
htmlEncode (str) {
|
||||
|
|
@ -309,12 +319,16 @@ class Danmaku {
|
|||
this.showing = false;
|
||||
this.pause();
|
||||
this.clear();
|
||||
|
||||
this.events && this.events.trigger('danmaku_hide');
|
||||
}
|
||||
|
||||
show () {
|
||||
this.seek();
|
||||
this.showing = true;
|
||||
this.play();
|
||||
|
||||
this.events && this.events.trigger('danmaku_show');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
class Events {
|
||||
constructor () {
|
||||
this.events = {};
|
||||
|
||||
this.videoEvents = [
|
||||
'abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'ended', 'error',
|
||||
'loadeddata', 'loadedmetadata', 'loadstart', 'mozaudioavailable', 'pause', 'play',
|
||||
'playing', 'progress', 'ratechange', 'seeked', 'seeking', 'stalled', 'suspend',
|
||||
'timeupdate', 'volumechange', 'waiting'
|
||||
];
|
||||
this.playerEvents = [
|
||||
'screenshot',
|
||||
'thumbnails_show', 'thumbnails_hide',
|
||||
'danmaku_show', 'danmaku_hide', 'danmaku_clear', 'danmaku_loaded', 'danmaku_send',
|
||||
'danmaku_opacity',
|
||||
'contextmenu_show', 'contextmenu_hide',
|
||||
'notice_show', 'notice_hide',
|
||||
'quality_start', 'quality_end',
|
||||
'destroy',
|
||||
'resize',
|
||||
'fullscreen', 'fullscreen_cancel'
|
||||
];
|
||||
}
|
||||
|
||||
on (name, callback) {
|
||||
if (this.type(name) && typeof callback === 'function') {
|
||||
if (!this.events[name]) {
|
||||
this.events[name] = [];
|
||||
}
|
||||
this.events[name].push(callback);
|
||||
}
|
||||
}
|
||||
|
||||
trigger (name, info) {
|
||||
if (this.events[name] && this.events[name].length) {
|
||||
for (let i = 0; i < this.events[name].length; i++) {
|
||||
this.events[name][i](info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type (name) {
|
||||
if (this.playerEvents.indexOf(name) !== -1) {
|
||||
return 'player';
|
||||
}
|
||||
else if (this.videoEvents.indexOf(name) !== -1) {
|
||||
return 'video';
|
||||
}
|
||||
|
||||
console.error(`Unknown event name: ${name}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Events;
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
class Thumbnails {
|
||||
constructor (container, width, url) {
|
||||
constructor (container, width, url, events) {
|
||||
this.container = container;
|
||||
this.width = width;
|
||||
this.container.style.backgroundImage = `url('${url}')`;
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
resize (width, height) {
|
||||
|
|
@ -11,14 +12,20 @@ class Thumbnails {
|
|||
this.container.style.top = `${-height + 2}px`;
|
||||
}
|
||||
|
||||
show (position) {
|
||||
show () {
|
||||
this.container.style.display = 'block';
|
||||
this.events && this.events.trigger('thumbnails_show');
|
||||
}
|
||||
|
||||
move (position) {
|
||||
this.container.style.backgroundPosition = `-${(Math.ceil(position / this.width * 100) - 1) * 160}px 0`;
|
||||
this.container.style.left = `${(position - this.container.offsetWidth / 2)}px`;
|
||||
}
|
||||
|
||||
hide () {
|
||||
this.container.style.display = 'none';
|
||||
|
||||
this.events && this.events.trigger('thumbnails_hide');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue