1 2// æ ¼å¼åæ¶é´ 3function formatTime (time) { 4 const interval = time | 0; 5 const minute = interval / 60 | 0; 6 const second = _pad(interval % 60); 7 return minute + ':' + second; 8} 9function hasClass (ele, cls) { 10 if (ele) { 11 cls = cls || ''; 12 if (cls.replace(/\s/g, '').length === 0) return false; 13 return new RegExp(' ' + cls + ' ').test(' ' + ele.className + ' '); 14 } 15}; 16// æ·»å class 17function addClass (ele, cls) { 18 if (!hasClass(ele, cls) && ele) { 19 ele.className = ele.className === '' ? cls : ele.className + ' ' + cls; 20 } 21}; 22// å»é¤class 23function removeClass (ele, cls) { 24 if (hasClass(ele, cls) && ele) { 25 var newClass = ' ' + ele.className.replace(/[\t\r\n]/g, '') + ' '; 26 while (newClass.indexOf(' ' + cls + ' ') >= 0) { 27 newClass = newClass.replace(' ' + cls + ' ', ' '); 28 } 29 ele.className = newClass.replace(/^\s+|\s+$/g, ''); 30 } 31}; 32class AudioPlay { 33 constructor (event) { 34 const { id } = (event.srcElement || event.target).dataset; 35 const audio = document.getElementById(id); 36 const { src, duration } = audio.dataset; 37 this.iframe = document.getElementsByTagName('iframe'); 38 this.audio = audio; 39 this.event = event; 40 this.target = event.target; 41 // è¿åº¦æ¡åç¹å®¹å¨ 42 this.audioProgressBtn = document.getElementById(`${id}-progress-btn`); 43 // è¿åº¦æ¡åç¹ 44 this.touchCircle = this.audioProgressBtn.children[0]; 45 // è¿åº¦æ¡åç¹å®½åº¦ 46 this.touchCircleWidth = this.touchCircle.clientWidth; 47 // å¼å§æ¶é´ 48 this.audioBeginTime = document.getElementById(`${id}-beginTime`); 49 // è¿åº¦æ¡å®¹å¨ 50 this.audioProgressInner = document.getElementById(`${id}-progress-inner`); 51 // è¿åº¦æ¡å®¹å¨å®½åº¦ 52 this.audioProgressWidth = this.audioProgressInner.clientWidth; 53 // è¿åº¦æ¡ 54 this.audioProgress = this.audioProgressInner.children[0]; 55 // è¿åº¦æ¡æ¨¡å 56 this.audioProgressBar = document.getElementById(`${id}-progress`); 57 // ææ¾å°å 58 this.src = src; 59 // ææ¾æ¶é¿ 60 this.duration = duration; 61 this.touch = {}; 62 } 63 play () { 64 if (hasClass(this.target, 'js-play')) { 65 removeClass(this.target, 'js-play'); 66 addClass(this.target, 'js-pause'); 67 this.event.preventDefault(); 68 this.event.stopPropagation(); 69 if (this.audio.src !== this.src) { this.audio.src = this.src; }; 70 this.audio.play(); 71 this.timeupdate(); 72 this.handleTouch(); 73 } else { 74 removeClass(this.target, 'js-pause'); 75 addClass(this.target, 'js-play'); 76 this.event.preventDefault(); 77 this.event.stopPropagation(); 78 this.audio.pause(); 79 } 80 } 81 ended () { 82 this.audio.onended = () => { 83 this.reset(); 84 }; 85 } 86 87 reset () { 88 removeClass(this.target, 'js-pause'); 89 addClass(this.target, 'js-play'); 90 this.audioProgressBtn.style.transform = `translate3d(0, 0, 0)`; 91 this.audioProgress.style.width = 0; 92 } 93 94 timeupdate () { 95 this.audio.ontimeupdate = (e) => { 96 const currentTime = e.target.currentTime; 97 this.audioBeginTime.innerHTML = formatTime(currentTime); 98 const percent = Math.min(1, currentTime / this.duration); 99 const offsetWidth = percent * this.audioProgressWidth; 100 if (!this.touch.initiated) { 101 this.audioProgressBtn.style.transform = `translate3d(${offsetWidth}px, 0, 0)`; 102 this.audioProgress.style.width = `${offsetWidth}px`; 103 } 104 }; 105 } 106 107 pauseOtherAudio () { 108 [].forEach.call(this.iframe, (i) => { 109 i && i.contentWindow.pause(); 110 }); 111 } 112 113 handleTouch () { 114 this.audioProgressBtn.addEventListener('touchstart', this.handleStart.bind(this), { passive: true });
115 this.audioProgressBtn.addEventListener('touchmove', this.handleMove.bind(this), { passive: true }); 116 this.audioProgressBtn.addEventListener('touchend', this.handleEnd.bind(this), { passive: true }); 117 } 118 119 handleStart (e) { 120 this.touch.initiated = true; 121 const touches = e.changedTouches; 122 this.touch.startX = touches[0].pageX; 123 const audioProgressInnerWidth = this.audioProgress.clientWidth; 124 this.touch.left = audioProgressInnerWidth; 125 } 126 127 handleMove (e) { 128 if (!this.touch.initiated) return; 129 const touches = e.changedTouches; 130 const deltaX = touches[0].pageX - this.touch.startX; 131 const offsetWidth = Math.min(Math.max(0, this.touch.left + deltaX), this.audioProgressWidth - this.touchCircleWidth); 132 this.audioProgress.style.width = `${offsetWidth}px`; 133 this.audioProgressBtn.style.transform = `translate3d(${offsetWidth}px, 0, 0)`; 134 } 135 136 handleEnd () { 137 const audioProgressInnerWidth = this.audioProgress.clientWidth; 138 const percent = audioProgressInnerWidth / (this.audioProgressWidth - this.touchCircleWidth); 139 const currentTime = this.duration * percent; 140 this.audio.currentTime = currentTime; 141 this.touch.initiated = false; 142 } 143 144 progressBarClick () { 145 this.audioProgressBar.addEventListener('click', e => { 146 this.touch.initiated = true; 147 const rect = this.audioProgress.getBoundingClientRect(); 148 const offsetWidth = e.pageX - rect.left; 149 const percent = offsetWidth / (this.audioProgressWidth - this.touchCircleWidth); 150 const currentTime = this.duration * percent; 151 this.audio.currentTime = currentTime; 152 this.touch.initiated = false; 153 }, false); 154 } 155}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.