From c9e7f8aa1101da00b1e4042fddd4b58d6a73a305 Mon Sep 17 00:00:00 2001 From: DIYgod Date: Fri, 2 Mar 2018 01:50:53 +0800 Subject: [PATCH] time module; some optimize --- package.json | 2 +- src/css/index.scss | 4 +- src/js/controller.js | 17 +-- src/js/player.js | 292 +++++++++++++++++++--------------------- src/js/time.js | 0 src/js/timer.js | 62 +++++++++ src/template/player.art | 6 +- yarn.lock | 6 +- 8 files changed, 211 insertions(+), 178 deletions(-) delete mode 100644 src/js/time.js create mode 100644 src/js/timer.js diff --git a/package.json b/package.json index 68655bac..1b7c44ec 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,6 @@ }, "dependencies": { "balloon-css": "^0.5.0", - "promise-polyfill": "7.0.2" + "promise-polyfill": "7.1.0" } } diff --git a/src/css/index.scss b/src/css/index.scss index 909197c2..f1b786f9 100644 --- a/src/css/index.scss +++ b/src/css/index.scss @@ -146,7 +146,7 @@ $aplayer-height-lrc: $aplayer-height + $lrc-height - 6; bottom: 50%; right: 50%; margin: 0 -15px -15px 0; - .aplayer-icon-play { + svg { position: absolute; top: 3px; left: 4px; @@ -161,7 +161,7 @@ $aplayer-height-lrc: $aplayer-height + $lrc-height - 6; border: 2px solid #fff; bottom: 4px; right: 4px; - .aplayer-icon-pause { + svg { position: absolute; top: 2px; left: 2px; diff --git a/src/js/controller.js b/src/js/controller.js index 9657bfa8..9e3f23ef 100644 --- a/src/js/controller.js +++ b/src/js/controller.js @@ -51,9 +51,7 @@ class Controller { this.player.bar.set('played', 0, 'width'); } else { - this.player.bar.set('played', percentage, 'width'); - this.player.template.ptime.innerHTML = utils.secondToTime(percentage * this.player.audio.duration); - this.player.audio.currentTime = this.player.bar.get('played', 'width') * this.player.audio.duration; + this.player.seek(percentage * this.player.audio.duration); } }); @@ -70,7 +68,7 @@ class Controller { percentage = percentage > 0 ? percentage : 0; percentage = percentage < 1 ? percentage : 1; this.player.bar.set('played', percentage, 'width'); - this.player.lrc && this.player.lrc.update(this.player.bar.get('played', 'width') * this.player.audio.duration); + this.player.lrc && this.player.lrc.update(percentage * this.player.audio.duration); this.player.template.ptime.innerHTML = utils.secondToTime(percentage * this.player.audio.duration); }; @@ -81,19 +79,14 @@ class Controller { this.player.bar.set('played', 0, 'width'); } else { - this.player.audio.currentTime = this.player.bar.get('played', 'width') * this.player.audio.duration; - this.player.playedTime = setInterval(() => { - this.player.bar.set('played', this.player.audio.currentTime / this.player.audio.duration, 'width'); - this.player.lrc && this.player.lrc.update(); - this.player.template.ptime.innerHTML = utils.secondToTime(this.player.audio.currentTime); - this.player.trigger('playing'); - }, 100); + this.player.seek(this.player.bar.get('played', 'width') * this.player.audio.duration); + this.player.timer.enable('progress'); } }; this.player.template.thumb.addEventListener('mousedown', () => { barWidth = this.player.template.barWrap.clientWidth; - clearInterval(this.player.playedTime); + this.player.timer.disable('progress'); document.addEventListener('mousemove', thumbMove); document.addEventListener('mouseup', thumbUp); }); diff --git a/src/js/player.js b/src/js/player.js index cfc918ab..ee64a301 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -1,3 +1,5 @@ +import Promise from 'promise-polyfill'; + import utils from './utils'; import Icons from './icons'; import handleOption from './options'; @@ -6,6 +8,7 @@ import Bar from './bar'; import User from './user'; import Lrc from './lrc'; import Controller from './controller'; +import Timer from './timer'; const instances = []; @@ -103,6 +106,12 @@ class APlayer { this.controller = new Controller(this); + this.timer = new Timer(this); + + this.paused = true; + + this.initAudio(); + if (this.mode === 'random') { this.setMusic(this.randomOrder[0]); } @@ -120,6 +129,82 @@ class APlayer { instances.push(this); } + initAudio () { + this.audio = document.createElement('audio'); + this.audio.preload = this.options.preload ? this.options.preload : 'auto'; + + this.audio.addEventListener('play', () => { + if (this.paused) { + this.play(); + } + }); + + this.audio.addEventListener('pause', () => { + if (!this.paused) { + this.pause(); + } + }); + + // show audio time: the metadata has loaded or changed + this.audio.addEventListener('durationchange', () => { + if (this.audio.duration !== 1) { // compatibility: Android browsers will output 1 at first + this.template.dtime.innerHTML = utils.secondToTime(this.audio.duration); + } + }); + + // show audio loaded bar: to inform interested parties of progress downloading the media + this.audio.addEventListener('progress', () => { + const percentage = this.audio.buffered.length ? this.audio.buffered.end(this.audio.buffered.length - 1) / this.audio.duration : 0; + this.bar.set('loaded', percentage, 'width'); + }); + + // audio download error: an error occurs + this.audio.addEventListener('error', () => { + this.template.author.innerHTML = ` - Error happens ╥﹏╥`; + }); + + // multiple music play + this.audio.addEventListener('ended', () => { + if (this.isMultiple()) { + if (this.audio.currentTime !== 0) { + if (this.mode === 'random') { + this.setMusic(this.nextRandomNum()); + this.play(); + } + else if (this.mode === 'single') { + this.setMusic(this.playIndex); + this.play(); + } + else if (this.mode === 'order') { + if (this.playIndex < this.options.music.length - 1) { + this.setMusic(++this.playIndex); + this.play(); + } + else { + this.pause(); + } + } + else if (this.mode === 'circulation') { + this.playIndex = (this.playIndex + 1) % this.options.music.length; + this.setMusic(this.playIndex); + this.play(); + } + } + } + else { + if (this.mode === 'order') { + this.pause(); + } + } + }); + + // control volume + this.audio.volume = parseInt(this.template.volume.style.height) / 100; + + // loop + this.audio.loop = !(this.isMultiple() || this.mode === 'order'); + } + /** * Set music */ @@ -146,155 +231,11 @@ class APlayer { } this.template.listItems[indexMusic].classList.add('aplayer-list-light'); - // set the previous audio object - if (!utils.isMobile && this.audio) { - this.pause(); - this.audio.currentTime = 0; - } - this.template.list.scrollTop = indexMusic * 33; - // get this audio object - if (utils.isMobile && this.audio) { - this.audio.src = this.music.url; - } - else if (!utils.isMobile && this.audios[indexMusic]) { - this.audio = this.audios[indexMusic]; - this.audio.volume = parseInt(this.template.volume.style.height) / 100; - this.audio.currentTime = 0; - this.audio.src = this.music.url; - } - else { - this.audio = document.createElement("audio"); - this.audio.src = this.music.url; - this.audio.preload = this.options.preload ? this.options.preload : 'auto'; - - this.audio.addEventListener('play', () => { - if (this.template.button.classList.contains('aplayer-play')) { - this.template.button.classList.remove('aplayer-play'); - this.template.button.classList.add('aplayer-pause'); - this.template.button.innerHTML = ''; - setTimeout(() => { - this.template.button.innerHTML = ` - `; - }, 100); - - // pause other players (Thanks @Aprikyblue) - if (this.options.mutex) { - for (let i = 0; i < instances.length; i++) { - if (this !== instances[i]) { - instances[i].pause(); - } - } - } - if (this.playedTime) { - clearInterval(this.playedTime); - } - this.playedTime = setInterval(() => { - this.bar.set('played', this.audio.currentTime / this.audio.duration, 'width'); - this.lrc && this.lrc.update(); - this.template.ptime.innerHTML = utils.secondToTime(this.audio.currentTime); - this.trigger('playing'); - }, 100); - this.trigger('play'); - } - }); - - const pauseHandler = () => { - if (this.template.button && (this.template.button.classList.contains('aplayer-pause') || this.ended)) { - this.ended = false; - this.template.button.classList.remove('aplayer-pause'); - this.template.button.classList.add('aplayer-play'); - this.template.button.innerHTML = ''; - setTimeout(() => { - this.template.button.innerHTML = ` - `; - }, 100); - clearInterval(this.playedTime); - this.trigger('pause'); - } - }; - - this.audio.addEventListener('pause', pauseHandler); - - this.audio.addEventListener('abort', pauseHandler); - - // show audio time: the metadata has loaded or changed - this.audio.addEventListener('durationchange', () => { - if (this.audio.duration !== 1) { // compatibility: Android browsers will output 1 at first - this.template.dtime.innerHTML = utils.secondToTime(this.audio.duration); - } - }); - - // show audio loaded bar: to inform interested parties of progress downloading the media - this.audio.addEventListener('progress', () => { - const percentage = this.audio.buffered.length ? this.audio.buffered.end(this.audio.buffered.length - 1) / this.audio.duration : 0; - this.bar.set('loaded', percentage, 'width'); - }); - - // audio download error: an error occurs - this.audio.addEventListener('error', () => { - this.template.author.innerHTML = ` - Error happens ╥﹏╥`; - this.trigger('pause'); - }); - - // audio can play: enough data is available that the media can be played - this.audio.addEventListener('canplay', () => { - this.trigger('canplay'); - }); - - // multiple music play - this.ended = false; - this.audio.addEventListener('ended', () => { - if (this.isMultiple()) { - if (this.audio.currentTime !== 0) { - if (this.mode === 'random') { - this.setMusic(this.nextRandomNum()); - this.play(); - } - else if (this.mode === 'single') { - this.setMusic(this.playIndex); - this.play(); - } - else if (this.mode === 'order') { - if (this.playIndex < this.options.music.length - 1) { - this.setMusic(++this.playIndex); - this.play(); - } - else { - this.ended = true; - this.pause(); - this.trigger('ended'); - } - } - else if (this.mode === 'circulation') { - this.playIndex = (this.playIndex + 1) % this.options.music.length; - this.setMusic(this.playIndex); - this.play(); - } - } - } - else { - if (this.mode === 'order') { - this.ended = true; - this.pause(); - this.trigger('ended'); - } - } - }); - - // control volume - this.audio.volume = parseInt(this.template.volume.style.height) / 100; - - // loop - this.audio.loop = !(this.isMultiple() || this.mode === 'order'); - - this.audios[indexMusic] = this.audio; - } + this.pause(); + this.audio.currentTime = 0; + this.audio.src = this.music.url; this.lrc && this.lrc.switch(indexMusic); @@ -304,15 +245,46 @@ class APlayer { } } + seek (time) { + time = Math.max(time, 0); + if (this.audio.duration) { + time = Math.min(time, this.audio.duration); + } + + this.audio.currentTime = time; + + this.bar.set('played', time / this.audio.duration, 'width'); + this.template.ptime.innerHTML = utils.secondToTime(time); + } + /** * Play music */ - play (time) { - if (Object.prototype.toString.call(time) === '[object Number]') { - this.audio.currentTime = time; - } - if (this.audio.paused) { - this.audio.play(); + play () { + if (this.paused) { + this.paused = false; + this.template.button.classList.remove('aplayer-play'); + this.template.button.classList.add('aplayer-pause'); + this.template.button.innerHTML = ''; + setTimeout(() => { + this.template.button.innerHTML = Icons.pause; + }, 100); + } + + const playedPromise = Promise.resolve(this.audio.play()); + playedPromise.catch(() => { + this.pause(); + }).then(() => { + }); + + this.timer.enable('progress'); + + if (this.options.mutex) { + for (let i = 0; i < instances.length; i++) { + if (this !== instances[i]) { + instances[i].pause(); + } + } } } @@ -320,9 +292,19 @@ class APlayer { * Pause music */ pause () { - if (!this.audio.paused) { - this.audio.pause(); + if (!this.paused) { + this.paused = true; + + this.template.button.classList.remove('aplayer-pause'); + this.template.button.classList.add('aplayer-play'); + this.template.button.innerHTML = ''; + setTimeout(() => { + this.template.button.innerHTML = Icons.play; + }, 100); } + + this.audio.pause(); + this.timer.disable('progress'); } switchVolumeIcon () { diff --git a/src/js/time.js b/src/js/time.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/js/timer.js b/src/js/timer.js new file mode 100644 index 00000000..c0d75936 --- /dev/null +++ b/src/js/timer.js @@ -0,0 +1,62 @@ +import utils from './utils'; + +class Timer { + constructor (player) { + this.player = player; + + window.requestAnimationFrame = (() => + window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000 / 60); + } + )(); + + this.types = ['progress']; + + this.init(); + } + + init () { + for (let i = 0; i < this.types.length; i++) { + const type = this.types[i]; + if (type !== 'fps') { + this[`init${type}Checker`](); + } + } + } + + initprogressChecker () { + this.progressChecker = setInterval(() => { + if (this.enableprogressChecker) { + this.player.bar.set('played', this.player.audio.currentTime / this.player.audio.duration, 'width'); + this.player.lrc && this.player.lrc.update(); + const currentTime = utils.secondToTime(this.player.audio.currentTime); + if (this.player.template.ptime.innerHTML !== currentTime) { + this.player.template.ptime.innerHTML = currentTime; + } + } + }, 100); + } + + enable (type) { + this[`enable${type}Checker`] = true; + + if (type === 'fps') { + this.initfpsChecker(); + } + } + + disable (type) { + this[`enable${type}Checker`] = false; + } + + destroy (type) { + this[`${type}Checker`] && clearInterval(this[`${type}Checker`]); + } +} + +export default Timer; \ No newline at end of file diff --git a/src/template/player.art b/src/template/player.art index a6a5d45e..edea03dd 100644 --- a/src/template/player.art +++ b/src/template/player.art @@ -1,9 +1,5 @@
-
- -
+
{{@ icons.play }}
diff --git a/yarn.lock b/yarn.lock index e10290d9..e82a3ce1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4405,9 +4405,9 @@ progress@^2.0.0: version "2.0.0" resolved "http://registry.npm.taobao.org/progress/download/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" -promise-polyfill@7.0.2: - version "7.0.2" - resolved "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-7.0.2.tgz#9d54ffae166e2aea840ff5b8d8f5da9834331771" +promise-polyfill@7.1.0: + version "7.1.0" + resolved "http://registry.npm.taobao.org/promise-polyfill/download/promise-polyfill-7.1.0.tgz#4d749485b44577c14137591c6f36e5d7e2dd3378" proxy-addr@~2.0.2: version "2.0.2"