@@ -5067,19 +5067,10 @@ class FastSearchCard extends HTMLElement {
50675067 }
50685068 }
50695069
5070- const categoryButtons = this.shadowRoot.querySelector('.category-buttons');
50715070 this.isMenuView = true;
5072- categoryButtons.classList.add('visible');
50735071
5074- // ALTE ANIMATION TEMPORÄR
5075- categoryButtons.animate([
5076- { opacity: 0, transform: 'translateX(20px) scale(0.9)' },
5077- { opacity: 1, transform: 'translateX(0) scale(1)' }
5078- ], {
5079- duration: 400,
5080- easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
5081- fill: 'forwards'
5082- });
5072+ // 🌊 NEUE SPOTLIGHT ANIMATION statt alter Animation
5073+ this.startSpotlightAnimation();
50835074 }
50845075
50855076 hideCategoryButtons() {
@@ -5133,9 +5124,169 @@ class FastSearchCard extends HTMLElement {
51335124 this.hideCategoryButtons();
51345125 }
51355126
5136- // 🌊 LIQUID ANIMATION METHODEN
5127+
5128+
5129+ // 🌊 ECHTE SPOTLIGHT ANIMATION METHODEN
5130+
5131+ startSpotlightAnimation() {
5132+ const searchPanel = this.shadowRoot.querySelector('.search-panel');
5133+ const liquidExtension = this.shadowRoot.querySelector('#liquidExtension');
5134+ const mainDroplet = this.shadowRoot.querySelector('#mainDroplet');
5135+
5136+ // 1. Suchleiste für Morphing vorbereiten
5137+ searchPanel.classList.add('morphing');
5138+
5139+ // 2. Animationssequenz starten
5140+ this.animateSearchMorphing(liquidExtension)
5141+ .then(() => this.animateDropletSeparation(liquidExtension, mainDroplet))
5142+ .then(() => this.animateDropletMigration(mainDroplet))
5143+ .then(() => this.animateDropletDivision())
5144+ .then(() => this.finalizeSpotlightAnimation());
5145+ }
5146+
5147+ animateSearchMorphing(liquidExtension) {
5148+ return new Promise((resolve) => {
5149+ // Liquid Extension aus der Suchleiste "wachsen" lassen
5150+ liquidExtension.style.display = 'block';
5151+
5152+ liquidExtension.animate([
5153+ { width: '0px', opacity: 0 },
5154+ { width: '100px', opacity: 1 }
5155+ ], {
5156+ duration: 400,
5157+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
5158+ fill: 'forwards'
5159+ }).finished.then(() => {
5160+ setTimeout(resolve, 100);
5161+ });
5162+ });
5163+ }
5164+
5165+ animateDropletSeparation(liquidExtension, mainDroplet) {
5166+ return new Promise((resolve) => {
5167+ // Haupttropfen vom Extension "abtrennen"
5168+ const rect = liquidExtension.getBoundingClientRect();
5169+
5170+ mainDroplet.style.width = '72px';
5171+ mainDroplet.style.height = '72px';
5172+ mainDroplet.style.left = '100px';
5173+ mainDroplet.style.top = '0px';
5174+ mainDroplet.style.display = 'block';
5175+
5176+ // Gleichzeitig: Extension schrumpft, Droplet erscheint
5177+ const extensionAnim = liquidExtension.animate([
5178+ { width: '100px', opacity: 1 },
5179+ { width: '0px', opacity: 0 }
5180+ ], {
5181+ duration: 300,
5182+ easing: 'ease-in',
5183+ fill: 'forwards'
5184+ });
5185+
5186+ const dropletAnim = mainDroplet.animate([
5187+ { opacity: 0, transform: 'scale(0)' },
5188+ { opacity: 1, transform: 'scale(1)' }
5189+ ], {
5190+ duration: 300,
5191+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
5192+ fill: 'forwards'
5193+ });
5194+
5195+ Promise.all([extensionAnim.finished, dropletAnim.finished]).then(() => {
5196+ setTimeout(resolve, 100);
5197+ });
5198+ });
5199+ }
5200+
5201+ animateDropletMigration(mainDroplet) {
5202+ return new Promise((resolve) => {
5203+ // Haupttropfen nach rechts bewegen
5204+ mainDroplet.animate([
5205+ { transform: 'scale(1) translateX(0px)' },
5206+ { transform: 'scale(1) translateX(150px)' }
5207+ ], {
5208+ duration: 500,
5209+ easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
5210+ fill: 'forwards'
5211+ }).finished.then(() => {
5212+ setTimeout(resolve, 150);
5213+ });
5214+ });
5215+ }
51375216
5217+ animateDropletDivision() {
5218+ return new Promise((resolve) => {
5219+ const droplets = [
5220+ this.shadowRoot.querySelector('#droplet1'),
5221+ this.shadowRoot.querySelector('#droplet2'),
5222+ this.shadowRoot.querySelector('#droplet3'),
5223+ this.shadowRoot.querySelector('#droplet4')
5224+ ];
5225+
5226+ // Finale Positionen für alle 5 Buttons (mainDroplet + 4 weitere)
5227+ const positions = [
5228+ { x: 150, y: 0 }, // mainDroplet (schon da)
5229+ { x: 234, y: 0 }, // droplet1
5230+ { x: 318, y: 0 }, // droplet2
5231+ { x: 402, y: 0 }, // droplet3
5232+ { x: 486, y: 0 } // droplet4
5233+ ];
5234+
5235+ // Alle 4 zusätzliche Droplets animieren
5236+ const animations = droplets.map((droplet, index) => {
5237+ droplet.style.width = '72px';
5238+ droplet.style.height = '72px';
5239+ droplet.style.left = '150px'; // Starten alle am mainDroplet
5240+ droplet.style.top = '0px';
5241+ droplet.style.display = 'block';
5242+
5243+ return droplet.animate([
5244+ {
5245+ opacity: 0,
5246+ transform: 'scale(0) translateX(0px)'
5247+ },
5248+ {
5249+ opacity: 1,
5250+ transform: `scale(1) translateX(${positions[index + 1].x - 150}px)`
5251+ }
5252+ ], {
5253+ duration: 400,
5254+ delay: index * 100,
5255+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
5256+ fill: 'forwards'
5257+ });
5258+ });
5259+
5260+ Promise.all(animations.map(anim => anim.finished)).then(() => {
5261+ setTimeout(resolve, 200);
5262+ });
5263+ });
5264+ }
51385265
5266+ finalizeSpotlightAnimation() {
5267+ const searchPanel = this.shadowRoot.querySelector('.search-panel');
5268+ const categoryButtons = this.shadowRoot.querySelector('.category-buttons');
5269+
5270+ // Alle Droplets verstecken
5271+ const allDroplets = this.shadowRoot.querySelectorAll('.liquid-droplet');
5272+ allDroplets.forEach(droplet => {
5273+ droplet.style.display = 'none';
5274+ });
5275+
5276+ // Suchleiste zurücksetzen
5277+ searchPanel.classList.remove('morphing');
5278+
5279+ // Category-Buttons erscheinen lassen
5280+ categoryButtons.classList.add('visible');
5281+ categoryButtons.animate([
5282+ { opacity: 0, transform: 'translateX(20px) scale(0.9)' },
5283+ { opacity: 1, transform: 'translateX(0) scale(1)' }
5284+ ], {
5285+ duration: 300,
5286+ easing: 'cubic-bezier(0.16, 1, 0.3, 1)',
5287+ fill: 'forwards'
5288+ });
5289+ }
51395290
51405291
51415292
0 commit comments