Mundarija (30)
- Bu darsda
- 1. Nega bu kerak?
- 2. Tween: bitta harakat
- 2.1 to, from, fromTo, set
- 2.2 stagger
- 3. Timeline: harakatlarni vaqt o'qida joylash
- 3.1 Zanjir va joylashuv parametri
- 3.2 Hisoblab ko'ramiz
- 3.3 Timeline'ni boshqarish
- 4. React'da: useGSAP
- 4.1 Nega useEffect yetmaydi
- 4.2 contextSafe: hodisadagi animatsiya
- 5. ScrollTrigger
- 5.1 Asosiy sozlamalar
- 5.2 scrub va pin: scroll hikoyasi
- 5.3 CSS, Motion yoki GSAP?
- 6. SplitText: matnni harflarga bo'lish
- 7. Harakatni kamaytirish: gsap.matchMedia()
- 8. Narx va CSP — o'lchov
- 9. GSAP yoki Motion?
- 10. Kanon nega GSAP'ni olmadi — tajriba
- 11. Ko'p uchraydigan xatolar
- 12. Mashqlar
- 1-mashq (oson): qachon boshlanadi?
- 2-mashq (o'rta): place ga ">" va "<0.1" ni qo'shing
- 3-mashq (qiyin): GSAP timeline'ni Motion bilan
- 4-mashq: Vazifalar qadami — tajriba (commit yo'q)
- 13. Real ishda
- Xulosa
- Manbalar
GSAP React'da: timeline, ScrollTrigger, useGSAP va SplitText
Qisqacha: GSAP — murakkab animatsiya "ssenariylari" uchun kutubxona.
gsap.to(nishon, { x: 100 })— bitta harakat (tween).gsap.timeline()— ko'p harakatni vaqt o'qida aniq joylash: "sarlavhadan 0.2 s oldin taomlar boshlansin". ScrollTrigger animatsiyani scroll'ga bog'laydi:scrub— scroll bilan birga,pin— elementni "mixlab" qo'yadi. React'dauseGSAPhooki animatsiyalarni komponent bilan birga tozalaydi. Narxi — +43.4 KB gzip. Shuning uchun GSAP marketing sahifalari va "scroll hikoyalari" uchun, ish vositasi ilovalari uchun emas.
Bu darsda
gsap.to,from,fromTo,setvastaggerbilan harakat yozasiz.- Timeline'da joylashuv parametrini (
"<","-=0.2", yorliqlar) o'qiysiz va hisoblaysiz. useGSAPbilan React'da animatsiyani to'g'ri tozalaysiz,contextSafeni bilasiz.- ScrollTrigger bilan
scrub,pin,toggleActionsva SplitText bilan harf animatsiyasini yasaysiz. - GSAP'ning narxi, CSP bilan mosligi va Motion'dan qachon afzalligini o'lchov bilan aytasiz.
Oldin bilishingiz kerak: Motion IV: scroll animatsiya va motion values, Motion II: variants va stagger, useRef II: DOM elementlari, Effekt hayot sikli va StrictMode, Scroll-driven animatsiyalar.
1. Nega bu kerak?
«Bahor» 10 yoshga to'ldi. Jasur aka bayram sahifasini xohlaydi. Sarlavha harfma-harf "yozilsin", taomlar ketma-ket chiqsin, narxlar "sakrab" paydo bo'lsin. Pastroqda "Osh qanday tayyorlanadi" bo'limi: foydalanuvchi aylantirgan sari qozon joyida turib qolsin, uning yonidan bosqichlar (zirvak, guruch, dam) birin-ketin o'tsin.
Buni Motion bilan ham yozsa bo'ladi. Lekin 15 ta harakat bir-biriga bog'langan: biri tugashidan 0.2 s oldin keyingisi, biri boshqasi bilan bir vaqtda. Har birining delay ini qo'lda hisoblash — bitta harakat o'zgarsa, qolganlari ham qayta hisoblanadi.
Hayotiy o'xshatish: to'y dasturi. Boshlovchining qog'ozida: "19:00 — kelin-kuyov kiradi, kirishidan 10 soniya oldin musiqa boshlanadi, ular o'tirgach — birinchi tilak". Vaqtlar bir-biriga nisbatan yozilgan. Bitta tadbir cho'zilsa, qolganlari o'zi suriladi. GSAP timeline — aynan shu dastur.
GSAP (GreenSock Animation Platform) — ko'p yillik JavaScript animatsiya kutubxonasi. U framework'ga bog'liq emas: React, Vue yoki oddiy JS bilan ishlaydi. Bugun (3.15.0) ScrollTrigger, SplitText, MorphSVG kabi barcha plaginlar ochiq npm paketining ichida. README'sida: Webflow tufayli GSAP to'liq bepul, tijoriy loyihada ham. Ilgari bonus plaginlar faqat pullik Club GSAP a'zolariga edi. Litsenziyasi esa MIT emas: package.json dagi license maydonida — "Standard 'no charge' license: https://gsap.com/standard-license.". Bepul, lekin o'z shartlari bor.
Natija oynasida GSAP yo'q. Shuning uchun bu darsdagi GSAP kodi o'zingizning loyihangiz uchun (npm i -E gsap@3.15.0 @gsap/react@2.1.2). Natijalar — kanon tajribasi va biz Chrome 155 da o'tkazgan qo'shimcha o'lchovlardan.
2. Tween: bitta harakat
2.1 to, from, fromTo, set
GSAP'da bitta harakat — tween (inglizcha "in-between" — "orasidagi"). Boshlang'ich va oxirgi holat orasidagi barcha oraliq kadrlarni kutubxona hisoblaydi.
import gsap from "gsap";
// hozirgi holatdan → shu qiymatlarga
gsap.to(".narx", { x: 100, duration: 0.5, ease: "power2.out" });
// shu qiymatlardan → hozirgi holatga (paydo bo'lish)
gsap.from(".taom", { opacity: 0, y: 20, duration: 0.4 });
// ikkalasini aniq berish
gsap.fromTo(".chiziq", { scaleX: 0 }, { scaleX: 1, duration: 1 });
// darhol, animatsiyasiz
gsap.set(".modal", { autoAlpha: 0 });- Nishon — CSS selektor, element, elementlar massivi yoki istalgan JS obyekti.
gsap.to(hisob, { qiymat: 1250 })— oddiy obyektning sonini ham animatsiya qiladi (hisoblagich uchun). x,y,rotation,scale—transformqisqartmalari (Motion'dagix,ykabi).autoAlpha—opacity+visibility: hidden(0 da element bosilmaydi ham).ease— tezlanish egri chizig'i:"power2.out"(oxirida sekinlashadi),"back.out(1.7)"(biroz o'tib qaytadi),"elastic.out","none"(tekis).duration— soniyada:0.5— yarim soniya. CSS va WAAPI'dagi millisekund emas.
2.2 stagger
Bir nechta nishon bo'lsa, stagger: 0.1 — har biri oldingisidan 0.1 s keyin boshlanadi. Motion II dagi delayChildren: stagger(…) ning o'zi:
gsap.from(".taom", {
opacity: 0,
x: -30,
duration: 0.4,
stagger: 0.1,
});Uchta taom: 0.0, 0.1, 0.2 s da boshlanadi, oxirgisi 0.6 s da tugaydi.
3. Timeline: harakatlarni vaqt o'qida joylash
3.1 Zanjir va joylashuv parametri
gsap.timeline() — tweenlar "konteyneri". Standartda har yangi tween oldingisi tugaganda boshlanadi. Uchinchi argument — joylashuv parametri (position parameter) — buni o'zgartiradi:
const tl = gsap.timeline({
defaults: { duration: 0.4, ease: "power2.out" },
});
tl.from(".sarlavha", { y: -20, opacity: 0 })
.from(".taom", { x: -30, opacity: 0, stagger: 0.1 }, "-=0.2")
.addLabel("narx")
.from(".narx", { scale: 0.8, opacity: 0 }, "narx");| Qiymat | Ma'nosi |
|---|---|
| (yo'q) | timeline oxiriga |
1 |
aniq 1-soniyada |
"-=0.2" / "+=0.5" |
oxiridan 0.2 s oldin / 0.5 s keyin |
"<" / ">" |
oldingi tween boshida / oxirida |
"<0.1" |
oldingi tween boshidan 0.1 s keyin |
"narx", "narx+=0.2" |
addLabel bilan qo'yilgan yorliqqa nisbatan |
defaults — barcha tweenlar uchun umumiy sozlama: har birida duration yozish shart emas.
3.2 Hisoblab ko'ramiz
Yuqoridagi timeline qachon nima qiladi? Uni o'zimiz hisoblaymiz — GSAP'ning joylashuv qoidasining soddalashtirilgan modeli:
// GSAP joylashuv parametri — soddalashtirilgan model
const fmt = (n) => n.toFixed(2);
function place(steps) {
let end = 0; // timeline oxiri
let prevStart = 0; // oldingi tween boshi
const labels = {};
const lines = [];
for (const s of steps) {
const at = s.at;
if (s.label) {
labels[s.label] = end;
continue;
}
let start = end;
if (typeof at === "number") start = at;
else if (at === "<") start = prevStart;
else if (at?.startsWith("-=")) start = end - Number(at.slice(2));
else if (at?.startsWith("+=")) start = end + Number(at.slice(2));
else if (at in labels) start = labels[at];
const finish = start + s.duration;
lines.push(`${s.name}: ${fmt(start)}–${fmt(finish)}`);
prevStart = start;
end = Math.max(end, finish);
}
lines.push(`jami: ${end.toFixed(2)} s`);
return lines.join("\n");
}
console.log(
place([
{ name: "sarlavha", duration: 0.4 },
// 3 ta taom, har biri 0.4 s, stagger 0.1 → 0.4 + 2 × 0.1
{ name: "taomlar", duration: 0.6, at: "-=0.2" },
{ label: "narx" },
{ name: "narx", duration: 0.4, at: "narx" },
]),
);Konsolda:
sarlavha: 0.00–0.40
taomlar: 0.20–0.80
narx: 0.80–1.20
jami: 1.20 sHaqiqiy GSAP nima deydi? Xuddi shu timeline'ni Chrome 155 da ishga tushirdik (gsap 3.15.0, tl.duration(), tl.labels.narx, tl.getChildren().length):
timeline: 1.20 s, narx yorlig'i 0.80 s, bolalar 3Bir xil. stagger li tween — bitta "bola", shuning uchun 3 ta. Vaqt chizig'ida:
gantt
title Timeline: 1.2 s
dateFormat x
axisFormat %S.%L
section Sarlavha
sarlavha 0–0.4 :a, 0, 400ms
section Taomlar
Osh 0.2–0.6 :b, 200, 400ms
Lag'mon 0.3–0.7 :c, 300, 400ms
Manti 0.4–0.8 :d, 400, 400ms
section Narx
narx 0.8–1.2 :e, 800, 400msTaomlar sarlavha tugashidan 0.2 s oldin boshlandi ("-=0.2") — ustma-ust tushish harakatni "oqimli" qiladi. Sarlavha 0.4 s cho'zilsa, hech narsani qayta hisoblamaysiz: taomlar va narx o'zi suriladi.
3.3 Timeline'ni boshqarish
Timeline — pleer kabi obyekt: tl.play(), tl.pause(), tl.reverse(), tl.seek(0.8), tl.progress(0.5), tl.timeScale(2) (ikki baravar tez). paused: true bilan yaratib, tugma bosilganda o'ynatish mumkin. Mobil menyu uchun klassik naqsh: bitta timeline — ochish, reverse() — yopish.
Tekshirib ko'ring:
tl.to(".a", { x: 100, duration: 1 }).to(".b", { x: 100, duration: 0.5 }, "<")—.bqachon boshlanadi va timeline necha soniya?
Javob
.b 0 s da — "<" oldingi tweenning boshi. Timeline 1 s: .a 0–1, .b 0–0.5. Eng uzoq tugagani timeline oxiri bo'ladi. Agar ">" bo'lsa, .b 1 s da boshlanib, timeline 1.5 s bo'lardi.
4. React'da: useGSAP
4.1 Nega useEffect yetmaydi
GSAP DOM'ni to'g'ridan-to'g'ri o'zgartiradi. Demak u effektda ishlashi kerak. Lekin uch muammo bor:
- StrictMode dev rejimda effektni ikki marta ishga tushiradi (Effekt hayot sikli). Tozalash bo'lmasa —
fromikki marta qo'llanadi, element "yarim yo'lda" qotib qoladi. - Tozalash — komponent o'chsa, tween va ScrollTrigger'lar xotirada qoladi va scroll hodisasini tinglashda davom etadi.
- Selektor —
".taom"butun sahifadan qidiriladi, boshqa komponentdagi.taomlarni ham ushlaydi.
GSAP'ning javobi — gsap.context(): ichida yaratilgan hamma narsani yozib boradi, revert() esa hammasini bekor qilib, elementlarni asl holatiga qaytaradi. @gsap/react paketidagi useGSAP hooki buni React'ga ulaydi:
import { useRef } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
gsap.registerPlugin(useGSAP);
export function Menu() {
const scope = useRef(null);
useGSAP(
() => {
gsap.from(".taom", { opacity: 0, x: -30, stagger: 0.1 });
},
{ scope }, // ".taom" — faqat shu komponent ichidan
);
return (
<ul ref={scope}>
<li className="taom">Osh</li>
<li className="taom">Lag'mon</li>
</ul>
);
}useGSAP nima beradi:
- Avtomatik tozalash — komponent o'chsa yoki StrictMode qayta ishga tushirsa,
context.revert()chaqiriladi. Kanon tajribasida (tajriba/kitlar/src/k/gsap.tsx) aynan shu naqsh. scope— selektorlar faqat shu ref ichidan qidiriladi. Motion'ninguseAnimateidagiscopebilan bir xil g'oya (Motion IV).dependencies—useEffectdagidek:{ scope, dependencies: [tanlangan] }. O'zgarsa, funksiya qayta ishlaydi.revertOnUpdate: true— avval eskisini bekor qiladi.- Ichkarida
useLayoutEffect— animatsiya brauzer chizishidan oldin o'rnatiladi,fromholatidagi element bir lahza "miltillab" ko'rinmaydi.
4.2 contextSafe: hodisadagi animatsiya
Bosish hodisasida yaratilgan tween useGSAP funksiyasi tashqarisida — kontekst uni bilmaydi va tozalamaydi. Uni contextSafe bilan o'rang:
const { contextSafe } = useGSAP({ scope });
const shake = contextSafe(() => {
gsap.to(".savat", { x: 6, repeat: 5, yoyo: true, duration: 0.05 });
});
return <button onClick={shake}>Savatga</button>;5. ScrollTrigger
5.1 Asosiy sozlamalar
ScrollTrigger — animatsiyani scroll'ga bog'laydigan plagin:
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(useGSAP, ScrollTrigger);
useGSAP(
() => {
gsap.from(".taom", {
opacity: 0,
y: 40,
stagger: 0.1,
scrollTrigger: {
trigger: ".menyu",
start: "top 80%",
toggleActions: "play none none reverse",
},
});
},
{ scope },
);trigger— qaysi element kuzatiladi.start: "top 80%"— "trigger'ning tepasi ekranning 80% chizig'iga yetganda". Birinchi so'z — element nuqtasi, ikkinchisi — ekran nuqtasi.endham xuddi shunday ("bottom top","+=500"— boshidan 500 px keyin).toggleActions— to'rt holat: kirdi, oldinga chiqib ketdi, orqaga qaytib kirdi, orqaga chiqib ketdi."play none none reverse"— kirganda o'ynasin, tepaga qaytib chiqsa — teskari.markers: true— dev rejimda start/end chiziqlarini ekranda chizadi. Production'ga qoldirmang.
5.2 scrub va pin: scroll hikoyasi
scrub: true — animatsiya vaqt bilan emas, scroll bilan yuradi. Aylantirsangiz — oldinga, qaytsangiz — orqaga. scrub: 0.5 — 0.5 s "ergashish" (Motion'dagi useSpring ga o'xshash yumshatish). pin: true — trigger start dan end gacha ekranda mixlangan turadi, sahifa esa uning atrofida aylanadi.
useGSAP(
() => {
const tl = gsap.timeline({
scrollTrigger: {
trigger: ".qozon",
start: "top top",
end: "+=1200",
scrub: 0.5,
pin: true,
},
});
tl.from(".zirvak", { opacity: 0 })
.from(".guruch", { opacity: 0, y: 40 })
.from(".dam", { opacity: 0, y: 40 });
},
{ scope },
);1200 px aylantirish davomida qozon joyida turadi, uning yonida uch bosqich birin-ketin chiqadi. Bu "scrollytelling" — scroll bilan hikoya.
Biz pin va scrub ni vazifalar CSP'si ostida sinab ko'rdik (Chrome 155, end: "+=300", sahifa 550 px aylantirildi):
{"csp":[],"xato":[],"log":["pin-spacer: 1"],"rot":"translate3d(0px, 0px, 0px) rotate(37.1deg)","pinPos":"fixed"}pin elementni pin-spacer nomli div ga o'radi va position: fixed qildi. Sahifa sakramasligi uchun pin-spacer bo'sh joyni ushlab turadi. scrub aylanishni scroll'ga bog'ladi (rotate(37.1deg) — 90° ning bir qismi). CSP buzilishi — 0: GSAP stillarni element.style orqali qo'yadi, <style> tegi yaratmaydi.
Diqqat: ScrollTrigger sahifa balandligini bir marta o'lchaydi. Keyin rasm yuklanib balandlik o'zgarsa, start/end nuqtalari noto'g'ri bo'ladi. Rasmlarga aniq
width/heightbering (Rasm unumdorligi darsidagidek), kontent o'zgarganda esaScrollTrigger.refresh()ni chaqiring.
5.3 CSS, Motion yoki GSAP?
| Vazifa | Eng yengil yo'l |
|---|---|
| progress chizig'i, "ko'ringanda paydo bo'lish" | CSS animation-timeline (C-75) — 0 KB |
| scroll qiymatiga React mantig'i | Motion useScroll (Motion IV) |
pin, bir nechta bosqichli scroll hikoyasi |
GSAP ScrollTrigger |
6. SplitText: matnni harflarga bo'lish
Sarlavha harfma-harf "yozilishi" uchun har harf alohida element bo'lishi kerak. Buni qo'lda qilish — 30 ta <span>. SplitText buni avtomatik qiladi:
import { SplitText } from "gsap/SplitText";
gsap.registerPlugin(useGSAP, SplitText);
useGSAP(
() => {
const split = SplitText.create(".shior", {
type: "words,chars",
aria: "auto",
});
gsap.from(split.chars, { opacity: 0, y: 10, stagger: 0.02 });
},
{ scope },
);Ekran o'quvchi uchun muammo: 14 ta alohida <span> — Malika "B, a, h, o, r…" ni harfma-harf eshitishi mumkin. aria: "auto" — SplitText asl matnni aria-label ga yozadi, bo'laklarni esa ekran o'quvchidan yashiradi. Chrome'dagi o'lchov (o'sha CSP + Trusted Types ostida):
SplitText: 14 harf, aria-label=Bahor oshxonasi"Bahor oshxonasi" — 15 belgi, bo'shliq harf emas: 14. aria-label qo'yildi. CSP va Trusted Types buzilishi — 0. Shrift kech yuklansa yoki ekran eni o'zgarsa, qatorlar qayta bo'linishi kerak — buning uchun autoSplit: true va onSplit sozlamalari bor. useGSAP tozalaganda split.revert() ham chaqiriladi — matn asl holiga qaytadi.
7. Harakatni kamaytirish: gsap.matchMedia()
GSAP'da prefers-reduced-motion uchun gsap.matchMedia() bor. U media so'rov mos kelsa animatsiyani yaratadi, mos kelmay qolsa — avtomatik revert qiladi:
useGSAP(
() => {
const mm = gsap.matchMedia();
mm.add("(prefers-reduced-motion: no-preference)", () => {
gsap.from(".taom", { opacity: 0, y: 40, stagger: 0.1 });
});
},
{ scope },
);Harakat kamaytirilgan bo'lsa, ichidagi kod umuman ishlamaydi — taomlar darhol joyida. pin li scroll hikoyasini ham shu ichiga qo'ying: kamaytirilgan rejimda bosqichlar oddiy ro'yxat bo'lib qoladi. Bitta matchMedia bilan ekran eni bo'yicha ham ajratish mumkin ("(min-width: 800px)") — mobil va kompyuter uchun turli animatsiya.
8. Narx va CSP — o'lchov
Kanon tajribasi (tajriba/kutubxonalar.txt, gsap 3.15.0 + ScrollTrigger + @gsap/react 2.1.2, Vite 8.3.3, gzip) va CSP natijasi:
- Motion m.* (vazifalar)14,2 KB
- Motion to'liq40,4 KB
- GSAP + ScrollTriggerCSP 043,4 KB
Manba: Kanon o'lchovi: tajriba/kutubxonalar.txt va QADAMLAR #23–#26 (Chrome 155, 2026-10-14)
- Hajm — +43.4 KB, to'liq Motion bilan deyarli teng. Faqat GSAP yadrosi (ScrollTrigger'siz) alohida o'lchanmadi.
- CSP — kanon tajribasida 0 buzilish. Biz qo'shimcha sinadik:
pin,scrubva SplitText —style-src 'self'va Trusted Types ostida ham 0. Bu GSAP'ning kuchli tomoni. U<style>yaratmaydi vainnerHTMLga satr yozmaydi. Mantine va Konva bunday CSP'da umuman ochilmagan edi, sonner esa ishladi, lekin uslubi to'sildi (UI kutubxonalar xaritasi, Node-diagramma va canvas). - Lazy yuklash — GSAP faqat landing sahifasida kerak bo'lsa, o'sha marshrutni lazy qiling: ilovaning qolgan qismi uni yuklamaydi.
9. GSAP yoki Motion?
Ikkalasi ham yaxshi kutubxona. Savol — vazifaga qaysi biri mos:
| Mezon | Motion | GSAP |
|---|---|---|
| Yondashuv | deklarativ: props (animate, exit) |
imperativ: gsap.to, timeline |
| React bilan | tabiiy: state → animatsiya, AnimatePresence, layout |
useGSAP orqali, DOM'ga to'g'ridan-to'g'ri |
| Murakkab ketma-ketlik | sequence (at, yorliqlar) — bor |
timeline — eng kuchli, boshqarish (seek, reverse) |
Scroll hikoyasi, pin |
useScroll — pin yo'q |
ScrollTrigger |
| Matn bo'lish, SVG morph | yo'q | SplitText, MorphSVG |
| Hajm (o'lchov) | 14.2 KB (LazyMotion) … 40.4 KB |
43.4 KB |
Qisqasi: ilova interfeysi (ro'yxat, modal, tab, holat o'zgarishi) — Motion yoki CSS. Marketing sahifasi, scroll hikoyasi, reklama banneri, SVG illyustratsiya — GSAP.
Motion ham timeline'ga o'xshash ketma-ketlikni biladi. 3-mashqda yuqoridagi GSAP timeline'ini Motion bilan qayta yozamiz va bir xil 1.20 s ni olamiz.
10. Kanon nega GSAP'ni olmadi — tajriba
vazifalar — ish vositasi: ro'yxat, forma, statistika. Unda scroll hikoyasi, pin, harfma-harf sarlavha yo'q. Kanon tajribasi GSAP'ni o'lchadi (tajriba/kitlar/src/k/gsap.tsx: useGSAP + scope, timeline().from(".b", { stagger }), ScrollTrigger scrub): +43.4 KB, CSP 0, xato yo'q. Texnik to'siq yo'q. Lekin ilovada Motion allaqachon bor (14.2 KB) va qator animatsiyasi uchun yetadi. Ikkinchi animatsiya kutubxonasi birinchi yuklashni yana ~43 KB ga oshirardi — hech qanday yangi imkoniyat foydalanuvchiga bermasdan.
Qoida (QADAMLAR, #27–#30): kutubxona vazifa bo'lganda qo'shiladi, "chiroyli" bo'lgani uchun emas.
11. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
dev'da from animatsiyasi yarim yo'lda qotadi |
useEffect + StrictMode, tozalash yo'q |
useGSAP |
boshqa komponentdagi .taom ham animatsiya bo'ldi |
scope berilmagan |
useGSAP(fn, { scope }) |
| bosishdagi animatsiya sahifadan chiqqach ham ishlaydi | hodisadagi tween kontekstdan tashqarida | contextSafe |
duration: 300 — animatsiya 5 daqiqa |
GSAP soniyada o'lchaydi | duration: 0.3 |
| ScrollTrigger noto'g'ri joyda boshlanadi | rasm yuklanib balandlik o'zgardi | o'lchamlar, ScrollTrigger.refresh() |
ScrollTrigger ishlamaydi, xato yo'q |
plagin ro'yxatdan o'tmagan | gsap.registerPlugin(ScrollTrigger) |
| ekran o'quvchi sarlavhani harflab o'qiydi | SplitText aria siz |
aria: "auto" |
| production'da qizil chiziqlar | markers: true qolib ketgan |
faqat dev'da |
12. Mashqlar
Mashqlar kurs/mashqlar/20/28-gsap/ da. GSAP natija oynasida yo'q — 2- va 3-mashqlar sof JavaScript va Motion bilan, GSAP g'oyasini tekshiradi.
1-mashq (oson): qachon boshlanadi?
Timeline: tl.to(".a", { duration: 1 }).to(".b", { duration: 1 }, POZITSIYA). .b necha soniyada boshlanadi?
POZITSIYAyo'q →"<"→"-=0.5"→"<0.25"→
Yechim
- Yo'q — oxiriga:
.a1 s da tugaydi,.b1 s da. "<"—.aning boshi: 0."-=0.5"— timeline oxiridan (1) 0.5 s oldin: 0.5."<0.25"—.aboshidan 0.25 s keyin: 0.25.
2-mashq (o'rta): place ga ">" va "<0.1" ni qo'shing
«Hisoblab ko'ramiz» bo'limidagi place funksiyasi ">" (oldingi tween oxiri) va "<0.1" (oldingi tween boshidan siljish) ni bilmaydi. Qo'shing. Kutilgan natija pastda.
Ishora: oldingi tweenning oxirini ham saqlang (prevEnd). "<0.1" — "<" bilan boshlanadi va qolgan qismi son: at.slice(1) (satr metodlari). "<" ning o'zi ham shu qoidaga tushsin (bo'sh qism — 0).
const fmt = (n) => n.toFixed(2);
function place(steps) {
let end = 0;
let prevStart = 0;
const lines = [];
for (const s of steps) {
const at = s.at;
let start = end;
if (typeof at === "number") start = at;
else if (at === "<") start = prevStart;
else if (at?.startsWith("-=")) start = end - Number(at.slice(2));
const finish = start + s.duration;
lines.push(`${s.name}: ${fmt(start)}–${fmt(finish)}`);
prevStart = start;
end = Math.max(end, finish);
}
return lines.join("\n");
}
console.log(
place([
{ name: "qozon", duration: 1 },
{ name: "bug'", duration: 0.5, at: "<0.1" },
{ name: "osh", duration: 0.4, at: ">" },
]),
);Konsolda:
qozon: 0.00–1.00
bug': 1.00–1.50
osh: 1.50–1.90Yechim
const fmt = (n) => n.toFixed(2);
function place(steps) {
let end = 0;
let prevStart = 0;
let prevEnd = 0;
const lines = [];
for (const s of steps) {
const at = s.at;
let start = end;
if (typeof at === "number") start = at;
else if (at === ">") start = prevEnd;
else if (at?.startsWith("<")) {
start = prevStart + Number(at.slice(1) || 0);
} else if (at?.startsWith("-=")) {
start = end - Number(at.slice(2));
}
const finish = start + s.duration;
lines.push(`${s.name}: ${fmt(start)}–${fmt(finish)}`);
prevStart = start;
prevEnd = finish;
end = Math.max(end, finish);
}
return lines.join("\n");
}
console.log(
place([
{ name: "qozon", duration: 1 },
{ name: "bug'", duration: 0.5, at: "<0.1" },
{ name: "osh", duration: 0.4, at: ">" },
]),
);Konsolda:
qozon: 0.00–1.00
bug': 0.10–0.60
osh: 0.60–1.00">" — timeline oxiri emas, oldingi tweenning oxiri. Farq shu yerda: «bug'» 0.6 da tugadi, timeline esa 1.0 gacha (qozon). "osh" 0.6 da boshlandi — "-=0" yoki standart bo'lsa 1.0 da boshlanardi. Number("" || 0) — "<" ning o'zi uchun 0 qo'shadi.
3-mashq (qiyin): GSAP timeline'ni Motion bilan
«Zanjir va joylashuv parametri» bo'limidagi timeline'ni natija oynasida Motion bilan qayta yozing. Talablar:
useAnimateva sequence (massivlar massivi) — bittaanimate([...])chaqiruvi.- Sarlavha 0.4 s; taomlar sarlavha tugashidan 0.2 s oldin, har biri 0.4 s,
stagger0.1;"narx"yorlig'i; narx yorliqda. - Konsolga umumiy davomiylik (
controls.duration, 2 xona) va tugagandatugadi.
Ishora: Motion sequence'da joylashuv — uchinchi elementdagi at ("-0.2" — oldingisi tugashidan 0.2 s oldin, "narx" — yorliq). Yorliq — massivdagi oddiy satr. stagger — motion/react dan, delay: stagger(0.1) (Motion II).
Yechim
import { stagger, useAnimate } from "motion/react";
export default function App() {
const [scope, animate] = useAnimate();
async function run() {
const controls = animate([
["h2", { opacity: [0, 1], y: [-20, 0] }, { duration: 0.4 }],
[
".taom",
{ opacity: [0, 1], x: [-30, 0] },
{ duration: 0.4, delay: stagger(0.1), at: "-0.2" },
],
"narx",
[
".narx",
{ opacity: [0, 1], scale: [0.8, 1] },
{ duration: 0.4, at: "narx" },
],
]);
console.log("davomiylik:", controls.duration.toFixed(2), "s");
await controls;
console.log("tugadi");
}
return (
<div ref={scope}>
<button onClick={run}>Boshla</button>
<h2>Menyu</h2>
<p className="taom">Osh</p>
<p className="taom">Lag'mon</p>
<p className="taom">Manti</p>
<p className="narx">35 000</p>
</div>
);
}Konsolda:
davomiylik: 1.20 s
tugadiGSAP bilan bir xil — 1.20 s. Sintaksis boshqa ("-=0.2" → at: "-0.2", addLabel → massivdagi satr), g'oya o'sha. Agar ilovada Motion allaqachon bo'lsa, bunday ketma-ketlik uchun GSAP qo'shish shart emas. Mezon — pin, SplitText, MorphSVG kabi imkoniyatlar kerakmi.
4-mashq: Vazifalar qadami — tajriba (commit yo'q)
Kanon GSAP'ni olmadi. O'z tajribangiz: vazifalar dan nusxa olingan alohida papkada npm i -E gsap@3.15.0 @gsap/react@2.1.2. Bo'sh holat (#bosh-xabar) ikonkasiga useGSAP bilan kichik "silkinish" qo'shing: scope, gsap.matchMedia bilan prefers-reduced-motion. npm run build — birinchi yuklash JS qancha o'sdi? Brauzerda CSP konsolida xato bormi?
Yechim
Kutiladigan natija:
- CSP xatosi yo'q — kanon tajribasi va bizning
pin/SplitText o'lchovimizdagidek. - Birinchi yuklash JS o'sadi. GSAP yadrosi (ScrollTrigger'siz) alohida o'lchanmagan; to'liq to'plam (+ ScrollTrigger) — +43.4 KB. Bitta silkinish uchun bu juda qimmat. Xuddi shuni CSS
@keyframes(CSS animatsiyalari React'da) 0 KB bilan qiladi. - Xulosa — kanon qarori bilan bir xil: ilova uchun GSAP ortiqcha. Nusxa papkani o'chiring.
13. Real ishda
- Landing sahifalar va reklama — mahsulot taqdimoti, bayram aksiyalari, scroll bilan hikoya qiluvchi sahifalar. Ko'p raqamli agentliklarning portfoliosida GSAP deyarli majburiy ko'nikma.
- Reklama bannerlari — GSAP README'sida: har bir yirik reklama tarmog'i GSAP'ni banner fayl hajmiga qo'shmaydi, ko'pchiligi uni o'z CDN'ida saqlaydi.
- SVG illyustratsiya va infografika — MorphSVG, DrawSVG, MotionPath plaginlari.
- Intervyu savollari: "GSAP timeline'dagi joylashuv parametri nima?", "React'da GSAP animatsiyasini qanday tozalaysiz?", "
scrubvatoggleActionsfarqi?", "Motion yoki GSAP — qachon qaysi?".
Xulosa
- Tween — bitta harakat (
to,from,fromTo,set),durationsoniyada,stagger— ketma-ket. - Timeline — harakatlar vaqt o'qida:
"<",">","-=0.2", yorliqlar. Bitta harakat o'zgarsa, qolganlari o'zi suriladi. - React'da —
useGSAP: avtomatikrevert,scope,dependencies; hodisadagi animatsiya —contextSafe. - ScrollTrigger:
start/end,toggleActions,scrub,pin(pin-spacer); SplitText —aria: "auto"bilan; harakatni kamaytirish —gsap.matchMedia(). - +43.4 KB, CSP va Trusted Types bilan to'liq mos (o'lchov). Marketing va scroll hikoyasi uchun — GSAP, ilova interfeysi uchun — Motion yoki CSS.
Keyingi dars: Lottie, Rive va AutoAnimate — dizayner tayyorlagan animatsiyalarni sahifaga qo'yish va bitta qator bilan ro'yxat animatsiyasi. U yerda CSP bilan haqiqiy to'qnashuvni ko'ramiz.
Manbalar
- GSAP 3.15.0: gsap.to/from, Timeline, position parameter, ScrollTrigger, SplitText, gsap.matchMedia — gsap.com/docs/v3 (2026-10)
- @gsap/react 2.1.2: useGSAP — gsap.com/resources/React
- GSAP litsenziyasi:
gsap/package.json3.15.0 (npm view gsap@3.15.0 license), gsap.com/standard-license; README — "GSAP is FREE!" bo'limi - Kanon tajribasi:
tajriba/kitlar/src/k/gsap.tsx,natijalar/tajriba/kutubxonalar.txt
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!