Jelajahi Sumber

more events

DIYgod 8 tahun lalu
induk
melakukan
e6652554cc
9 mengubah file dengan 175 tambahan dan 64 penghapusan
  1. 12 0
      demo/demo.css
  2. 26 1
      demo/index.html
  3. 0 0
      dist/DPlayer.min.js
  4. 0 0
      dist/DPlayer.min.js.map
  5. 1 1
      package.json
  6. 58 60
      src/DPlayer.js
  7. 14 0
      src/danmaku.js
  8. 55 0
      src/events.js
  9. 9 2
      src/thumbnails.js

+ 12 - 0
demo/demo.css

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

+ 26 - 1
demo/index.html

@@ -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 ditekan karena terlalu besar
+ 0 - 0
dist/DPlayer.min.js


File diff ditekan karena terlalu besar
+ 0 - 0
dist/DPlayer.min.js.map


+ 1 - 1
package.json

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

+ 58 - 60
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];

+ 14 - 0
src/danmaku.js

@@ -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');
     }
 }
 

+ 55 - 0
src/events.js

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

+ 9 - 2
src/thumbnails.js

@@ -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');
     }
 }
 

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini