/** * AI Creative Studio - スクロールアニメーション * Intersection Observer API使用(高パフォーマンス) */ (function() { 'use strict'; /** * アニメーション対象クラスの配列 */ const animationClasses = [ 'is-style-aics-fade-in', 'is-style-aics-fade-up', 'is-style-aics-fade-down', 'is-style-aics-slide-left', 'is-style-aics-slide-right', 'is-style-aics-zoom-in', 'is-style-aics-rotate-in', 'is-style-aics-bounce-in' ]; /** * アニメーション対象要素を検出・初期化 */ function aicsInitAnimationElements() { const elements = []; animationClasses.forEach(function(className) { const found = document.querySelectorAll('.' + className); found.forEach(function(element, index) { if (!element.classList.contains('aics-animation-ready')) { // 初期状態として非表示クラスを追加 element.classList.add('aics-animation-pending'); element.classList.add('aics-animation-ready'); // 同じページ内での遅延時間設定(100msずつ) element.dataset.animationDelay = index * 100; elements.push(element); } }); }); return elements; } /** * Intersection Observer のコールバック */ function aicsHandleIntersection(entries, observer) { entries.forEach(function(entry) { if (entry.isIntersecting) { const element = entry.target; const delay = parseInt(element.dataset.animationDelay) || 0; // 遅延実行でアニメーション開始 setTimeout(function() { element.classList.remove('aics-animation-pending'); element.classList.add('aics-animation-active'); }, delay); // 一度実行したら監視を停止(パフォーマンス最適化) observer.unobserve(element); } }); } /** * スクロールアニメーションの初期化 */ function aicsInitScrollAnimations() { // ユーザーが動きを減らす設定の場合は無効化 if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) { // 即座に全要素を表示状態にする const elements = aicsInitAnimationElements(); elements.forEach(function(element) { element.classList.remove('aics-animation-pending'); element.classList.add('aics-animation-active'); }); return; } // Intersection Observer API のサポート確認 if (!('IntersectionObserver' in window)) { console.warn('Intersection Observer not supported. Showing all animations immediately.'); const elements = aicsInitAnimationElements(); elements.forEach(function(element) { element.classList.remove('aics-animation-pending'); element.classList.add('aics-animation-active'); }); return; } // Observer の設定 const observerOptions = { root: null, // viewport rootMargin: '0px 0px -50px 0px', // 下部50px手前で発火 threshold: 0.1 // 10%表示されたら発火 }; // Observer の作成 const observer = new IntersectionObserver(aicsHandleIntersection, observerOptions); // アニメーション対象要素を取得・監視開始 const elements = aicsInitAnimationElements(); elements.forEach(function(element) { observer.observe(element); }); console.log('AICS Scroll Animations initialized:', elements.length, 'elements'); } /** * DOM読み込み完了後に初期化 */ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', aicsInitScrollAnimations); } else { aicsInitScrollAnimations(); } })();