Albina — zboara in jurul cursorului
Pagina live: /albina/. Nu e un port: e o piesa scrisa de noi, care refoloseste albina Lottie si tratamentul umbrei de la LeoParpeix, dar o conduce cu mouse-ul in loc de scroll.
Ce face
- Un singur ecran galben, un titlu scurt, si albina care zboara in preajma cursorului — fara sa se aseze vreodata pe el.
- Efectul vine din trei intarzieri suprapuse, si asta e tot secretul: (1) o ancora urmareste cursorul, incet; (2) un punct de orbita se roteste la nesfarsit in jurul ancorei; (3) albina urmareste punctul de orbita, ceva mai repede. Pentru ca pasul 2 nu se opreste niciodata, albina continua sa dea ocol si cand mouse-ul sta pe loc, in loc sa se parcheze pe cursor.
- Orbita e turtita pe verticala (
ORBIT_FLATTEN = 0.55), ceea ce citeste ca perspectiva: pare ca da ocol pe orizontala, nu ca deseneaza un cerc pe ecran. - Inclinarea vine din viteza ei orizontala, nu din pozitia cursorului — deci se inclina in directia in care chiar merge, inclusiv cand se intoarce singura in orbita.
- Umbra foloseste distanta ramasa pana la ancora ca senzatie de inaltime: cand goneste dupa cursor se departeaza si paleste, cand s-a asezat in cerc se strange sub ea.
- Pana la prima miscare de mouse — si deci pe orice ecran tactil, unde aceea nu vine niciodata — cursorul e inlocuit de doua sinusoide lente, iar albina hoinareste singura prin ecran. Pagina nu arata niciodata moarta la incarcare.
Ce cere site-ul
- GSAP 3.13.0 — deja global. Se folosesc doar
gsap.set,gsap.tickersigsap.utils.clamp. - lottie-web 5.13.0, build-ul
lottie_svg.min.js, incarcat cu un tag<script>creat din JS, doar pe pagina asta. Acelasi fisierleo-bee.jsonca la LeoParpeix — nu s-a mai urcat inca o copie. - Fara ScrollTrigger si fara Lenis. Pagina nu are scroll deloc, deci nu exista un proprietar al scroll-ului si nu se bate cu nimic. In tabelul de compatibilitate sta la grupa 3 (GSAP plus un fisier tras de pe CDN), nu la grupa 2, exact din cauza lui lottie.
- Fonts: DM Sans, acelasi ca la LeoParpeix.
Cum e construit in Bricks
O sectiune, un element Code. Markup-ul are 610 octeti — o secventa de titlu si doua div-uri goale pe care le umple lottie.
- Sectiunea
.albeposition: fixed; inset: 0, adica e chiar viewport-ul. Asta e alegerea care scuteste toata aritmetica:clientX/clientYde la mouse se pun direct pex/yla albina, fara corectii de scroll sau de offset. - Page settings:
bodyClasses: albina,headerDisabled,footerDisabled,disableLazyLoad. body.albina { overflow: hidden }— o pagina de un singur ecran nu trebuie sa poata fi derulata.- Ca la orice port:
*, titlul si restul sunt scopate sub.alb, iarcolor: #000sifont-size: 16pxsunt puse explicit pentru ca tema pune gri si 15px. - Titlul are doua variante, comutate din CSS: „Misca mouse-ul” pe desktop si „Albina zboara singura” sub
@media (hover: none), (pointer: coarse). Fara asta, pe telefon pagina ar cere ceva ce nu se poate face acolo.
Reglaje
Cele patru numere de sus din JS schimba complet caracterul zborului:
| Constanta | Acum | Ce face |
|---|---|---|
ORBIT_R |
90px | cat de larg da ocol cursorului |
ORBIT_SPEED |
1.5 rad/s | cat de repede se invarte |
ANCHOR_EASE |
0.055 | cat de repede vine cand misti mouse-ul |
BEE_EASE |
0.13 | cat de strans tine cercul |
Capcane
- Interpolarea pe cadru nu e acelasi lucru cu interpolarea pe secunda.
x += (tinta - x) * 0.13merge de doua ori mai repede pe un ecran la 120Hz decat pe unul la 60Hz. Aici toate cele trei urmariri trec prinapproach(), care corecteaza cu1 - Math.pow(1 - ease, dt * 60)— aceeasi fractie pe secunda, indiferent de monitor. La fel si inclinarea, impartita ladt * 60. - Delta de la ticker se plafoneaza.
Math.min(deltaMs, 50): dupa o pauza de tab, un delta de doua secunde ar teleporta albina. Cu plafon, isi reia zborul de unde a ramas. - Bara de admin adauga 32px de scroll (
html { margin-top: 32px }), deci pagina pare derulabila cat esti logat. Vizitatorul delogat nu o vede. Nu e un defect al paginii — se verifica cudocument.getElementById('wpadminbar')inainte sa dai vina pe CSS. - Pe 390px albina iese pana la 75px dincolo de marginea din dreapta, pentru ca orbita de 90px plus amplitudinea hoinarelii depasesc jumatatea ecranului. Lasat intentionat asa — o albina care iese o clipa din cadru si revine arata natural. Nu produce scroll orizontal. Daca cineva vrea totusi sa o tina in ecran, solutia e sa lege
ORBIT_Rsi amplitudinea de latimea viewport-ului, nu sa le lase fixe. - Spre deosebire de LeoParpeix, aici
requestAnimationFramechiar merge in tabul de automatizare (72 de cadre in 1200ms), deci zborul se poate verifica direct. Nu presupune nici intr-o parte, nici in alta: citestegsap.ticker.framede doua ori si compara.
Pasi de reproducere
- Fa sectiunea
position: fixed; inset: 0si puneoverflow: hiddenpe body. De aici incolo coordonatele mouse-ului sunt direct coordonatele albinei. - Incarca lottie-web (build-ul svg) cu un tag
<script>creat din JS si porneste abia dupaonload. Randeaza acelasi JSON de doua ori: o data albina, o data umbra, filtratabrightness(0) blur(2px)si turtitascaleY: 0.5. - Tine trei perechi de coordonate: cursorul, ancora, albina. Ancora urmareste cursorul; punctul de orbita se roteste in jurul ancorei; albina urmareste punctul de orbita. Toate trei prin
approach(), corectat de rata de cadre. - Inclinarea din viteza orizontala proprie, limitata la ±18 grade. Umbra din distanta ramasa pana la ancora.
- Steagul
followingpornestefalsesi devinetruela primulmousemove. Cat efalse, cursorul e generat din doua sinusoide cu perioade fara numitor comun, ca traseul sa nu se repete vizibil. Asta acopera si ecranele tactile, fara nicio detectie de dispozitiv. - Scrie pagina cu
wp_slash()sisignature => wp_hash($code), verifica md5 la citire, apoi\Bricks\Breakpoints::regenerate_bricks_css_files(). - Verifica pe pagina, in ordinea asta: (a)
gsap.ticker.framecreste; (b) fara niciunmousemove, albina se misca singura; (c) trimisa cudispatchEventintr-un colt, ajunge acolo; (d) cu cursorul tinut nemiscat, pozitia ei continua sa varieze — dovada ca orbiteaza si nu se parcheaza.