// === 軽量化パッチ Phase 1 === (function() { 'use strict'; // 1. render呼び出しの抑制(デバウンス) let renderScheduled = false; const originalRender = window.render; window.render = function() { if (renderScheduled) return; // 即座に必要な更新(HP、メッセージ)は同期実行 if (window.updateBars) updateBars(); if (window.updateMessage) updateMessage(); // それ以外は次フレームで実行 renderScheduled = true; requestAnimationFrame(() => { renderScheduled = false; if (originalRender) originalRender.call(this); }); }; // 2. アニメーション要素の定期削除 setInterval(() => { // 2秒以上経過した要素を削除 const now = Date.now(); document.querySelectorAll('.damage-num, .cast-chip, .screen-flash, .chip-ring').forEach(el => { if (!el.dataset.created) { el.dataset.created = now; } else if (now - parseInt(el.dataset.created) > 2000) { el.remove(); } }); // 画面外の要素を削除 document.querySelectorAll('.floating-text').forEach(el => { const rect = el.getBoundingClientRect(); if (rect.bottom < 0 || rect.top > window.innerHeight) { el.remove(); } }); }, 3000); // 3. 手札更新の最適化(innerHTML使用を削減) const originalUpdateHand = window.updateHand; if (originalUpdateHand) { let lastHandCount = 0; window.updateHand = function() { // 手札数が変わっていない場合は選択状態の更新のみ if (state.hand.length === lastHandCount && state.mode === 'selecting') { const cards = document.querySelectorAll('#hand .card'); cards.forEach(card => { const uid = parseInt(card.dataset.uid); if (!isNaN(uid)) { const isSelected = state.selected.includes(uid); card.classList.toggle('selected', isSelected); } }); return; } lastHandCount = state.hand.length; originalUpdateHand.call(this); }; } console.log('[Performance Patch Phase 1] Applied'); })(); // === 軽量化パッチ Phase 2 === // Phase 1が安定してから適用 (function() { 'use strict'; // 1. タブごとのレンダリング制御 const tabRenderControl = { deck: { lastRound: -1, needsUpdate: true }, cards: { lastUpdate: 0, interval: 30000 }, // 30秒ごと badges: { lastUpdate: 0, interval: 30000 } }; const originalUpdateDeck = window.updateDeck; if (originalUpdateDeck) { window.updateDeck = function() { // ラウンドが変わった時のみ更新 if (tabRenderControl.deck.lastRound !== state.round) { tabRenderControl.deck.lastRound = state.round; originalUpdateDeck.call(this); } }; } const originalUpdateLibrary = window.updateLibrary; if (originalUpdateLibrary) { window.updateLibrary = function() { const now = Date.now(); // 表示されているタブのみ更新 const activeTab = document.querySelector('.tab-button.active'); if (!activeTab) return; const tabName = activeTab.dataset.tab; const control = tabRenderControl[tabName]; if (control && now - control.lastUpdate > control.interval) { control.lastUpdate = now; originalUpdateLibrary.call(this); } }; } // 2. CSSアニメーションの最適化 const style = document.createElement('style'); style.textContent = ` /* GPU acceleration */ .card, .hpfill, .feverfill { will-change: auto; transform: translateZ(0); } /* Reduce reflows */ .hand { contain: layout; min-height: 100px; } .stats-bar { contain: layout; } /* Optimize animations */ .card-enter { animation-fill-mode: backwards; } `; document.head.appendChild(style); console.log('[Performance Patch Phase 2] Applied'); })();