UNPKG

cplayer

Version:

A beautiful and clean WEB Music Player by HTML5.

447 lines 20.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const returntypeof_1 = require("./helper/returntypeof"); const events_1 = require("events"); const defaultPoster = require('../defaultposter.jpg'); const htmlTemplate = require('../cplayer.html'); const playIcon = require('../playicon.svg'); const style = require('!css-loader!postcss-loader!sass-loader!../scss/cplayer.scss'); function kanaFilter(str) { const starttag = '<span class="cp-lyric-text-zoomout">'; const endtag = '</span>'; let res = ''; let startflag = false; for (let i = 0; i < str.length; i++) { let ch = str.charAt(i); let kano = /[ぁ-んァ-ン]/.test(ch); if (kano && !startflag) { res += starttag; startflag = true; } if (!kano && startflag) { res += endtag; startflag = false; } res += ch; } if (startflag) { res += endtag; } return res; } function buildLyric(lyric, sublyric, zoomOutKana = false) { return (zoomOutKana ? kanaFilter(lyric) : lyric) + (sublyric ? `<span class="cp-lyric-text-sub">${sublyric}</span>` : ''); } function secondNumber2TimeStr(secondTime) { const minute = parseInt((secondTime / 60).toString()).toString().padStart(2, '0'); const second = parseInt((secondTime % 60).toString()).toString().padStart(2, '0'); return minute + ':' + second; } const defaultOption = { element: document.body, generateBeforeElement: false, deleteElementAfterGenerate: false, zoomOutKana: false, showPlaylist: false, showPlaylistButton: true, dropDownMenuMode: 'bottom', width: '', size: '12px', style: '', shadowDom: true }; function createStyleElement(style) { const styleElement = document.createElement('style'); styleElement.id = 'cplayer-style'; styleElement.innerHTML = style; return styleElement; } function createShadowElement(targetElement, htmlTemplate, style) { let shadowRoot = targetElement.createShadowRoot(); shadowRoot.innerHTML = htmlTemplate; shadowRoot.appendChild(createStyleElement(style)); return shadowRoot.firstChild; } function createBeforeElement(targetElement, htmlTemplate, style) { let element = document.createElement('div'); element.innerHTML = htmlTemplate; targetElement.parentNode.insertBefore(element, targetElement); if (!document.getElementById('cplayer-style')) { document.body.appendChild(createStyleElement(style)); } return element.firstChild; } function createBeforeShadowElement(targetElement, htmlTemplate, style) { let element = document.createElement('div'); let shadowRoot = element.createShadowRoot(); shadowRoot.innerHTML = htmlTemplate; shadowRoot.appendChild(createStyleElement(style)); targetElement.parentNode.insertBefore(element, targetElement); return shadowRoot.firstChild; } function createElement(targetElement, htmlTemplate, style) { targetElement.innerHTML = htmlTemplate; if (!document.getElementById('cplayer-style')) { document.body.appendChild(createStyleElement(style)); } return targetElement.firstChild; } class cplayerView extends events_1.EventEmitter { constructor(player, options) { super(); this.elementLinks = returntypeof_1.default(this.getElementLinks); this.dropDownMenuShowInfo = true; this.__OldVolume = 1; this.__OldLyric = ''; this.__OldTotalTime = 0; this.handlePlaylistchange = () => { this.updatePlaylist(); }; this.handleClickListButton = () => { this.toggleDropDownMenu(); }; this.handleClickModeButton = () => { this.player.toggleMode(); }; this.handleClickPlayList = (point, event) => { if (this.player.nowplaypoint !== point) { this.player.to(point); this.player.play(); } }; this.handleClickPlayButton = () => { this.player.togglePlayState(); }; this.handleClickVolumeButton = () => { this.toggleVolumeControllerKeepShow(); }; this.handleOpenAudio = (audio) => { if (audio.type !== 'video') { this.setPoster(audio.poster || defaultPoster); } else { this.setPoster('none'); } this.setProgress(0, 0, 0); this.elementLinks.title.innerText = audio.name; this.elementLinks.artist.innerText = audio.artist || ''; this.updateLyric(); this.updatePlaylist(); }; this.handleModeChange = (mode) => { this.setMode(mode); }; this.handleVolumeChange = (volume) => { this.setVolume(volume); }; this.handleTimeUpdate = (playedTime, time) => { this.setProgress(playedTime / time, playedTime, time); this.updateLyric(playedTime); }; this.handleClickPrevButton = () => { this.player.prev(); this.player.play(); }; this.handleClickNextButton = () => { this.player.next(); this.player.play(); }; this.handlePlayStateChange = (paused) => { this.setPlayIcon(paused); }; this.handleMouseVolumeController = (event) => { this.removeVolumeControllerKeepShow(); if (event.buttons === 1 || typeof event.buttons === 'undefined' && event.which === 1) { let volume = Math.max(0, Math.min(1.0, (event.clientX - this.elementLinks.volumeController.getBoundingClientRect().left) / this.elementLinks.volumeController.clientWidth)); this.player.setVolume(volume); this.setVolume(volume); } }; this.handleTouchVolumeController = (event) => { this.removeVolumeControllerKeepShow(); let volume = Math.max(0, Math.min(1.0, (event.targetTouches[0].clientX - this.elementLinks.volumeController.getBoundingClientRect().left) / this.elementLinks.volumeController.clientWidth)); this.player.setVolume(volume); this.setVolume(volume); }; this.handleAudioElementChange = (element) => { if (element instanceof HTMLVideoElement) { this.elementLinks.poster.appendChild(element); } else { this.elementLinks.poster.innerHTML = ''; } }; this.handleMouseProgress = (event) => { if (event.buttons === 1 || typeof event.buttons === 'undefined' && event.which === 1) { let progress = Math.max(0, Math.min(1.0, (event.clientX - this.elementLinks.progress.getBoundingClientRect().left) / this.elementLinks.progress.clientWidth)); this.player.setCurrentTime(progress * 100 + '%'); } }; this.handleTouchProgress = (event) => { let progress = Math.max(0, Math.min(1.0, (event.targetTouches[0].clientX - this.elementLinks.progress.getBoundingClientRect().left) / this.elementLinks.progress.clientWidth)); this.player.setCurrentTime(progress * 100 + '%'); }; this.options = Object.assign(Object.assign({}, defaultOption), options); this.player = player; if (this.options.generateBeforeElement) { if (this.options.element.createShadowRoot && options.shadowDom !== false) { this.rootElement = createBeforeShadowElement(this.options.element, htmlTemplate, style + this.options.style); } else { this.rootElement = createBeforeElement(this.options.element, htmlTemplate, style + this.options.style); } } else { if (this.options.element.createShadowRoot && options.shadowDom !== false) { this.rootElement = createShadowElement(this.options.element, htmlTemplate, style + this.options.style); } else { this.rootElement = createElement(this.options.element, htmlTemplate, style + this.options.style); } } if (options.deleteElementAfterGenerate) { options.element.parentElement.removeChild(options.element); } this.rootElement.style.width = this.options.width; this.rootElement.style.fontSize = this.options.size; this.elementLinks = this.getElementLinks(); this.injectEventListener(); this.setPlayIcon(this.player.paused); this.dropDownMenuShowInfo = !this.options.showPlaylist; if (this.dropDownMenuShowInfo) { this.showInfo(); } else this.showPlaylist(); if (!this.options.showPlaylistButton) this.elementLinks.button.list.style.display = 'none'; else this.elementLinks.button.list.style.display = ''; this.elementLinks.dropDownMenu.classList.add('cp-drop-down-menu-' + this.options.dropDownMenuMode); if (this.options.dark) { this.dark(); } if (this.options.big) { this.big(); } // this.setPoster(this.player.nowplay.poster || defaultPoster); this.setProgress(this.player.currentTime / this.player.duration, this.player.currentTime, this.player.duration); // this.elementLinks.title.innerText = this.player.nowplay.name; // this.elementLinks.artist.innerText = this.player.nowplay.artist || ''; this.updateLyric(); this.updatePlaylist(); } getRootElement() { return this.rootElement; } dark() { this.rootElement.classList.add('cp-dark'); } big() { this.rootElement.classList.add('cp-big'); } getPlayListLinks(rootElement = this.rootElement) { return rootElement.querySelectorAll('.cp-playlist li'); } getElementLinks(rootElement = this.rootElement) { let gebc = className => rootElement.getElementsByClassName(className)[0]; return { icon: { play: gebc('cp-play-icon'), mode: gebc('cp-mode-icon'), }, button: { prev: gebc('cp-prev-button'), play: gebc('cp-play-button'), next: gebc('cp-next-button'), volume: gebc('cp-volume-icon'), list: gebc('cp-list-button'), mode: gebc('cp-mode-button') }, progress: gebc('cp-progress'), progressFill: gebc('cp-progress-fill'), progressButton: gebc('cp-progress-button'), progressDuration: gebc('cp-progress-duration'), progressCurrentTime: gebc('cp-progress-current-time'), poster: gebc('cp-poster'), title: gebc('cp-audio-title'), artist: gebc('cp-audio-artist'), lyric: gebc('cp-lyric-text'), lyricContainer: gebc('cp-lyric'), volumeController: gebc('cp-volume-controller'), volumeFill: gebc('cp-volume-fill'), volumeControllerButton: gebc('cp-volume-controller-button'), volumeControllerContainer: gebc('cp-volume-container'), dropDownMenu: gebc('cp-drop-down-menu'), playlist: gebc('cp-playlist'), playlistItems: this.getPlayListLinks(rootElement) }; } setPlayIcon(paused) { if (paused) { this.elementLinks.icon.play.classList.add('cp-play-icon-paused'); } else { this.elementLinks.icon.play.classList.remove('cp-play-icon-paused'); } } setProgress(point, currentTime, duration) { this.elementLinks.progressFill.style.width = `${point * 100}%`; this.elementLinks.progressButton.style.right = (1 - point) * 100 + '%'; this.elementLinks.progressCurrentTime.innerText = secondNumber2TimeStr(currentTime); this.elementLinks.progressDuration.innerText = secondNumber2TimeStr(duration); } setPoster(src) { this.elementLinks.poster.style.backgroundImage = `url("${src}")`; } setVolume(volume) { if (this.__OldVolume !== volume) { this.elementLinks.volumeFill.style.width = `${volume * 100}%`; this.elementLinks.volumeControllerButton.style.right = (1 - volume) * 100 + '%'; this.__OldVolume = volume; } } setMode(mode) { var modeattr = document.createAttribute('data-mode'); modeattr.value = mode; this.elementLinks.button.mode.attributes.setNamedItem(modeattr); } showInfo() { let dropDownMenu = this.elementLinks.dropDownMenu; dropDownMenu.style.height = ''; dropDownMenu.classList.remove('cp-drop-down-menu-playlist'); dropDownMenu.classList.add('cp-drop-down-menu-info'); this.dropDownMenuShowInfo = true; } showPlaylist() { let dropDownMenu = this.elementLinks.dropDownMenu; dropDownMenu.style.height = this.player.playlist.length * 2.08333 + 'em'; dropDownMenu.classList.remove('cp-drop-down-menu-info'); dropDownMenu.classList.add('cp-drop-down-menu-playlist'); this.dropDownMenuShowInfo = false; } toggleDropDownMenu() { if (this.dropDownMenuShowInfo) { this.showPlaylist(); } else { this.showInfo(); } } setVolumeControllerKeepShow() { this.elementLinks.volumeControllerContainer.classList.add('cp-volume-container-show'); } toggleVolumeControllerKeepShow() { this.elementLinks.volumeControllerContainer.classList.toggle('cp-volume-container-show'); } removeVolumeControllerKeepShow() { this.elementLinks.volumeControllerContainer.classList.remove('cp-volume-container-show'); } setLyric(lyric, time = 0, totalTime = 0) { if (this.__OldLyric !== lyric || this.__OldTotalTime !== totalTime) { this.elementLinks.lyric.innerHTML = lyric; this.elementLinks.lyric.style.transition = ''; this.elementLinks.lyric.style.transform = ''; if (totalTime !== 0) { let lyricWidth = this.elementLinks.lyric.clientWidth; let lyricContainerWidth = this.elementLinks.lyricContainer.clientWidth; if (lyricWidth > lyricContainerWidth) { let duration = totalTime - time; let targetOffset = (lyricWidth - lyricContainerWidth); let timepage = lyricContainerWidth / lyricWidth * duration; let startTime = Math.min(timepage * 0.6, duration); let moveTime = duration - timepage; this.elementLinks.lyric.style.transition = `transform ${moveTime}ms linear ${startTime}ms`; this.elementLinks.lyric.style.transform = `translateX(-${targetOffset}px)`; } } this.__OldLyric = lyric; this.__OldTotalTime = totalTime; } } updatePlaylist() { var lis = this.player.playlist.map((audio, index) => { var element = document.createElement('li'); element.innerHTML = ` ${index === this.player.nowplaypoint ? playIcon : '<span class="cp-play-icon"></span>'} <span>${audio.name}</span><span class='cp-playlist-artist'>${audio.artist ? ' - ' + audio.artist : ''}</span> `; return element; }); this.elementLinks.playlist.innerHTML = ''; lis.forEach((li) => { this.elementLinks.playlist.appendChild(li); }); this.elementLinks.playlistItems = this.getPlayListLinks(); this.injectPlayListEventListener(); if (!this.dropDownMenuShowInfo) { this.elementLinks.dropDownMenu.style.height = this.player.playlist.length * 2.08333 + 'em'; } } injectPlayListEventListener() { Array.prototype.forEach.call(this.elementLinks.playlistItems, ((i, index) => { i.addEventListener('click', (event) => { this.handleClickPlayList(index, event); }); })); } injectEventListener() { this.elementLinks.button.play.addEventListener('click', this.handleClickPlayButton); this.elementLinks.button.prev.addEventListener('click', this.handleClickPrevButton); this.elementLinks.button.next.addEventListener('click', this.handleClickNextButton); this.elementLinks.button.volume.addEventListener('click', this.handleClickVolumeButton); this.elementLinks.button.list.addEventListener('click', this.handleClickListButton); this.elementLinks.button.mode.addEventListener('click', this.handleClickModeButton); this.elementLinks.volumeController.addEventListener('mousemove', this.handleMouseVolumeController); this.elementLinks.volumeController.addEventListener('mousedown', this.handleMouseVolumeController); this.elementLinks.volumeController.addEventListener('touchmove', this.handleTouchVolumeController, { passive: true }); this.elementLinks.progress.addEventListener('mousemove', this.handleMouseProgress); this.elementLinks.progress.addEventListener('mousedown', this.handleMouseProgress); this.elementLinks.progress.addEventListener('touchmove', this.handleTouchProgress, { passive: true }); this.player.addListener('playstatechange', this.handlePlayStateChange); this.player.addListener('timeupdate', this.handleTimeUpdate); this.player.addListener('openaudio', this.handleOpenAudio); this.player.addListener('volumechange', this.handleVolumeChange); this.player.addListener('playmodechange', this.handleModeChange); this.player.addListener('playlistchange', this.handlePlaylistchange); this.player.addListener('audioelementchange', this.handleAudioElementChange); this.injectPlayListEventListener(); } updateLyric(playedTime = 0) { if (!this.player.nowplay) { this.setLyric(null); return; } if (this.player.nowplay.lyric && typeof this.player.nowplay.lyric !== 'string' && this.player.played) { let lyric = this.player.nowplay.lyric.getLyric(playedTime * 1000); let nextLyric = this.player.nowplay.lyric.getNextLyric(playedTime * 1000); if (lyric) { let sublyric; if (this.player.nowplay.sublyric && typeof this.player.nowplay.sublyric !== 'string') { sublyric = this.player.nowplay.sublyric.getLyric(playedTime * 1000); } if (nextLyric) { let duration = nextLyric.time - lyric.time; let currentTime = playedTime * 1000 - lyric.time; this.setLyric(buildLyric(lyric.word, sublyric ? sublyric.word : undefined, this.options.zoomOutKana), currentTime, duration); } else { let duration = this.player.duration - lyric.time; let currentTime = playedTime * 1000 - lyric.time; this.setLyric(buildLyric(lyric.word, sublyric ? sublyric.word : undefined, this.options.zoomOutKana), currentTime, duration); } } else { this.setLyric(buildLyric(this.player.nowplay.name, this.player.nowplay.artist, false), playedTime * 1000, nextLyric.time); } } else { this.setLyric(buildLyric(this.player.nowplay.name, this.player.nowplay.artist, false)); } } destroy() { this.rootElement.parentElement.removeChild(this.rootElement); } } exports.default = cplayerView; //# sourceMappingURL=view.js.map