@@ -14959,21 +14959,254 @@ class FastSearchCard extends HTMLElement {
1495914959
1496014960
1496114961
14962+ // 🔄 VERBESSERTE animateElementIn für allgemeine Nutzung
1496214963 animateElementIn(element, keyframes, options = {}) {
1496314964 if (!element) return;
14964-
14965- // Reset alle Transform- Properties vor Animation
14965+
14966+ // Reset alle Properties
1496614967 element.style.transform = '';
1496714968 element.style.scale = '';
14968- element.style.opacity = '';
14969+ element.style.opacity = '';
14970+ element.style.filter = '';
1496914971
14970- return element.animate(keyframes, {
14971- duration: 400,
14972- easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
14973- fill: 'forwards',
14974- ...options
14972+ // Apple-Style Defaults
14973+ const defaultOptions = {
14974+ duration: 500,
14975+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)', // Apple's spring easing
14976+ fill: 'forwards'
14977+ };
14978+
14979+ return element.animate(keyframes, { ...defaultOptions, ...options });
14980+ }
14981+
14982+
14983+
14984+ // 🎭 STAGGERED ENTRANCE für große Listen
14985+ animateCardsInWaves(cards, waveSize = 4) {
14986+ cards.forEach((card, index) => {
14987+ const waveIndex = Math.floor(index / waveSize);
14988+ const cardInWave = index % waveSize;
14989+
14990+ const delay = (waveIndex * 200) + (cardInWave * 50);
14991+
14992+ setTimeout(() => {
14993+ this.animateCardInHomeKitStyle(card);
14994+ }, delay);
14995+ });
14996+ }
14997+
14998+ // 🌊 SCROLL-TRIGGERED ANIMATIONS (für große Listen)
14999+ setupScrollAnimations() {
15000+ const observer = new IntersectionObserver((entries) => {
15001+ entries.forEach(entry => {
15002+ if (entry.isIntersecting) {
15003+ const card = entry.target;
15004+ if (!card.classList.contains('animated')) {
15005+ this.animateCardInHomeKitStyle(card);
15006+ card.classList.add('animated');
15007+ }
15008+ }
15009+ });
15010+ }, {
15011+ threshold: 0.1,
15012+ rootMargin: '50px'
15013+ });
15014+
15015+ // Observer für alle Cards aktivieren
15016+ const cards = this.shadowRoot.querySelectorAll('.device-card');
15017+ cards.forEach(card => observer.observe(card));
15018+ }
15019+
15020+ // 🎯 ENHANCED HOVER ANIMATIONS
15021+ enhanceHoverAnimations() {
15022+ const cards = this.shadowRoot.querySelectorAll('.device-card');
15023+
15024+ cards.forEach(card => {
15025+ // Mouse Enter - Apple-style lift
15026+ card.addEventListener('mouseenter', () => {
15027+ card.animate([
15028+ { transform: 'translateY(0) scale(1)' },
15029+ { transform: 'translateY(-6px) scale(1.03)' }
15030+ ], {
15031+ duration: 300,
15032+ easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
15033+ fill: 'forwards'
15034+ });
15035+
15036+ // Icon bounce
15037+ const icon = card.querySelector('.device-icon');
15038+ if (icon) {
15039+ icon.animate([
15040+ { transform: 'scale(1)' },
15041+ { transform: 'scale(1.1)' },
15042+ { transform: 'scale(1.05)' }
15043+ ], {
15044+ duration: 200,
15045+ easing: 'ease-out'
15046+ });
15047+ }
15048+ });
15049+
15050+ // Mouse Leave - Smooth return
15051+ card.addEventListener('mouseleave', () => {
15052+ card.animate([
15053+ { transform: 'translateY(-6px) scale(1.03)' },
15054+ { transform: 'translateY(0) scale(1)' }
15055+ ], {
15056+ duration: 250,
15057+ easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
15058+ fill: 'forwards'
15059+ });
15060+
15061+ const icon = card.querySelector('.device-icon');
15062+ if (icon) {
15063+ icon.animate([
15064+ { transform: 'scale(1.05)' },
15065+ { transform: 'scale(1)' }
15066+ ], {
15067+ duration: 200,
15068+ easing: 'ease-out'
15069+ });
15070+ }
15071+ });
15072+
15073+ // Click - Apple-style press
15074+ card.addEventListener('mousedown', () => {
15075+ card.animate([
15076+ { transform: 'translateY(-6px) scale(1.03)' },
15077+ { transform: 'translateY(-2px) scale(0.98)' }
15078+ ], {
15079+ duration: 100,
15080+ easing: 'ease-out',
15081+ fill: 'forwards'
15082+ });
15083+ });
15084+
15085+ card.addEventListener('mouseup', () => {
15086+ card.animate([
15087+ { transform: 'translateY(-2px) scale(0.98)' },
15088+ { transform: 'translateY(-6px) scale(1.03)' }
15089+ ], {
15090+ duration: 150,
15091+ easing: 'ease-out',
15092+ fill: 'forwards'
15093+ });
15094+ });
15095+ });
15096+ }
15097+
15098+ // 🎬 SCENE TRANSITION ANIMATIONS
15099+ animateSceneTransition(oldCards, newCards) {
15100+ // Fade out alte Cards
15101+ const fadeOutPromises = oldCards.map(card => {
15102+ return card.animate([
15103+ { opacity: 1, transform: 'scale(1)' },
15104+ { opacity: 0, transform: 'scale(0.9)' }
15105+ ], {
15106+ duration: 200,
15107+ easing: 'ease-in'
15108+ }).finished;
15109+ });
15110+
15111+ // Nach fade out, neue Cards einblenden
15112+ Promise.all(fadeOutPromises).then(() => {
15113+ newCards.forEach((card, index) => {
15114+ setTimeout(() => {
15115+ this.animateCardInHomeKitStyle(card);
15116+ }, index * 30);
15117+ });
1497515118 });
1497615119 }
15120+
15121+ // 🌟 FAVORITEN TOGGLE ANIMATION
15122+ animateFavoriteToggle(card, isFavorite) {
15123+ const icon = card.querySelector('.device-icon');
15124+
15125+ if (isFavorite) {
15126+ // Favorite hinzugefügt - Gold glow effect
15127+ card.animate([
15128+ { filter: 'brightness(1)' },
15129+ { filter: 'brightness(1.3) hue-rotate(45deg)' },
15130+ { filter: 'brightness(1)' }
15131+ ], {
15132+ duration: 600,
15133+ easing: 'ease-out'
15134+ });
15135+
15136+ // Star burst effect
15137+ this.addStarSparkleEffect(card);
15138+
15139+ } else {
15140+ // Favorite entfernt - subtle fade
15141+ card.animate([
15142+ { filter: 'brightness(1)' },
15143+ { filter: 'brightness(0.8)' },
15144+ { filter: 'brightness(1)' }
15145+ ], {
15146+ duration: 300,
15147+ easing: 'ease-out'
15148+ });
15149+ }
15150+ }
15151+
15152+ // 🎯 INIT FUNCTION - Alle Animationen aktivieren
15153+ initHomeKitAnimations() {
15154+ // Setup enhanced hover animations
15155+ this.enhanceHoverAnimations();
15156+
15157+ // Setup scroll animations für performance
15158+ if (this.filteredItems.length > 20) {
15159+ this.setupScrollAnimations();
15160+ }
15161+
15162+ // Performance monitoring
15163+ this.monitorAnimationPerformance();
15164+ }
15165+
15166+ // 📊 PERFORMANCE MONITORING
15167+ monitorAnimationPerformance() {
15168+ let frameCount = 0;
15169+ let lastTime = performance.now();
15170+
15171+ const measureFPS = () => {
15172+ frameCount++;
15173+ const currentTime = performance.now();
15174+
15175+ if (currentTime - lastTime >= 1000) {
15176+ const fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
15177+
15178+ // Wenn FPS zu niedrig, Animationen reduzieren
15179+ if (fps < 30) {
15180+ this.reduceAnimationComplexity();
15181+ }
15182+
15183+ frameCount = 0;
15184+ lastTime = currentTime;
15185+ }
15186+
15187+ requestAnimationFrame(measureFPS);
15188+ };
15189+
15190+ requestAnimationFrame(measureFPS);
15191+ }
15192+
15193+ // ⚡ PERFORMANCE FALLBACK
15194+ reduceAnimationComplexity() {
15195+ // Einfachere Animationen für schwächere Geräte
15196+ this.animateCardInHomeKitStyle = (card) => {
15197+ return card.animate([
15198+ { opacity: 0, transform: 'translateY(20px)' },
15199+ { opacity: 1, transform: 'translateY(0)' }
15200+ ], {
15201+ duration: 300,
15202+ easing: 'ease-out',
15203+ fill: 'forwards'
15204+ });
15205+ };
15206+ }
15207+
15208+
15209+
1497715210
1497815211 animateElementOut(element, options = {}) {
1497915212 if (!element) return;
0 commit comments