1export class YoutubePlayer { 2 elementId; 3 videoId; 4 static iframeApiReadyPromise = null; 5 static apiReadyResolvers = []; 6 player = null; 7 constructor(elementId, videoId) { 8 this.elementId = elementId; 9 this.videoId = videoId; 10 } 11 /** iframe_APIèªã¿è¾¼ã¿ */ 12 static loadAPI() { 13 if (YoutubePlayer.iframeApiReadyPromise) { 14 return YoutubePlayer.iframeApiReadyPromise; 15 } 16 YoutubePlayer.iframeApiReadyPromise = new Promise((resolve) => { 17 YoutubePlayer.apiReadyResolvers.push(resolve); 18 const win = window; 19 // ãã§ã« API ãã¼ãæ¸ã¿ãªãå³ resolve 20 if (win.YT?.Player) { 21 resolve(); 22 return; 23 } 24 // ãã§ã« script ã¿ã°ããããç¢ºèª 25 const existing = document.querySelector('script[src="https://www.youtube.com/iframe_api"]'); 26 // script ãã¾ã ãªã â æ¿å ¥ 27 if (!existing) { 28 const tag = document.createElement('script'); 29 tag.src = 'https://www.youtube.com/iframe_api'; 30 document.head.appendChild(tag); 31 } 32 // YouTube API ã ready ã«ãªã£ãæã«å ¨ callbacks ãå®è¡ 33 window.onYouTubeIframeAPIReady = () => { 34 YoutubePlayer.apiReadyResolvers.forEach((cb) => { 35 void cb(); 36 }); 37 YoutubePlayer.apiReadyResolvers = []; 38 }; 39 }); 40 return YoutubePlayer.iframeApiReadyPromise; 41 } 42 /** ãã¬ã¤ã¤ã¼çæ */ 43 async init() { 44 const container = document.getElementById(this.elementId); 45 if (!container) { 46 throw new Error(`YouTube target element #${this.elementId} was not found.`); 47 } 48 // API ãã¼ã 49 await YoutubePlayer.loadAPI(); 50 // ãã¬ã¤ã¤ã¼çæ 51 await this.createPlayer(); 52 } 53 /** ãã¬ã¤ã¤ã¼çæå¦ç */ 54 createPlayer() { 55 return new Promise((resolve, reject) => { 56 try { 57 this.player = new YT.Player(this.elementId, { 58 videoId: this.videoId, 59 events: { 60 onReady: () => resolve(), 61 }, 62 }); 63 } 64 catch (err) { 65 reject(err); 66 } 67 }); 68 } 69 /** ã³ã³ããã¼ã«ã¡ã½ãã */ 70 play() { 71 this.player?.playVideo(); 72 } 73 pause() { 74 this.player?.pauseVideo(); 75 } 76 stop() { 77 this.player?.stopVideo(); 78 } 79 /** æå®ç§ã¸ã·ã¼ã¯ */ 80 seekTo(seconds, allowSeekAhead = true) { 81 this.player?.seekTo(seconds, allowSeekAhead); 82 } 83 destroy() { 84 this.player?.destroy(); 85 this.player = null; 86 } 87} 88export default YoutubePlayer;
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.