Hero: Zutaten als Fontäne von Hand komponiert statt zufällig gestreut
- Burger wurde von unten getroffen: Salat, Zwiebel, Tomate und Sesam schießen nach oben und fächern zur Seite auf, Bacon liegt waagerecht (sah senkrecht wie Chili aus), keine halb verdeckten unscharfen Teile mehr - Größere Teile mit klarer Rangfolge, Burger, Schriftzeile, Sticker, Hahn und Text bleiben frei - Intro: Teile schießen aus der Burger-Mitte hoch, über das Ziel hinaus und setzen sich; Scroll setzt die Bewegung nach oben fort und blendet früher aus - Zutaten drehen und wachsen um ihre eigene Mitte (transform-origin), Burger wandert beim Scrollen wieder nach oben statt nach unten - Ausgewählt aus vier Entwürfen (Fontäne, Schlag, Kampagne, Schockwelle) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
002dfa21f1
commit
706854a9a7
2 files changed
+53
-16
No files matched your search
@@ -1095,12 +1095,14 @@ body.nav-visible .cat-nav.is-stuck ul { top: var(--nav-h); }
|
||||
|
||||
/* ============ Fliegende Zutaten ============ */
|
||||
.blast__bits { position: absolute; inset: 0; pointer-events: none; }
|
||||
.bit { position: absolute; z-index: 3; }
|
||||
.bit { position: absolute; z-index: 3; transform-origin: 0 0; } /* Mittelpunkt der Zutat liegt auf left/top: so drehen und wachsen sie um sich selbst */
|
||||
.bit__c { display: block; translate: -50% -50%; }
|
||||
.bit__in, .bit__fl { display: block; }
|
||||
.bit img { display: block; width: 100%; height: auto; filter: drop-shadow(0 12px 10px rgba(40, 0, 0, .35)); }
|
||||
.bit--b { z-index: 1; }
|
||||
.bit--b img { filter: blur(1.2px) brightness(.88) drop-shadow(0 8px 8px rgba(40, 0, 0, .3)); }
|
||||
.bit--n { z-index: 5; }
|
||||
.bit--n img { filter: blur(4px) drop-shadow(0 24px 22px rgba(40, 0, 0, .35)); }
|
||||
.hero__burger .blast__bits, .visit__deco .blast__bits, .wings__hero .blast__bits { z-index: auto; }
|
||||
.champ__food .bit--f { z-index: 3; }
|
||||
@media (max-width: 820px) { .bit--b img { filter: brightness(.9) drop-shadow(0 6px 6px rgba(40, 0, 0, .3)); } }
|
||||
|
||||
+50
-15
@@ -195,7 +195,7 @@
|
||||
|
||||
/* ---------- Zutaten rund ums Essen (Explosion beim Scrollen) ----------
|
||||
Jede Zutat: [Datei, x %, y % (relativ zur Essens-Box), Größe % der Box, Drehung, Ebene, auch mobil, gespiegelt]
|
||||
Ebenen: b = hinter dem Essen (leicht unscharf), f = davor */
|
||||
Ebenen: b = hinter dem Essen (leicht unscharf), f = davor, n = ganz nah an der Kamera (groß, unscharf) */
|
||||
var BITS = 'assets/img/bits/';
|
||||
/* Natürliche Streuung statt fester Positionen (fester Seed, damit es bei jedem Laden gleich aussieht).
|
||||
- food: Umriss des Essens im Bild [Mitte x, Mitte y, Halbbreite, Halbhöhe] in % der Box (abgerundetes Rechteck)
|
||||
@@ -204,11 +204,25 @@
|
||||
- left/right/top/bottom: erlaubter Bereich (% der Box), z. B. damit nichts über Text oder aus der Karte ragt
|
||||
items: [Datei, Grundgröße in % der Box-Breite, auch mobil] */
|
||||
var SCATTER = {
|
||||
burger: { seed: 4, food: [39, 49, 38, 47], hw: .72, reach: 34, bursts: 3, behind: .3, top: -26, bottom: 116, items: [
|
||||
['lettuce-2', 22, 1], ['tomato', 17, 1], ['bacon', 24, 1], ['onion-1', 15, 1], ['jalapeno-1', 12, 1], ['lettuce-1', 24, 1],
|
||||
['pickle', 11, 1], ['tomato', 13, 0], ['onion-2', 12, 0], ['jalapeno-2', 11, 0], ['bacon', 18, 0], ['lettuce-3', 18, 0],
|
||||
['sesame-1', 3.4, 1], ['sesame-2', 3.8, 0], ['sesame-1', 3, 0], ['sesame-1', 2.6, 0]
|
||||
] },
|
||||
burger: [
|
||||
['lettuce-3', 70, -37, 21, 24, 'b', 0, 0],
|
||||
['onion-2', 27, -43, 13, 30, 'b', 0, 0],
|
||||
['lettuce-2', 47, -27, 26, 12, 'f', 1, 0],
|
||||
['onion-1', 14, -21, 24, -15, 'f', 1, 0],
|
||||
['tomato', 81, 6, 27, 20, 'f', 1, 0],
|
||||
['lettuce-1', -9, 19, 25, -30, 'f', 1, 0],
|
||||
['lettuce-1', 94, 38, 27, 42, 'f', 1, 1],
|
||||
['tomato', -20, 50, 20, -34, 'f', 0, 1],
|
||||
['onionring', 103, 62, 23, 15, 'f', 0, 0],
|
||||
['bacon', -31, 68, 26, -12, 'f', 0, 1],
|
||||
['bacon', 110, 84, 24, 12, 'f', 0, 0],
|
||||
['jalapeno-1', 6, 107, 16, 20, 'f', 0, 0],
|
||||
['pickle', 73, 101, 16, -14, 'f', 0, 0],
|
||||
['sesame-1', 33, -6, 6.5, 25, 'f', 1, 0],
|
||||
['sesame-1', 39, -15, 6, -35, 'f', 0, 1],
|
||||
['sesame-2', 62, -17, 8, -20, 'f', 0, 0],
|
||||
['sesame-1', 58, -5, 5.5, 10, 'f', 1, 1]
|
||||
],
|
||||
'burger-visit': { seed: 8, food: [38, 49, 37, 47], hw: .63, reach: 26, bursts: 2, behind: .3, top: 6, bottom: 112, left: -12, items: [
|
||||
['lettuce-2', 20, 1], ['tomato', 16, 1], ['bacon', 22, 1], ['onion-1', 14, 1], ['jalapeno-1', 11, 1], ['lettuce-1', 20, 0],
|
||||
['pickle', 10, 0], ['tomato', 12, 0], ['sesame-1', 3.4, 0], ['sesame-2', 3.8, 0]
|
||||
@@ -294,7 +308,8 @@
|
||||
var blasts = $$('[data-blast]').map(function (box) {
|
||||
var spec = SCATTER[box.getAttribute('data-blast')];
|
||||
if (!spec) return null;
|
||||
var set = scatter(spec);
|
||||
// Array = von Hand gesetzte Komposition, Objekt = berechnete Streuung
|
||||
var set = Array.isArray(spec) ? spec : scatter(spec);
|
||||
var lazy = box.getAttribute('data-blast-mode') !== 'hero';
|
||||
var holder = document.createElement('span');
|
||||
holder.className = 'blast__bits';
|
||||
@@ -304,7 +319,8 @@
|
||||
if (mobileBits && !b[6]) return;
|
||||
// Verschachtelt, damit sich nichts in die Quere kommt:
|
||||
// .bit (Scroll-Explosion) > .bit__c (CSS-Zentrierung) > .bit__in (Intro) > .bit__fl (Schweben) > img (feste Drehung)
|
||||
var size = b[3] * bitScale;
|
||||
// Hero: Handy etwas weniger vergrößert (1,2 statt 1,35), damit die Fontäne den Burger nur berührt und nicht überdeckt
|
||||
var size = b[3] * (mobileBits && !lazy ? 1.2 : bitScale);
|
||||
var el = document.createElement('span');
|
||||
el.className = 'bit bit--' + b[5];
|
||||
el.style.left = b[1] + '%'; el.style.top = b[2] + '%'; el.style.width = size + '%';
|
||||
@@ -485,7 +501,8 @@
|
||||
var parts = $$('[data-hero-big] .part', hero);
|
||||
gsap.to(parts[0], { xPercent: -10, ease: 'none', scrollTrigger: { trigger: hero, start: 'top top', end: 'bottom top', scrub: true } });
|
||||
gsap.to(parts[1], { xPercent: 12, ease: 'none', scrollTrigger: { trigger: hero, start: 'top top', end: 'bottom top', scrub: true } });
|
||||
gsap.to('.hero__burger', { yPercent: -12, ease: 'none', scrollTrigger: { trigger: hero, start: 'top top', end: 'bottom top', scrub: true } });
|
||||
// CSS zentriert mit translate(-50%, -50%), GSAP liest das als yPercent -50: also -62 = 12 % nach oben
|
||||
gsap.to('.hero__burger', { yPercent: -62, ease: 'none', scrollTrigger: { trigger: hero, start: 'top top', end: 'bottom top', scrub: true } });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -544,17 +561,35 @@
|
||||
y: v.y * .3 + (v.y / len) * W() * k * .55 - W() * .45 * k
|
||||
};
|
||||
};
|
||||
// Hero = Fontäne: Der Burger wurde von unten getroffen. Alles schießt aus der Burger-Mitte nach oben,
|
||||
// fächert zur Seite auf (Spin dreht nach außen) und die Scroll-Explosion setzt diese Bewegung fort.
|
||||
var FX = .39, FY = .45; // Ausbruchspunkt in Box-Anteilen (Mitte des Burgers)
|
||||
var spread = function (b) { // Abstand Ausbruchspunkt -> Endposition in px
|
||||
return { x: (b.x / 100 - FX) * W(), y: (b.y / 100 - FY) * bl.box.offsetHeight };
|
||||
};
|
||||
var launch = function (b, k) { // Scroll-Ziel: weiter nach oben + nach außen fächern
|
||||
var d = spread(b), sp = b.layer === 'n' ? 1.5 : b.layer === 'b' ? .7 : 1;
|
||||
return { x: d.x * 1.1 * sp * k, y: -(W() * .55 + Math.max(0, -d.y) * .4) * sp * k };
|
||||
};
|
||||
var floats = [];
|
||||
var tl = gsap.timeline({ paused: true });
|
||||
bl.bits.forEach(function (b, i) {
|
||||
b.side = i % 2 ? 1 : -1;
|
||||
b.side = bl.hero ? (b.x < FX * 100 ? -1 : 1) : (i % 2 ? 1 : -1);
|
||||
floats.push(gsap.to(b.fl, { y: '+=' + rand(-16, -8), rotation: '+=' + rand(-8, 8), duration: rand(1.8, 3.2), yoyo: true, repeat: -1, ease: 'sine.inOut', delay: rand(0, 1.5), paused: true }));
|
||||
var spin = rand(160, 340) * b.side;
|
||||
var grow = b.layer === 'b' ? 1.15 : 1.9;
|
||||
var spin = (bl.hero ? rand(70, 210) : rand(160, 340)) * b.side;
|
||||
var grow = b.layer === 'b' ? 1.15 : b.layer === 'n' ? 2.6 : bl.hero ? 1.6 : 1.9;
|
||||
if (bl.hero) {
|
||||
gsap.from(b.inner, { x: function () { return -vec(b).x; }, y: function () { return -vec(b).y; }, scale: .2, opacity: 0, rotation: -spin / 3, duration: 1.2, ease: 'back.out(1.3)', delay: .55 + i * .035 });
|
||||
tl.to(b.el, { x: function () { return away(b, 1).x; }, y: function () { return away(b, 1).y; }, rotation: spin, scale: grow, duration: 1, ease: 'power2.in' }, 0)
|
||||
.to(b.el, { opacity: 0, duration: .25, ease: 'none' }, .75);
|
||||
// Intro: aus der Burger-Mitte nach oben; x gleitet, y schießt über das Ziel hinaus und fällt zurück
|
||||
var dist = Math.sqrt(Math.pow(b.x / 100 - FX, 2) + Math.pow((b.y / 100 - FY) * .72, 2));
|
||||
var t0 = .5 + (i % 5) * .03, dur = .95 + dist * .8;
|
||||
gsap.from(b.inner, { x: function () { return -spread(b).x; }, duration: dur, ease: 'power3.out', delay: t0 });
|
||||
gsap.from(b.inner, { y: function () { return -spread(b).y; }, duration: dur + .35, ease: 'back.out(2.1)', delay: t0 });
|
||||
gsap.from(b.inner, { scale: .2, opacity: 0, rotation: -spin / 2, duration: dur, ease: 'back.out(1.4)', delay: t0 });
|
||||
// Scroll: Position schießt zuerst schnell hoch und läuft dann aus (Fontäne), Spin/Größe wachsen gleichmäßig mit
|
||||
var st = b.layer === 'n' ? 0 : b.layer === 'f' ? .04 + (i % 4) * .02 : .12;
|
||||
tl.to(b.el, { x: function () { return launch(b, 1).x; }, y: function () { return launch(b, 1).y; }, duration: 1 - st, ease: 'power1.out' }, st)
|
||||
.to(b.el, { rotation: spin, scale: grow, duration: 1 - st, ease: 'none' }, st)
|
||||
.to(b.el, { opacity: 0, duration: .3, ease: 'none' }, .6);
|
||||
} else {
|
||||
tl.fromTo(b.el, { x: function () { return -vec(b).x * .6; }, y: function () { return -vec(b).y * .6; }, scale: .4, opacity: 0, rotation: -spin / 3 },
|
||||
{ x: 0, y: 0, scale: 1, opacity: 1, rotation: 0, duration: .4, ease: 'power2.out' }, 0)
|
||||
|
||||
Reference in new issue
Block a user