Browse Source

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

DIYgod 8 years ago
parent
commit
cc45df71bc
6 changed files with 148 additions and 51 deletions
  1. 1 0
      README.md
  2. 28 0
      demo/index.html
  3. 0 0
      dist/DPlayer.min.js
  4. 0 0
      dist/DPlayer.min.js.map
  5. 1 1
      package.json
  6. 118 50
      src/DPlayer.js

+ 1 - 0
README.md

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

+ 28 - 0
demo/index.html

@@ -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 it is too large
+ 0 - 0
dist/DPlayer.min.js


File diff suppressed because it is too large
+ 0 - 0
dist/DPlayer.min.js.map


+ 1 - 1
package.json

@@ -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": {

+ 118 - 50
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;

Some files were not shown because too many files changed in this diff