1/** 2 * ã³ã¤ã³ã¬ã¤ã³ã¢ãã¡ã¼ã·ã§ã³å ±éã¢ã¸ã¥ã¼ã« 3 * 4 * ä½¿ãæ¹: 5 * var anim = CoinRainAnimation.start(canvasElement, options); 6 * anim.stop(); 7 * 8 * options: 9 * mode: 'fullscreen' | 'section' 10 * - fullscreen: canvas ã window å ¨ä½ã«æç»ï¼ãã°ã¤ã³Popupçï¼ 11 * - section: canvas ã親è¦ç´ ã®ç¯å²ã«æç»ï¼æ°è¦ç»é²ãããã¯çï¼ 12 * sectionEl: mode='section' æã®è¦ªè¦ç´ ï¼IntersectionObserver / ResizeObserver å¯¾è±¡ï¼ 13 * coins: true (ããã©ã«ã) / false - false ã®å ´åã¯ã³ã¤ã³éä¸ãç¡å¹åã sparkle ã®ã¿è¡¨ç¤º 14 */ 15var CoinRainAnimation = (function() { 16 'use strict'; 17 18 var COLS = ['#FFD700', '#FFA500', '#FFE44D', '#ffffff', '#FFF3B0', '#FFCC00']; 19 20 function start(canvas, options) { 21 if (!canvas) return { stop: function(){} }; 22 23 options = options || {}; 24 var mode = options.mode || 'fullscreen'; 25 var sectionEl = options.sectionEl || null; 26 var spawnCoins = options.coins !== false; 27 28 var cx = canvas.getContext('2d'); 29 var pts = []; 30 var animId = null; 31 var stopped = false; 32 var resizeObserver = null; 33 34 // Canvas ãµã¤ãºè¨å® 35 function resize() { 36 if (mode === 'section' && sectionEl) { 37 canvas.width = sectionEl.offsetWidth; 38 canvas.height = sectionEl.offsetHeight; 39 } else { 40 canvas.width = window.innerWidth; 41 canvas.height = window.innerHeight; 42 } 43 } 44 resize(); 45 46 if (mode === 'section' && sectionEl && typeof ResizeObserver !== 'undefined') { 47 resizeObserver = new ResizeObserver(function() { resize(); }); 48 resizeObserver.observe(sectionEl); 49 } 50 51 // ç»é¢å å¤å®ï¼section ã¢ã¼ãï¼ãIntersectionObserver ãç»é¢å¤ã¨éç¥ãã¦ããé㯠rAF èªä½ãæ¢ããã 52 // é対å¿ç°å¢ã¯å¸¸ã«ç»é¢å æ±ãï¼å¾æ¥ã©ãã rAF ãåããä¸ã® rect å¤å®ã§æç»ã ãé£ã°ãï¼ 53 var inView = true; 54 var intersectionObserver = null; 55 56 // ãã¼ãã£ã¯ã«çæï¼vTop / vBottom ã¯åããã¬ã¼ã ã§ 1 åã ãè¨ç®ããå¤ãåãåãï¼ 57 function mkSparkle(vBottom) { 58 var spawnY = (mode === 'section') 59 ? vBottom + Math.random() * 20 60 : canvas.height + Math.random() * 20; 61 return { 62 type: 's', 63 x: Math.random() * canvas.width, 64 y: spawnY, 65 r: Math.random() * 2 + 0.8, 66 col: COLS[Math.floor(Math.random() * COLS.length)], 67 vx: (Math.random() - 0.5) * 0.6, 68 vy: -(Math.random() * 1.2 + 0.4), 69 life: 0 70 }; 71 } 72 73 function mkCoin(vTop) { 74 var spawnY = (mode === 'section') 75 ? vTop - 14 76 : -14; 77 return { 78 type: 'c', 79 x: Math.random() * canvas.width, 80 y: spawnY, 81 r: 5 + Math.random() * 4, 82 vy: Math.random() * 1.69 + 0.78, 83 vx: (Math.random() - 0.5) * 0.4, 84 rot: Math.random() * Math.PI * 2, 85 rs: (Math.random() - 0.5) * 0.07, 86 life: 0 87 }; 88 } 89 90 function star(x, y, ir, or, n) { 91 cx.beginPath(); 92 for (var i = 0; i < n * 2; i++) { 93 var a = i * Math.PI / n - Math.PI / 2; 94 var r = i % 2 ? ir : or; 95 if (i === 0) cx.moveTo(x + r * Math.cos(a), y + r * Math.sin(a)); 96 else cx.lineTo(x + r * Math.cos(a), y + r * Math.sin(a)); 97 } 98 cx.closePath(); 99 } 100 101 function canRun() { 102 return !stopped && inView && document.hidden !== true; 103 } 104 105 // 次ã®ãã¬ã¼ã ãäºç´ãããåªçï¼æ¢ã«äºç´æ¸ã¿ãªãä½ãããªã = rAF ã¯å¸¸ã« 1 æ¬ï¼ 106 function scheduleNext() { 107 if (animId !== null || !canRun()) return; 108 animId = requestAnimationFrame(loop); 109 } 110 111 function cancelNext() { 112 if (animId === null) return; 113 cancelAnimationFrame(animId); 114 animId = null; 115 } 116 117 // æç»ã«ã¼ã 118 function loop() { 119 animId = null; 120 if (stopped) return; 121 122 // ãã¥ã¼ãã¼ãç¯å²ï¼section ã¢ã¼ãç¨ï¼ãgetBoundingClientRect 㯠1 ãã¬ã¼ã 1 åã ã 123 var vTop = 0; 124 var vBottom = canvas.height; 125 if (mode === 'section' && sectionEl) { 126 var rect = sectionEl.getBoundingClientRect(); 127 // section ã¢ã¼ã: ç»é¢å¤ãªãæç»ã¹ãããï¼IO ã®ä½ç½ 100px ã®ç¯å²ã§ã¯ããã§æ¢ã¾ãï¼ 128 if (rect.bottom < 0 || rect.top > window.innerHeight) { 129 scheduleNext(); 130 return; 131 } 132 vTop = Math.max(-rect.top, 0); 133 vBottom = Math.min(window.innerHeight - rect.top, canvas.height); 134 } 135 136 if (mode === 'section') { 137 cx.clearRect(0, vTop, canvas.width, vBottom - vTop); 138 } else { 139 cx.clearRect(0, 0, canvas.width, canvas.height); 140 } 141 142 if (pts.length < 50 && Math.random() < 0.25) pts.push(mkSparkle(vBottom)); 143 if (spawnCoins && pts.length < 50 && Math.random() < 0.08) pts.push(mkCoin(vTop)); 144 145 pts = pts.filter(function(p) { 146 p.life++; 147 if (p.type === 's') { 148 p.x += p.vx; p.y += p.vy; 149 var boundaryTop = (mode === 'section') ? vTop
149- 20 : -20; 150 if (p.y < boundaryTop) return false; 151 cx.save(); 152 cx.globalAlpha = 0.85; 153 cx.fillStyle = p.col; 154 star(p.x, p.y, p.r * 0.4, p.r, 4); 155 cx.fill(); 156 cx.restore(); 157 } else { 158 p.x += p.vx; p.y += p.vy; p.rot += p.rs; 159 if (p.y > vBottom + 20) return false; 160 var fade = Math.min(1, p.life / 8) * 0.85; 161 var rx = p.r * Math.abs(Math.cos(p.rot * 2.1)); 162 cx.save(); 163 cx.globalAlpha = fade; 164 cx.translate(p.x, p.y); 165 cx.rotate(p.rot); 166 cx.fillStyle = '#FFD700'; 167 cx.beginPath(); 168 cx.ellipse(0, 0, Math.max(rx, 0.5), p.r, 0, 0, Math.PI * 2); 169 cx.fill(); 170 cx.restore(); 171 } 172 return true; 173 }); 174 175 scheduleNext(); 176 } 177 178 // é表示ã¿ãã§ã¯æ¢ããè¡¨ç¤ºã«æ»ã£ããï¼ç»é¢å ãªãï¼åéãã 179 function onVisibilityChange() { 180 if (document.hidden === true) { 181 cancelNext(); 182 } else { 183 scheduleNext(); 184 } 185 } 186 function onPageShow(e) { 187 if (e && e.persisted) scheduleNext(); 188 } 189 document.addEventListener('visibilitychange', onVisibilityChange); 190 window.addEventListener('pageshow', onPageShow); 191 192 if (mode === 'section' && sectionEl && typeof IntersectionObserver === 'function') { 193 try { 194 intersectionObserver = new IntersectionObserver(function(entries) { 195 inView = entries[entries.length - 1].isIntersecting; 196 if (inView) { 197 scheduleNext(); 198 } else { 199 cancelNext(); 200 } 201 }, { rootMargin: '100px', threshold: 0 }); 202 intersectionObserver.observe(sectionEl); 203 } catch (e) { 204 intersectionObserver = null; 205 inView = true; 206 } 207 } 208 209 canvas.style.display = 'block'; 210 loop(); 211 212 // 忢颿°ãè¿ã 213 return { 214 stop: function() { 215 stopped = true; 216 cancelNext(); 217 if (resizeObserver) { 218 resizeObserver.disconnect(); 219 resizeObserver = null; 220 } 221 if (intersectionObserver) { 222 intersectionObserver.disconnect(); 223 intersectionObserver = null; 224 } 225 document.removeEventListener('visibilitychange', onVisibilityChange); 226 window.removeEventListener('pageshow', onPageShow); 227 pts = []; 228 } 229 }; 230 } 231 232 return { start: start }; 233})();
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.