1/** 2 * 鳿ºãã¬ã¤ã¤ã¼ 3 * 以ä¸ã®ã©ã¤ãã©ãªãå¿ è¦ 4 * wavesurfer.js, jquery.js 5 * 6 * @doc https://wavesurfer-js.org/ 7 */ 8class AudioPlayer { 9 constructor() { 10 this.el1 = '#waveform1'; 11 //this.el2 = '#waveform2'; 12 this.player1 = {}; 13 this.trackLoadedAt = 0; // ç´è¿ã«æ²ãèªã¿è¾¼ãã æå»(ms)ãèªã¿è¾¼ã¿ç´å¾ã®ãè¦ãããã®åççµäºãå¤å®ã«ä½¿ç¨ 14 this.initWaveSurfer(); 15 this.initPlayerActions(); 16 } 17 /** 18 * 波形表示ã©ã¤ãã©ãªãèªã¿è¾¼ã 19 * 20 * WebAudioã¨MediaElementã«ã¯å¤ãã®éããããã®ã§ã以ä¸ã®ããã¥ã¡ã³ããèªããã¨ãæ¨å¥¨ 21 * 22 * @see https://github.com/katspaugh/wavesurfer.js/issues/676 23 * @see https://github.com/katspaugh/wavesurfer.js/issues/509 24 */ 25 initWaveSurfer() { 26 const options1 = { 27 container: this.el1, 28 waveColor: "#E93344", // æ³¢å½¢ã®æªåçé¨åã®è² 29 progressColor: "#BA2936", // 波形ã®åçæ¸ã¿ã®é¨åã®è² 30 backgroundColor: "transparent", // 波形ã®èæ¯è² 31 cursorColor: "#FFFFFF", // ã·ã¼ã¯ãã¼(縦æ£)ã®æ è² 32 splitChannels: false, 33 height: 40, // px 34 barWidth: 1, // å¤ã大ããããã¨æ³¢å½¢ãå³å³ã®ããã«ãããã¯ä¸ã«ãªã: âââââ â 35 cursorWidth: 2, // px 36 //backend: 'WebAudio' // 鳿ºãã¡ã¤ã«ã®DLãå®äºããã¾ã§åçãããªã, iOS é³é調æ´ã使ç¨å¯è½ 37 backend: "MediaElement", // 鳿ºãã¡ã¤ã«ã®DLãå¾ ããã«ã¹ããªã¼ãã³ã°åçå¯è½, iOS é³é調æ´ã使ç¨ä¸å¯ 38 }; 39 const wavesurfer1 = WaveSurfer.create(options1); 40 this.player1 = wavesurfer1; 41 } 42 /** 43 * å¶å¾¡ç³»ã®åæå 44 */ 45 initPlayerActions() { 46 this.play(); 47 //this.pause(); 48 this.togglePlay(); 49 //this.stop(); 50 this.toggleMute(); 51 this.adjustVolume(); 52 this.showCurrentTime(); 53 this.showDurationTime(); 54 this.playNextTrack(); 55 this.playPrevTrack(); 56 this.autoPlayNextTrack(); 57 } 58 /** 59 * 波形表示ãé表示ã«ãã 60 */ 61 hideWaveForm() { 62 // $(this.el1).hide(); 63 $(this.el1).css("visibility", "hidden"); 64 } 65 /** 66 * 波形表示ãé表示ã«ãã 67 */ 68 showWaveForm() { 69 // $(this.el1).show(); 70 $(this.el1).css("visibility", "visible"); 71 } 72 /** 73 * æ²ãèªã¿è¾¼ã 74 * backend ã« WebAudio ãæå®ããå ´å 75 * play ã¡ã½ãããå®è¡ãããã¨ã§åãã¦èªã¿è¾¼ã¾ãã 76 * 77 * @see https://github.com/katspaugh/wavesurfer.js/issues/676 78 */ 79 loadTrack(trackPath) { 80 this.trackLoadedAt = performance.now(); // èªã¿è¾¼ã¿æå»ãè¨é²ï¼å³æfinishé£éã®æ¤ç¥ã«ä½¿ç¨ï¼ 81 // load() 㯠Promise ãè¿ããæ²ãé£ç¶ã§åãæ¿ããã¨åã®èªã¿è¾¼ã¿ã䏿ããã 82 // "AbortError: signal is aborted without reason" ãæªå¦çä¾å¤ã¨ãã¦åºãããæ¡ãæ½°ã 83 this.player1.load(trackPath).catch(() => {}); 84 //this.player1.play(); // backend ã WebAudio ã®æãå¿ é ã MediaElement ãªãä¸è¦ 85 } 86 /** 87 * åç(ãã¬ã¤ãªã¹ãã®ãªã³ã¯ãã¯ãªãã¯ã§åç) 88 */ 89 play() { 90 const self = this; 91 //const target = "#btn_play1"; 92 const target = "#tracks a.track_link"; 93 const links1 = $(target); 94 $(target).on('click', function (e) { 95 e.preventDefault(); 96 let trackPath = $(this).attr("href"); 97 let trackIndex = links1.index(this); 98 self.setCurrentTrack(trackIndex); 99 self.showWaveForm(); 100 self.showTrackInfo(this); 101 102 /* 103 self.player1.on("ready", self.player1.play.bind(self.player1)); 104 // é³é調æ´ããã¦ããªãå ´å 105 if (!$("#volume1").hasClass("volume-adjusted")) { 106 self.player1.setVolume(0.4); 107 } 108 */ 109 110 // wavesurfer.js 7.9.4対å¿: readyã¤ãã³ãã®å¦çæ¹æ³ã夿´ 111 const readyHandler = () => { 112 self.player1.setTime(0); // åæ²ã®æ«å°¾ä½ç½®ã®å¼ãç¶ããæã¡ãå¿ ãå é ããåçãã 113 self.player1.play(); 114 // é³é調æ´ããã¦ããªãå ´å 115 if (!$("#volume1").hasClass("volume-adjusted")) { 116 self.player1.setVolume(0.4); 117 } 118 // ã¤ãã³ããªã¹ãã¼ãä¸åº¦ã ãå®è¡ããããã«åé¤ 119 self.player1.un("ready", readyHandler); 120 }; 121 122 // readyã¤ãã³ããªã¹ãã¼ã追å 123 self.player1.on("ready", readyHandler); 124 125 //$('#btn_playpause1').removeClass("pause"); 126 $("#btn_playpause1").addClass("pause"); 127 $(target).removeClass("now-playing"); 128 $(target).find(".track_play").removeClass("pause"); 129 $(this).addClass("now-playing"); 130 $(this).find(".track_play").addClass("pause"); 131 self.changeAlbumInfo(); 132 }); 133 } 134 /** 135 * 䏿忢 136 */ 137 pause() { 138 const self = this; 139 const target = "#btn_pause1"; 140 $(target).on('click', function () { 141 self.player1.pause(); 142 }); 143 } 144 /** 145 * 䏿忢ä¸ãªãåç 146 * åçä¸ãªã䏿忢 147 */ 148 togglePlay() { 149 const self = this; 150 const target = "#btn_playpause1"; 151 $(target).on('click', function () { 152 if ($(".now-playing").length === 0) { // æ²ãä¸åº¦ãåçããã«æ¼ãããå¦ç䏿¢ 153 return false;
154 } 155 self.player1.playPause(); 156 $('#btn_playpause1').toggleClass("pause"); 157 $('.now-playing').find('.track_play').toggleClass('pause'); 158 }); 159 } 160 /** 161 * 忢ãã¦æåã«æ»ã 162 */ 163 stop() { 164 const self = this; 165 const target = "#btn_stop1"; 166 $(target).on('click', function () { 167 self.player1.stop(); 168 }); 169 } 170 /** 171 * æ¶é³ãã°ã« 172 */ 173 toggleMute() { 174 const self = this; 175 const target = "#btn_mute1"; 176 $(target).on('click', function () { 177 self.player1.toggleMute(); 178 }); 179 } 180 /** 181 * ç¾å¨åçä¸ã®æéãè¿ã 182 */ 183 getCurrentTime() { 184 let raw = this.player1.getCurrentTime(); 185 let time = this.formatTime(raw); 186 return time; 187 } 188 /** 189 * ç¾å¨åçä¸ã®æéã表示ãã 190 */ 191 showCurrentTime() { 192 const self = this; 193 const target = '#current_time1'; 194 self.player1.on('audioprocess', function () { 195 let time = self.getCurrentTime(); 196 $(target).text(time); 197 }); 198 } 199 /** 200 * æ²ã®åççµäºæéãè¿ã 201 */ 202 getDurationTime() { 203 let raw = this.player1.getDuration(); 204 let time = this.formatTime(raw); 205 return time; 206 } 207 /** 208 * åççµäºæéã表示ãã 209 */ 210 showDurationTime() { 211 const self = this; 212 let target = "#duration_time1"; 213 self.player1.on('ready', function () { 214 let time = self.getDurationTime(); 215 $(target).text(time); 216 }); 217 } 218 /** 219 * é³éèª¿æ´ 220 */ 221 adjustVolume() { 222 const self = this; 223 const target = "#volume1"; 224 // backend ã MediaElement ã®æã«ä½¿ç¨ãiOSã§é³é調æ´ã使ç¨ã§ããªããããã¹ã©ã¤ããé表示ã«ãã 225 // backend ã WebAudio ã®æã¯ã³ã¡ã³ãã¢ã¦ããããã¨ãiOSã§é³é調æ´ã使ç¨ã§ãããã 226 // ãã®ä»£ãããã¹ããªã¼ãã³ã°åçãã§ããªããããä¸è¦ã鳿ºãèªã¿è¾¼ã¾ãã¦ããªããããªèª¤è§£ãçã 227 if (self.iOS()) { 228 //$(".volume_control_box").css("visibility", "hidden"); 229 //return false; 230 } 231 $(target).on('input', function () { 232 if ($(".now-playing").length === 0) { // æ²ãä¸åº¦ãåçããã«æ¼ãããå¦ç䏿¢ 233 return false; 234 } 235 let newVolume = $(this).val(); 236 self.player1.setVolume(newVolume); 237 $(this).addClass("volume-adjusted"); 238 }); 239 } 240 /** 241 * iOS端æ«ãã©ãããå¤å®ãã 242 */ 243 iOS() { 244 return [ 245 'iPad Simulator', 246 'iPhone Simulator', 247 'iPod Simulator', 248 'iPad', 249 'iPhone', 250 'iPod' 251 ].includes(navigator.platform) 252 // iPad on iOS 13 detection 253 || (navigator.userAgent.includes("Mac") && "ontouchend" in document) 254 } 255 /** 256 * çµéç§ãåç§(m:ss)ã«å¤æãã¦è¿ã 257 */ 258 formatTime(time) { 259 const min = Math.floor((time % 3600) / 60); 260 const sec = ('00' + Math.floor(time % 60)).slice(-2); 261 const formattedTime = [min, sec].join(':'); 262 return formattedTime; 263 } 264 /** 265 * Load a track by index and highlight the corresponding link 266 */ 267 setCurrentTrack(index) { 268 const links1 = $('#tracks a.track_link'); 269 this.current_track_idx = index || 0; 270 //console.log(this.current_track_idx); 271 const trackPath = links1[index].href; 272 this.loadTrack(trackPath); 273 } 274 /** 275 * æ¬¡ã®æ²ãåç 276 * æå¾ã®æ²ãåçä¸ã«æ¬¡ã®æ²ãåçããããæåã®æ²ãåãããåçãç´ã 277 */ 278 playNextTrack() { 279 const self = this; 280 const target = "#btn_next1"; 281 const links1 = $('#tracks a.track_link'); 282 $(target).click(function () { 283 if ($(".now-playing").length === 0) { // æ²ãä¸åº¦ãåçããã«æ¼ãããå¦ç䏿¢ 284 return false;
285 } 286 const currentIndex = self.current_track_idx; 287 let newIndex = (currentIndex + 1) % links1.length; 288 self.setCurrentTrack(newIndex); 289 const elem = $(links1[newIndex]); 290 self.showTrackInfo(elem); 291 //$('#btn_playpause1').removeClass("pause"); 292 $('#btn_playpause1').addClass("pause"); 293 $(links1).removeClass("now-playing"); 294 $(links1).find('.track_play').removeClass('pause'); 295 $(elem).addClass('now-playing'); 296 $(elem).find('.track_play').addClass('pause'); 297 self.changeAlbumInfo(); 298 }); 299 } 300 /** 301 * åã®æ²ãåç 302 * æåã®æ²ãåçä¸ã«åã®æ²ãåçããããæå¾ã®æ²ãåãããåçãç´ã 303 */ 304 playPrevTrack() { 305 const self = this; 306 const target = "#btn_prev1"; 307 const links1 = $('#tracks a.track_link'); 308 $(target).click(function () { 309 if ($(".now-playing").length === 0) { // æ²ãä¸åº¦ãåçããã«æ¼ãããå¦ç䏿¢ 310 return false; 311 } 312 const currentIndex = self.current_track_idx; 313 let newIndex = (currentIndex - 1) % links1.length; 314 newIndex = newIndex >= 0 ? newIndex : links1.length - 1; 315 self.setCurrentTrack(newIndex); 316 const elem = $(links1[newIndex]); 317 self.showTrackInfo(elem); 318 //$('#btn_playpause1').removeClass("pause"); 319 $('#btn_playpause1').addClass("pause"); 320 $(links1).removeClass("now-playing"); 321 $(links1).find('.track_play').removeClass('pause'); 322 $(elem).addClass('now-playing'); 323 $(elem).find('.track_play').addClass('pause'); 324 self.changeAlbumInfo(); 325 }); 326 } 327 /** 328 * æ¥½æ²æ å ±ã表示ãã 329 */ 330 showTrackInfo(elem) { 331 const parent = $(elem).children(".track_box"); 332 $("#track_name1").text($(parent).find(".track_track_name").text()); 333 $("#artist_name1").text($(parent).find(".track_artist_name").text()); 334 } 335 /** 336 * ã¢ã¼ãã¯ã¼ã¯ç»åã夿´ãã 337 */ 338 changeAlbumInfo() { 339 const parent = $("section#library .library_head"); 340 const target = $("#tracks a.track_link.now-playing"); 341 let item = { 342 'track_name': $(target).find(".track_track_name").text(), 343 'artist_name': $(target).find(".track_artist_name").text(), 344 'album_name': $(target).find(".track_img > img").attr("alt"), 345 'album_pic': $(target).find(".track_img > img").attr("src"), 346 }; 347 $(parent).find("figure > img").attr("src", item.album_pic).attr("alt", item.album_name); 348 $(parent).find("dl > dd").text(item.artist_name); 349 } 350 /** 351 * ç¾å¨ã®æ²ã®åçãçµäºããã 352 * èªåã§æ¬¡ã®æ²ãåçãã 353 * æå¾ã®æ²ã®åçãçµäºããããèªååçãçµäºãã 354 */ 355 autoPlayNextTrack() { 356 const self = this; 357 const links1 = $('#tracks a.track_link'); 358 this.player1.on('finish', function () { 359 // Range対å¿ãµã¼ã(206)ã§ã¯æ²åæ¿æã«åæ²ã®æ«å°¾ä½ç½®ãå¼ãç¶ããã 360 // èªã¿è¾¼ã¿ç´å¾ã«å³ finish ãçºç«ãã¦æå¾ã®æ²ã¾ã§é£éã¹ããããã¦ãã¾ãã 361 // å®éã«åçããã¦ããªããè¦ãããã®çµäºãã¯ç¡è¦ããå é ã¸æ»ãã 362 // ï¼å ¨æ²30ç§ãé常åçãªããã®é¾å¤ãå¿ ãè¶ ãããã誤æ¤ç¥ããªãï¼ 363 const MIN_PLAY_MS = 1500; 364 if (performance.now() - self.trackLoadedAt < MIN_PLAY_MS) { 365 self.player1.setTime(0); 366 return false; 367 } 368 const currentIndex = self.current_track_idx; 369 let newIndex = (currentIndex + 1) % links1.length; 370 if (newIndex === 0) { // æå¾ã®æ²ã®åçãçµäºããæ 371 //self.player1.stop(); 372 return false; 373 } 374 self.setCurrentTrack(newIndex); 375 const elem = $(links1[newIndex]); 376 self.showTrackInfo(elem); 377 $(links1).removeClass("now-playing"); 378 $(links1).find('.track_play').removeClass('pause'); 379 $(elem).addClass('now-playing'); 380 $(elem).find('.track_play').addClass('pause'); 381 self.changeAlbumInfo(); 382 }); 383 } 384} 385 386$(function () { 387 var audioPlayer = new AudioPlayer(); 388});
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.