diff --git a/src/css/index.scss b/src/css/index.scss index 426959a..5923ab4 100644 --- a/src/css/index.scss +++ b/src/css/index.scss @@ -37,6 +37,9 @@ $aplayer-height-lrc: $aplayer-height + $lrc-height - 6; .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon.aplayer-icon-menu { display: inline; } + .aplayer-icon-order { + display: inline; + } } &.aplayer-withlrc { @@ -116,6 +119,10 @@ $aplayer-height-lrc: $aplayer-height + $lrc-height - 6; } } + .aplayer-icon-order { + display: none; + } + .aplayer-lrc-content { display: none; } diff --git a/src/js/controller.js b/src/js/controller.js index 539a5cf..ca8ea22 100644 --- a/src/js/controller.js +++ b/src/js/controller.js @@ -6,11 +6,8 @@ class Controller { this.player = player; this.initPlayButton(); - this.initList(); this.initPlayBar(); - if (this.player.isMultiple()) { - this.initOrderButton(); - } + this.initOrderButton(); this.initLoopButton(); this.initMenuButton(); if (!utils.isMobile) { @@ -24,26 +21,6 @@ class Controller { }); } - initList () { - this.player.template.list.addEventListener('click', (e) => { - let target; - if (e.target.tagName.toUpperCase() === 'LI') { - target = e.target; - } - else { - target = e.target.parentElement; - } - const audioIndex = parseInt(target.getElementsByClassName('aplayer-list-index')[0].innerHTML) - 1; - if (audioIndex !== this.player.playIndex) { - this.player.switchAudio(audioIndex); - this.player.play(); - } - else { - this.player.toggle(); - } - }); - } - initPlayBar () { const thumbMove = (e) => { let percentage = ((e.clientX || e.changedTouches[0].clientX) - utils.getElementViewLeft(this.player.template.barWrap)) / this.player.template.barWrap.clientWidth; @@ -156,12 +133,7 @@ class Controller { this.player.template.list.style.height = 33 * this.player.options.audio.length - 1 + 'px'; this.player.template.listOl.style.height = 33 * this.player.options.audio.length - 1 + 'px'; this.player.template.menu.addEventListener('click', () => { - if (!this.player.template.list.classList.contains('aplayer-list-hide')) { - this.player.template.list.classList.add('aplayer-list-hide'); - } - else { - this.player.template.list.classList.remove('aplayer-list-hide'); - } + this.player.list.toggle(); }); } } diff --git a/src/js/list.js b/src/js/list.js new file mode 100644 index 0000000..a99c60f --- /dev/null +++ b/src/js/list.js @@ -0,0 +1,145 @@ +import tplListItem from '../template/list-item.art'; +import utils from './utils'; + +class List { + constructor (player) { + this.player = player; + this.index = 0; + this.audios = this.player.options.audio; + + this.bindEvents(); + } + + bindEvents () { + this.player.template.list.addEventListener('click', (e) => { + let target; + if (e.target.tagName.toUpperCase() === 'LI') { + target = e.target; + } + else { + target = e.target.parentElement; + } + const audioIndex = parseInt(target.getElementsByClassName('aplayer-list-index')[0].innerHTML) - 1; + if (audioIndex !== this.index) { + this.switch(audioIndex); + this.player.play(); + } + else { + this.player.toggle(); + } + }); + } + + show () { + this.player.events.trigger('listshow'); + this.player.template.list.classList.remove('aplayer-list-hide'); + } + + hide () { + this.player.events.trigger('listhide'); + this.player.template.list.classList.add('aplayer-list-hide'); + } + + toggle () { + if (!this.player.template.list.classList.contains('aplayer-list-hide')) { + this.hide(); + } + else { + this.show(); + } + } + + add (audios) { + this.player.events.trigger('listadd', audios); + const wasSingle = !(this.audios.length > 1); + + this.player.template.listOl.innerHTML += tplListItem({ + theme: this.player.options.theme, + audio: audios, + index: this.audios.length + 1 + }); + + this.audios = this.audios.concat(audios); + + if (wasSingle && this.audios.length > 1) { + this.player.container.classList.add('aplayer-withlist'); + } + this.player.template.list.style.height = this.audios.length * 33 - 1 + 'px'; + this.player.template.listOl.style.height = this.audios.length * 33 - 1 + 'px'; + + this.player.randomOrder = utils.randomOrder(this.audios.length); + this.player.template.listCurs = this.player.container.querySelectorAll('.aplayer-list-cur'); + + this.player.template.listCurs[this.audios.length - 1].style.backgroundColor = audios.theme || this.player.options.theme; + } + + remove (index) { + this.player.events.trigger('listremove', index); + if (this.audios[index] && this.audios.length > 1) { + const list = this.player.container.querySelectorAll('.aplayer-list li'); + list[index].remove(); + + this.audios.splice(index, 1); + + if (index === this.index) { + if (this.audios[index + 1]) { + this.switch(index); + } + else { + this.switch(index - 1); + } + } + if (this.index > index) { + this.index--; + } + + for (let i = index; i < list.length; i++) { + list[i].getElementsByClassName('aplayer-list-index')[0].textContent = i; + } + if (this.audios.length === 1) { + this.player.container.classList.remove('aplayer-withlist'); + } + this.player.template.list.style.height = this.audios.length * 33 - 1 + 'px'; + this.player.template.listOl.style.height = this.audios.length * 33 - 1 + 'px'; + + this.player.template.listCurs = this.player.container.querySelectorAll('.aplayer-list-cur'); + } + else { + // TODO + } + } + + switch (index) { + this.player.events.trigger('listswitch', index); + if (typeof index !== 'undefined') { + this.index = index; + } + + const audio = this.audios[this.index]; + + // set html + this.player.template.pic.style.backgroundImage = audio.cover ? `url('${audio.cover}')` : ''; + this.player.theme(this.audios[this.index].theme || this.player.options.theme, this.index); + this.player.template.title.innerHTML = audio.name; + this.player.template.author.innerHTML = audio.artist ? ' - ' + audio.artist : ''; + + const light = this.player.container.getElementsByClassName('aplayer-list-light')[0]; + if (light) { + light.classList.remove('aplayer-list-light'); + } + this.player.container.querySelectorAll('.aplayer-list li')[this.index].classList.add('aplayer-list-light'); + + this.player.template.list.scrollTop = this.index * 33; + + this.player.setAudio(audio); + + this.player.lrc && this.player.lrc.switch(this.index); + + // set duration time + if (this.player.audio.duration !== 1) { // compatibility: Android browsers will output 1 at first + this.player.template.dtime.innerHTML = this.player.audio.duration ? utils.secondToTime(this.player.audio.duration) : '00:00'; + } + } +} + +export default List; \ No newline at end of file diff --git a/src/js/player.js b/src/js/player.js index 361c2c3..d1b344e 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -10,7 +10,7 @@ import Lrc from './lrc'; import Controller from './controller'; import Timer from './timer'; import Events from './events'; -import tplListItem from '../template/list-item.art'; +import List from './list'; const instances = []; @@ -25,7 +25,6 @@ class APlayer { constructor (options) { this.options = handleOption(options); this.container = this.options.container; - this.playIndex = 0; this.paused = true; this.playedPromise = Promise.resolve(); this.mode = 'normal'; @@ -84,13 +83,14 @@ class APlayer { this.bar = new Bar(this.template); this.controller = new Controller(this); this.timer = new Timer(this); + this.list = new List(this); this.initAudio(); if (this.options.order === 'random') { - this.switchAudio(this.randomOrder[0]); + this.list.switch(this.randomOrder[0]); } else { - this.switchAudio(0); + this.list.switch(0); } // autoplay @@ -156,36 +156,36 @@ class APlayer { this.on('ended', () => { if (this.options.loop === 'none') { if (this.options.order === 'list') { - if (this.playIndex < this.options.audio.length - 1) { - this.switchAudio((this.playIndex + 1) % this.options.audio.length); + if (this.list.index < this.list.audios.length - 1) { + this.list.switch((this.list.index + 1) % this.list.audios.length); this.play(); } else { - this.switchAudio((this.playIndex + 1) % this.options.audio.length); + this.list.switch((this.list.index + 1) % this.list.audios.length); this.pause(); } } else if (this.options.order === 'random') { - if (this.randomOrder.indexOf(this.playIndex) < this.randomOrder.length - 1) { - this.switchAudio(this.nextRandomNum()); + if (this.randomOrder.indexOf(this.list.index) < this.randomOrder.length - 1) { + this.list.switch(this.nextRandomNum()); this.play(); } else { - this.switchAudio(this.nextRandomNum()); + this.list.switch(this.nextRandomNum()); this.pause(); } } } else if (this.options.loop === 'one') { - this.switchAudio(this.playIndex); + this.list.switch(this.list.index); this.play(); } else if (this.options.loop === 'all') { if (this.options.order === 'list') { - this.switchAudio((this.playIndex + 1) % this.options.audio.length); + this.list.switch((this.list.index + 1) % this.list.audios.length); } else if (this.options.order === 'random') { - this.switchAudio(this.nextRandomNum()); + this.list.switch(this.nextRandomNum()); } this.play(); } @@ -194,32 +194,7 @@ class APlayer { this.volume(this.user.get('volume'), true); } - switchAudio (index) { - this.events.trigger('switchaudio', index); - if (typeof index !== 'undefined') { - this.playIndex = index; - } - - const audio = this.options.audio[this.playIndex]; - // set html - if (audio.cover) { - this.template.pic.style.backgroundImage = `url('${audio.cover}')`; - } - else { - this.template.pic.style.backgroundImage = ''; - } - this.theme(); - this.template.title.innerHTML = audio.name; - this.template.author.innerHTML = audio.artist ? ' - ' + audio.artist : ''; - const light = this.container.getElementsByClassName('aplayer-list-light')[0]; - if (light) { - light.classList.remove('aplayer-list-light'); - } - this.container.querySelectorAll('.aplayer-list li')[this.playIndex].classList.add('aplayer-list-light'); - - this.template.list.scrollTop = this.playIndex * 33; - - // mse + setAudio (audio) { if (this.hls) { this.hls.destroy(); this.hls = null; @@ -259,25 +234,17 @@ class APlayer { this.audio.src = audio.url; } } - this.seek(0); if (!this.paused) { this.audio.play(); } - - this.lrc && this.lrc.switch(this.playIndex); - - // set duration time - if (this.audio.duration !== 1) { // compatibility: Android browsers will output 1 at first - this.template.dtime.innerHTML = this.audio.duration ? utils.secondToTime(this.audio.duration) : '00:00'; - } } - theme (color = this.options.audio[this.playIndex].theme, index = this.playIndex) { - this.options.audio[index].theme = color; + theme (color = this.list.audios[this.list.index].theme || this.options.theme, index = this.list.index) { + this.list.audios[index].theme = color; this.template.listCurs[index].style.backgroundColor = color; - if (index === this.playIndex) { + if (index === this.list.index) { this.template.pic.style.backgroundColor = color; this.template.played.style.background = color; this.template.thumb.style.background = color; @@ -415,19 +382,12 @@ class APlayer { } } - /** - * get whether multiple audio definitions are loaded - */ - isMultiple () { - return this.options.audio.length > 1; - } - /** * get next random number */ nextRandomNum () { - if (this.isMultiple()) { - const index = this.randomOrder.indexOf(this.playIndex); + if (this.list.audios.length > 1) { + const index = this.randomOrder.indexOf(this.list.index); if (index === this.randomOrder.length - 1) { return this.randomOrder[0]; } @@ -440,67 +400,19 @@ class APlayer { } } - /** - * add audio dynamically - * - * @param {Array} newMusic - */ - addAudio (newMusic) { - this.events.trigger('addaudio', newMusic); - const wasSingle = !this.isMultiple(); - - this.template.listOl.innerHTML += tplListItem({ - theme: this.options.theme, - audio: newMusic, - index: this.options.audio.length + 1 - }); - - this.options.audio = this.options.audio.concat(newMusic); - - if (wasSingle && this.isMultiple()) { - this.container.classList.add('aplayer-withlist'); - } - this.template.list.style.height = this.options.audio.length * 33 - 1 + 'px'; - this.template.listOl.style.height = this.options.audio.length * 33 - 1 + 'px'; - - this.randomOrder = utils.randomOrder(this.options.audio.length); - this.template.listCurs = this.container.querySelectorAll('.aplayer-list-cur'); + // abandoned + switchAudio (index) { + this.list.switch(index); } - /** - * Remove song from playlist - */ + // abandoned + addAudio (audios) { + this.list.add(audios); + } + + // abandoned removeAudio (index) { - this.events.trigger('removeaudio', index); - if (this.options.audio[index] && this.options.audio.length > 1) { - const list = this.container.querySelectorAll('.aplayer-list li'); - - this.options.audio.splice(index, 1); - - if (index === this.playIndex) { - if (this.options.audio[index + 1]) { - this.switchAudio(index); - } - else { - this.switchAudio(index - 1); - } - } - if (this.playIndex > index) { - this.playIndex--; - } - - list[index].remove(); - for (let i = index; i < list.length; i++) { - list[i].getElementsByClassName('aplayer-list-index')[0].textContent = i; - } - if (this.options.audio.length === 1) { - this.container.classList.remove('aplayer-withlist'); - } - this.template.list.style.height = this.options.audio.length * 33 - 1 + 'px'; - this.template.listOl.style.height = this.options.audio.length * 33 - 1 + 'px'; - - this.template.listCurs = this.container.querySelectorAll('.aplayer-list-cur'); - } + this.list.remove(index); } /** diff --git a/src/js/utils.js b/src/js/utils.js index 88d9fbc..ec978f3 100644 --- a/src/js/utils.js +++ b/src/js/utils.js @@ -70,7 +70,7 @@ const utils = { /** * get random order, using Fisher–Yates shuffle */ - randomOrder: (length = this.options.audio.length) => { + randomOrder: (length) => { function shuffle (arr) { for (let i = arr.length - 1; i >= 0; i--) { const randomIndex = Math.floor(Math.random() * (i + 1)); diff --git a/src/template/player.art b/src/template/player.art index b7be18d..5a9a2a3 100644 --- a/src/template/player.art +++ b/src/template/player.art @@ -35,11 +35,9 @@ - {{ if options.audio.length > 1 }} - {{ /if }}