Mundarija (39)
- Bu darsda
- 1. Nega bu kerak?
- 2. Paket: Framer Motion endi Motion
- 2.1 O'rnatish va import
- 2.2 Saytdagi natija oynasida
- 3. Birinchi animatsiya: initial va animate
- 3.1 motion.div
- 3.2 initial={false}
- 4. State o'zgarganda
- 4.1 animate — state'dan
- 4.2 Har render yangi animatsiya emas
- 5. transition: qanday borish
- 5.1 Tween
- 5.2 Spring
- 5.3 Har xususiyatga alohida
- 5.4 Takrorlash
- 6. Keyframes massivi
- 6.1 Bir nechta nuqta orqali
- 6.2 times va null
- 7. Qanday tez ishlaydi
- 7.1 Kompozitor va JavaScript kadrlari
- 7.2 React render'siz
- 8. prefers-reduced-motion: MotionConfig
- 9. O'z komponentingiz: motion.create
- 10. Narx: Motion qancha turadi
- 11. Vazifalar qadami: yangi qator jonlanadi (holat 25 boshlanadi)
- 11.1 Reja
- 11.2 qator-harakati.ts: kirish sozlamasi
- 11.3 Qator.tsx va HarakatSozlamasi
- 11.4 Kanon tekshiruvlari
- 12. Ko'p uchraydigan xatolar
- 13. Mashqlar
- 1-mashq (oson): props nomlari
- 2-mashq (o'rta): progress chizig'i — scaleX bilan
- 3-mashq (qiyin): "Savatga qo'shildi" belgisi
- 4-mashq: Vazifalar qadami
- 14. Real ishda
- Xulosa
- Manbalar
Motion (Framer Motion) React'da: motion.div, initial, animate va transition — birinchi animatsiyalar
Qisqacha: Motion (avvalgi nomi Framer Motion) — React uchun deklarativ animatsiya kutubxonasi:
npm i motion, import —motion/react. Oddiy teg o'rnigamotion.divyozasiz va ikki narsani aytasiz:initial— qayerdan boshlash,animate— qayerga borish. Qanday borishinitransitionbelgilaydi: davomiylik va easing (tween) yoki prujina (spring).animatedagi qiymat o'zgarsa, Motion joriy holatdan yangi maqsadga silliq o'tadi — to'xtatilgan animatsiya ham "sinmaydi". Qiymat massiv bo'lsa (x: [0, -8, 8, 0]) — keyframes.
Bu darsda
framer-motionvamotionpaketlari farqini bilasiz va to'g'ri import qilasiz.motion.divgainitial,animate,transitionberib, birinchi animatsiyalarni yozasiz.- State o'zgarganda Motion qanday ishlashini va to'xtatilgan animatsiyani kuzatasiz.
- Tween va spring sozlamalarini, har xususiyat uchun alohida
transitionni yozasiz. - Keyframes massivi bilan "titrash" qilasiz va
MotionConfigbilan reduced-motion'ni ulaysiz.
Oldin bilishingiz kerak: UI animatsiya tamoyillari va performance, CSS animatsiyalari React'da, Web Animations API.
1. Nega bu kerak?
Oldingi darsda vazifalar dagi oyna, menyu va tooltip CSS bilan jonlandi. Endi ro'yxat qatorlari navbatda. Jasur aka: "yangi vazifa qo'shilganda ko'z uni darhol topsin".
Sardor CSS bilan urinib ko'rdi va to'rtta muammoga duch keldi:
- Qaysi qator "yangi"? Sahifa ochilganda 30 ta qator bor — ular animatsiyasiz chiqishi kerak. Faqat keyin qo'shilgani jonlansin. Bu ma'lumot React state'ida, CSS'da emas.
- Tez almashadigan holat. Almashtirgichni (switch) tez-tez bossangiz, CSS keyframe har safar boshidan boshlaydi.
- Qiymat JavaScript'da. Sudrash masofasi, ro'yxatdagi tartib — CSS ularni bilmaydi.
- Chiqish. React elementni o'chirganda animatsiyani kutish kerak — buni qo'lda yozdik va qiyin bo'ldi.
Motion bu ishlarni deklarativ qiladi: "qayerga" deysiz, "qanday" — kutubxonaning ishi. React'ning o'zi kabi: UI = f(state), animatsiya = f(state).
Hayotiy o'xshatish: taksi. Siz manzilni aytasiz — "Chorsu". Qaysi ko'chadan, qaysi tezlikda borishni haydovchi o'zi hal qiladi. Yo'lda manzilni "Amir Temur xiyoboni" ga o'zgartirsangiz, u to'xtab boshidan boshlamaydi — shu joydan burilib ketadi.
2. Paket: Framer Motion endi Motion
2.1 O'rnatish va import
Kutubxona uzoq vaqt Framer Motion nomi bilan tanilgan (Framer — dizayn vositasi kompaniyasi). Keyin u mustaqil loyiha bo'ldi va Motion nomini oldi. Yangi paket — motion:
npm i -E motion@14.0.0import { motion } from "motion/react"; // ✅ hozirgi yo'l
import { motion } from "framer-motion"; // eski kodda uchratasizframer-motion paketi ham hali chiqadi. motion aynan uning ustiga qurilgan: npm ls qilsangiz, motion@14.0.0 ostida framer-motion@14.0.0 ni ko'rasiz. API bir xil. Eski loyihani ko'chirish — importni motion/react ga almashtirish. Ikkala paketni bir loyihada aralashtirmang: kod ikki marta to'planadi.
motion paketida React'siz qism ham bor: import { animate } from "motion" — oddiy JavaScript'da DOM elementini animatsiya qilish uchun. Bu darsda faqat React qismi.
2.2 Saytdagi natija oynasida
motion va motion/react natija oynasida ishlaydi — har misolni «Ishga tushir» bilan ko'ring. Bir farqni yodda tuting. Kurs tekshiruvchisi brauzersiz muhitda ishlaydi: u yerda Motion animatsiyani vaqt bo'yicha JavaScript bilan hisoblaydi. Biz natijani yakuniy holat (Ekranda:) va Motion hodisalari (onAnimationStart, onAnimationComplete) bilan ko'rsatamiz. Harakatning o'zini natija oynasida ko'rasiz.
3. Birinchi animatsiya: initial va animate
3.1 motion.div
Har HTML va SVG tegining motion. versiyasi bor: motion.div, motion.li, motion.button, motion.svg. Ular oddiy teg kabi ishlaydi — barcha props'lar, ref, hodisalar. Qo'shimchasiga animatsiya props'larini qabul qiladi:
import { useRef } from "react";
import { motion } from "motion/react";
export default function App() {
const ref = useRef(null);
return (
<motion.div
ref={ref}
initial={{ opacity: 0, x: -20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.3 }}
onAnimationStart={() => console.log("boshlandi")}
onAnimationComplete={(target) => {
console.log("tugadi:", JSON.stringify(target));
console.log("style:", ref.current.style.cssText);
}}
>
Yangi buyurtma: osh
</motion.div>
);
}Konsolda:
boshlandi
tugadi: {"opacity":1,"x":0}
style: opacity: 1; transform: none;Ekranda:
Yangi buyurtma: oshNatija oynasida yozuv chapdan siljib, so'nib paydo bo'ladi. Qatorma-qator:
initial— birinchi chizilishdagi qiymatlar. Elementopacity: 0va 20 px chapda paydo bo'ladi.animate— maqsad. Motion darhol shu qiymatlarga olib boradi.transition— qanday: 0.3 soniya. Motion'da vaqt soniyada, CSS'dagidek millisekundda emas.onAnimationComplete— tugaganda; argumenti — erishilgan maqsad (animatedagi obyekt).
Oxirgi qatorga qarang: x: 0 DOM'da transform: none bo'ldi. x — Motion'ning alohida transform qiymati: Motion uni transform: translateX(...) ga yig'adi va nolga yetganda tozalaydi. Xuddi shunday y, scale, scaleX, rotate. Ularni alohida-alohida animatsiya qilish mumkin — CSS'dagi bitta transform satri bilan bu qiyin.
3.2 initial={false}
initial yozilmasa, Motion boshlang'ich qiymatni elementning hozirgi uslubidan oladi. initial={false} esa "birinchi chizilishda animatsiya qilma, darhol animate dagi qiymatda bo'l" degani. Sahifa ochilganda allaqachon bor narsalar uchun aynan shu kerak: ular "uchib kirmasin", faqat keyingi o'zgarishlar jonlansin.
Tekshirib ko'ring:
transition={{ duration: 300 }}yozilsa, nima bo'ladi?
Javob
Animatsiya 300 soniya — 5 daqiqa davom etadi. Element deyarli qimirlamaydi va "animatsiya ishlamayapti" degan taassurot qoladi. Motion'da duration va delay soniyada: 300 ms → 0.3. CSS'dan kelganlarning eng ko'p uchraydigan xatosi.
4. State o'zgarganda
4.1 animate — state'dan
animate ichidagi qiymat state'ga bog'liq bo'lsa, state o'zgarganda Motion eski qiymatdan yangisiga o'tadi. Almashtirgich (switch) misolida tugmani tez ikki marta bosamiz — ikkinchi bosish birinchi animatsiyani yarim yo'lda to'xtatadi:
import { useState } from "react";
import { motion } from "motion/react";
export default function App() {
const [on, setOn] = useState(false);
return (
<div>
<button
role="switch"
aria-checked={on}
onClick={() => setOn(!on)}
>
{on ? "O'chirish" : "Yoqish"}
</button>
<motion.div
initial={false}
animate={{ x: on ? 24 : 0 }}
onAnimationStart={() => console.log("boshlandi, on =", on)}
onAnimationComplete={(target) =>
console.log("tugadi:", JSON.stringify(target))
}
style={{ width: 24, height: 24, background: "#1d4ed8" }}
/>
</div>
);
}Konsolda:
boshlandi, on = true
boshlandi, on = false
tugadi: {"x":0}Uchta narsaga qarang:
- Ikkita "boshlandi", bitta "tugadi". Birinchi animatsiya (
x: 24ga) yo'lda to'xtatildi. UningonAnimationCompletei chaqirilmadi. Faqat oxirgi maqsadga yetgani tugadi. - Sakrash yo'q. Ikkinchi animatsiya
x = 0dan emas, quti hozir turgan joydan boshlandi. Joriy tezlik ham saqlandi — chunkixuchun Motion sukut bo'yicha spring ishlatadi (UI animatsiya tamoyillari darsidagi "to'xtatish" afzalligi). initial={false}— sahifa ochilganda quti joyida edi, "boshlandi" faqat bosishdan keyin keldi.
role="switch" va aria-checked — Malika uchun: "almashtirgich, yoqilgan". Animatsiya faqat ko'rinish, holat esa ARIA'da.
4.2 Har render yangi animatsiya emas
Motion animate dagi qiymatlarni oldingisi bilan solishtiradi. Qiymat o'zgarmagan bo'lsa (masalan, boshqa sabab bilan qayta render), animatsiya boshlanmaydi. Shuning uchun animate={{ opacity: 1 }} ni har renderda yangi obyekt qilib yozish xavfsiz.
5. transition: qanday borish
5.1 Tween
Tween — davomiylik va easing:
transition={{ duration: 0.2, ease: "easeOut" }}
// cubic-bezier:
transition={{ duration: 0.2, ease: [0.16, 1, 0.3, 1] }}
transition={{ duration: 0.2, delay: 0.1 }}Easing nomlari CSS'dan biroz farq qiladi: "linear", "easeIn", "easeOut", "easeInOut" (camelCase), yana "circOut", "backOut", "anticipate". Massiv — CSS'dagi cubic-bezier ning to'rt soni.
5.2 Spring
Spring — prujina. Ikki xil sozlanadi:
// 1) Fizika bilan: qattiqlik, so'ndirish, massa
transition={{ type: "spring", stiffness: 300, damping: 20 }}
// 2) Ko'z bilan: ko'rinadigan davomiylik va "sakrash"
transition={{ type: "spring", visualDuration: 0.3, bounce: 0.25 }}Ikkinchi shakl tushunarliroq: visualDuration — element maqsadga birinchi marta yetguncha bo'lgan vaqt. bounce — 0 (sakrashsiz) dan 1 gacha. Prujinaning "tebranishi" visualDuration dan keyin ham biroz davom etadi — lekin ko'z uchun animatsiya o'sha vaqtda tugagan bo'ladi.
Sukut bo'yicha nima? type yozilmasa, Motion qiymatga qarab tanlaydi. x, y, scale, rotate kabi "jismoniy" qiymatlar uchun — spring. opacity va ranglar uchun — tween (0.3 s). Shuning uchun almashtirgich misoli transition siz ham "tirik" harakatlandi.
5.3 Har xususiyatga alohida
Ko'pincha x prujina bilan, opacity esa qisqa tween bilan kerak bo'ladi:
import { useRef } from "react";
import { motion } from "motion/react";
export default function App() {
const ref = useRef(null);
return (
<motion.div
ref={ref}
initial={{ opacity: 0, scale: 0.5 }}
animate={{ opacity: 1, scale: 1 }}
transition={{
default: { type: "spring", visualDuration: 0.3, bounce: 0.3 },
opacity: { duration: 0.15, ease: "easeOut" },
}}
onAnimationComplete={() =>
console.log("style:", ref.current.style.cssText)
}
>
Savatga qo'shildi
</motion.div>
);
}Konsolda:
style: opacity: 1; transform: none;default — hamma boshqa qiymatlar uchun (bu yerda scale). opacity — o'zining 0.15 s lik tween'i. Yozuv tez paydo bo'ladi va bir oz "sakrab" o'z o'lchamiga keladi.
transition ni animate ichiga ham yozish mumkin: animate={{ x: 0, transition: { duration: 0.2 } }} — faqat shu maqsad uchun.
5.4 Takrorlash
// Yuklanish belgisi: abadiy aylanadi
<motion.div
animate={{ rotate: 360 }}
transition={{ repeat: Infinity, duration: 1, ease: "linear" }}
/>repeat — necha marta (Infinity — abadiy), repeatType: "reverse" — borib-qaytib. Abadiy animatsiyani faqat yuklanish kabi vaqtinchalik holatlarda ishlating — doimiy harakat diqqatni o'g'irlaydi.
Tekshirib ko'ring: Dizayner "tugma bosilganda bir oz kattalashib qaytsin, lekin sakramasin" dedi. Qaysi
transitionni tanlaysiz?
Javob
{ type: "spring", visualDuration: 0.2, bounce: 0 } — prujina, lekin sakrashsiz: tez boradi va yumshoq to'xtaydi. Yoki tween: { duration: 0.15, ease: "easeOut" }. Bosish tez-tez takrorlansa, spring yaxshiroq: keyingi bosish oldingisini "to'xtatsa", harakat sinmaydi.
6. Keyframes massivi
6.1 Bir nechta nuqta orqali
animate dagi qiymat massiv bo'lsa — bu keyframes: Motion qiymatni shu nuqtalar orqali olib o'tadi. Noto'g'ri PIN kiritilganda xabar chapga-o'ngga titraydi:
import { useState } from "react";
import { motion } from "motion/react";
export default function App() {
const [attempt, setAttempt] = useState(0);
return (
<div>
<button onClick={() => setAttempt(attempt + 1)}>Kirish</button>
{attempt > 0 && (
<motion.p
key={attempt}
role="alert"
animate={{ x: [0, -8, 8, -8, 0] }}
transition={{ duration: 0.4 }}
onAnimationComplete={(target) =>
console.log("titradi:", JSON.stringify(target))
}
>
PIN noto'g'ri ({attempt}-urinish)
</motion.p>
)}
</div>
);
}Konsolda:
titradi: {"x":[0,-8,8,-8,0]}
titradi: {"x":[0,-8,8,-8,0]}Ekranda:
Kirish
PIN noto'g'ri (2-urinish)Har urinishda key o'zgaradi — xabar yangidan yasaladi va titrash qaytadan boshlanadi (CSS animatsiyalari React'da darsidagi key usuli). Massivdagi 5 nuqta 0.4 s ga teng taqsimlandi.
6.2 times va null
times— har nuqta qachon kelishi (0 dan 1 gacha):transition={{ duration: 1, times: [0, 0.2, 1] }}— ikkinchi nuqtaga vaqtning 20% ida.null— "hozirgi qiymat":animate={{ x: [null, 100, 0] }}— qayerda bo'lsa, o'sha joydan boshlaydi.
Keyframes sukut bo'yicha tween (0.8 s — bir nechta nuqta bo'lsa). Prujina faqat ikki nuqta orasida ishlaydi.
7. Qanday tez ishlaydi
7.1 Kompozitor va JavaScript kadrlari
Motion ichida ikki yo'l bor (manba: motion-dom 14.0.0 kodi, supportsBrowserAnimation):
opacity,transform(butun satr),filter,clipPath,backgroundColor— imkon bo'lsa, brauzerning Web Animations API'siga (WAAPI) topshiriladi. Animatsiya kompozitorda ishlaydi: asosiy oqim band bo'lsa ham silliq.x,y,scale,rotate(alohida transform'lar) va boshqalar — Motion o'zi har kadrda hisoblaydi vastyle.transformga yozadi. Bu asosiy oqimda ishlaydi, lekin baribir faqattransform— layout yo'q.
WAAPI'ga topshirish o'chadigan holatlar ham bor: masalan onUpdate callback'i berilsa (har kadrda qiymat kerak — WAAPI uni bera olmaydi).
Amaliy xulosa: animatsiya UI animatsiya tamoyillari darsidagi qoidaga mos bo'lsa (opacity va transform), Motion uni tez qiladi. width, height, top ni Motion ham layout'siz animatsiya qila olmaydi. Bunday o'zgarish uchun layout props'i bor — Motion III darsida.
7.2 React render'siz
Animatsiya paytida Motion komponentingizni qayta render qilmaydi. Qiymatlar React state'ida emas, Motion ichidagi "motion value" larda. Biz o'tgan darslarda ref bilan qo'lda qilgan ish shu: React — "qayerga", Motion — har kadr.
8. prefers-reduced-motion: MotionConfig
Motion o'zi reduced-motion'ni bilmaydi — siz aytishingiz kerak. Eng oson yo'l — ilovaning tepasida MotionConfig:
import { MotionConfig } from "motion/react";
<MotionConfig reducedMotion="user">
<App />
</MotionConfig>reducedMotion="user" — "foydalanuvchining tizim sozlamasiga qara". Harakatni kamaytirish yoqilgan bo'lsa, transform animatsiyalari (x, y, scale, rotate) o'chadi — element darhol maqsadda bo'ladi. opacity va rang esa qoladi — UI animatsiya tamoyillari darsidagi "harakatni olib tashla, ma'noni qoldir" qoidasi o'zi bajariladi. Boshqa qiymatlar: "always" (doim kamaytir — sinash uchun qulay), "never".
MotionConfig ga umumiy transition ham berish mumkin: <MotionConfig transition={{ duration: 0.2 }}> — ichidagi hamma motion komponentlar uchun sukut.
Komponentning o'zida tekshirish kerak bo'lsa — useReducedMotion() hook'i bor. Uni Motion IV darsida, kanon kodida ko'ramiz.
9. O'z komponentingiz: motion.create
motion. faqat HTML/SVG teglari uchun. O'z Tugma komponentingizni jonlantirmoqchi bo'lsangiz:
import { motion } from "motion/react";
import { Tugma } from "@/ui/Tugma.tsx";
const MotionTugma = motion.create(Tugma);
<MotionTugma whileTap={{ scale: 0.97 }}>Saqlash</MotionTugma>Shart — Radix'dagi asChild kabi: Tugma ref va qolgan props'ni <button> ga yoyishi kerak. Motion animatsiyani ref orqali haqiqiy DOM elementiga qo'llaydi. Eski kodda motion(Tugma) yozuvini ko'rasiz — bu motion.create ning eski shakli.
10. Narx: Motion qancha turadi
Kanon kutubxonalar tajribasida (natijalar/tajriba/kutubxonalar.txt, bir xil kichik ro'yxat):
- to'liq motion.* (layout bilan)40,4 KB
- LazyMotion + m (sinxron)27,1 KB
- vazifalar: birinchi yuklash+14.5 KB keyin14,2 KB
Manba: Kanon o'lchovi: tajriba/kutubxonalar.txt va QADAMLAR #23–#26 (Chrome 155, 2026-10-14)
Grafikda nimaga qarang: to'liq motion.* +40.4 KB — React Flow'dan sal kam. Kanon uni ikki bo'lakka bo'ldi: sahifa ochilganda faqat 14.2 KB, animatsiya "yadrosi" (14.5 KB) esa birinchi chizishdan keyin alohida fayl bo'lib keladi. Bu LazyMotion va m komponentlari bilan qilinadi — Motion IV darsida batafsil. CSP: 0 buzilish — Motion uslubni style xususiyatlari orqali beradi.
Va INP: UI animatsiya tamoyillari darsidagi o'lchovda qatorlardagi Motion katak bosishga taxminan +8 ms qo'shgan edi. Har qatorga motion.li qo'yishdan oldin o'ylang.
11. Vazifalar qadami: yangi qator jonlanadi (holat 25 boshlanadi)
11.1 Reja
Jasur akaning talabi: yangi vazifa qo'shilganda u ko'zga tashlansin. Kanon qarorlari:
- Faqat kirish — yangi qator yuqoridan 8 px tushib, so'nib paydo bo'ladi. 150 ms,
easeOut, faqatopacityvay. - Faqat ochilgandan keyin qo'shilgan qator. Sahifa ochilganda bor qatorlar jim turadi.
- Chiqish — Motion emas. O'chirilayotgan qator brauzerning WAAPI'si bilan chiqadi (Motion III darsida — nega
AnimatePresenceemas, o'lchov bilan). - Reduced-motion — umuman animatsiyasiz,
opacityham.
git switch -c feat/motion
npm i -E motion@14.0.011.2 qator-harakati.ts: kirish sozlamasi
Yangi fayl src/ui/qator-harakati.ts (kanon, holat 25; kirish qismi):
// qator-harakati.ts — ro'yxat qatorlari animatsiyasi (20/#23–#26).
// Faqat opacity va transform — kompozitor, layout qayta hisoblanmaydi
// (20/#21 tamoyili). Davomiylik qisqa: 150 ms.
import { useReducedMotion } from "motion/react";
import type { HTMLMotionProps } from "motion/react";
type QatorHarakati = Pick<
HTMLMotionProps<"li">,
"initial" | "animate" | "transition"
>;
/** @param yangi — ro'yxat ochilgandan KEYIN qo'shilgan qator */
export function useQatorHarakati(yangi: boolean): QatorHarakati {
// prefers-reduced-motion — animatsiyasiz (opacity ham)
const kamaytir = useReducedMotion() ?? false;
return {
initial: yangi && !kamaytir ? { opacity: 0, y: -8 } : false,
animate: { opacity: 1, y: 0 },
transition: { duration: 0.15, ease: "easeOut" },
};
}(Kanon fayli boshidagi izohning chiqish haqidagi qismi va chiqishAnimatsiyasi funksiyasi — Motion III darsida.)
Bugungi darsning hammasi shu 10 qatorda:
initial— yangi qator uchun{ opacity: 0, y: -8 }, qolganlar uchunfalse(animatsiyasiz, «initial={false}» bo'limidagidek).animate— doim bir xil maqsad. Qiymat o'zgarmagani uchun keyingi render'lar animatsiya boshlamaydi.transition— tween, 0.15 s,easeOut. Spring emas: qator to'xtatilmaydi, sakrash kerak emas.HTMLMotionProps<"li">— Motion'ningmotion.liprops turlari.Pickbilan faqat uchtasini oldik (Utility types darsidagiPick).useReducedMotion()—MotionConfigdan farqli: uopacityni ham o'chiradi (initial: false). Kanon bu yerda "hech qanday animatsiya" ni tanladi.
11.3 Qator.tsx va HarakatSozlamasi
Qator.tsx da to'liq ro'yxatdagi <li> endi m.li (kanon, holat 25):
+import * as m from "motion/react-m";
+import { useQatorHarakati } from "../ui/qator-harakati.ts";
...
+ const harakat = useQatorHarakati(yangi);
+ // 20/#25: to'liq ro'yxatda — m.li (yangi qator paydo bo'lishi);
+ // virtual ro'yxatda — oddiy li (aylantirishda chizilganlar
+ // animatsiyasiz)
+ if (joy === undefined) {
+ return (
+ <m.li
+ data-id={id}
+ className={bajarildi ? "bajarildi" : undefined}
+ {...harakat}
+ >
+ {children}
+ </m.li>
+ );
+ }m.li — motion.li ning "yengil" shakli: uning ichida animatsiya mexanizmi yo'q, mexanizm alohida yuklanadi. Hozircha m ni motion deb o'qing — farqi Motion IV darsida. Virtual ro'yxatda (virtualizatsiya) esa oddiy <li>: aylantirganda ekranga kirgan qatorlar "yangi" emas, ular jonlanmasligi kerak.
Butun ilova uchun sozlama — yangi src/ui/HarakatSozlamasi.tsx (kanon):
// HarakatSozlamasi.tsx — Motion sozlamasi (20/#23–#26): LazyMotion
// (yadro kerak bo'lganda) + MotionConfig. reducedMotion="user" —
// tizimda "harakatni kamaytirish" yoqilgan bo'lsa transform
// animatsiyalari o'chadi; opacity esa qoladi, shuning uchun qatorlar
// o'zi ham useReducedMotion'ga qaraydi
import { LazyMotion, MotionConfig } from "motion/react";
import type { ReactNode } from "react";
const yadro = () =>
import("./harakat-imkoniyatlari.ts").then((m) => m.default);
export function HarakatSozlamasi({
children,
}: {
children: ReactNode;
}) {
return (
// strict — to'liq motion.* ni LazyMotion ichida taqiqlaydi (u
// butun yadroni birinchi yuklashga qaytaradi: +26 KB gzip). Lekin
// tekshiruv faqat Node'da ishlaydi (Motion `typeof process` ga
// qaraydi): brauzerda — dev'da ham, build'da ham — JIM. Vitest'da
// ham ushlamaydi: testlar App'ni bu provider'siz chizadi. Haqiqiy
// himoya — lint (eslint.config.js: motion/react dan `motion`
// importi taqiqlangan)
<LazyMotion features={yadro} strict>
<MotionConfig reducedMotion="user">{children}</MotionConfig>
</LazyMotion>
);
}(Izoh qatorlari telefonga sig'ishi uchun qayta bo'lingan.) Bugun bizga MotionConfig reducedMotion="user" muhim — «MotionConfig» bo'limidagi sozlama. LazyMotion va yadro — Motion IV mavzusi. Qobiq.tsx butun sahifani shu komponentga o'raydi.
strict haqidagi izohga e'tibor bering. Nomi "qattiq tekshiruv" ga o'xshaydi, lekin brauzerda u hech narsa demaydi — kanon buni o'lchab ko'rdi. Shuning uchun haqiqiy himoya — lint qoidasi. Uni Motion IV da, holat 25 commit'idan oldin qo'shamiz.
Qaysi qator "yangi" ekanini kim aytadi (yangi props'i qayerdan keladi)? Bu keyingi darsda — u yerda ro'yxat darajasidagi qaror va nega "birin-ketin" (stagger) animatsiya qilmaganimiz.
11.4 Kanon tekshiruvlari
Holat 25 ning e2e ssenariysidagi (Chrome 155) shu darsga tegishli qatorlar:
✅ yangi qator: kirish animatsiyasi — faqat opacity va transform: true
✅ Motion: CSP buzilishi yo'q: []
✅ reduced-motion: qatorda animatsiya yo'q, o'chirilgan qator darhol yo'q: [0,false]Ssenariy Chrome'da Element.prototype.animate ni (WAAPI) kuzatadi. Birinchi qator: yangi <li> ga brauzerga topshirilgan animatsiyalarda faqat opacity va transform bor. Uchinchisi: reduced-motion'da qatorlarga bitta ham shunday animatsiya topshirilmadi. Commit hali yo'q: holat 25 Motion darslarining oxirida bitta commit bo'ladi.
12. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
| animatsiya "ishlamaydi", element qimirlamaydi | duration: 300 — 5 daqiqa |
soniyada: 0.3 |
| sahifa ochilganda hamma narsa uchib kiradi | initial hamma elementda |
mavjudlariga initial={false} |
style={{ transform }} yo'qoldi |
Motion x/scale bilan transform ni o'zi yozadi |
style da ham x, scale ishlating |
motion(Tugma) animatsiya qilmaydi |
ref yoki props <button> ga yetmaydi |
{...rest} va ref; motion.create |
| bundle'da framer-motion ikki marta | framer-motion va motion importlari aralash |
hammasi motion/react dan |
| reduced-motion foydalanuvchida ham uchadi | MotionConfig yo'q |
reducedMotion="user" |
| sekin, qaltiraydi | width, height, top animatsiyasi |
scale, x, y yoki layout |
13. Mashqlar
Mashqlar kurs/mashqlar/20/23-motion-i/ da. Har yechimni «Ishga tushir» bilan sinang.
1-mashq (oson): props nomlari
Bo'sh joylarni to'ldiring:
- Birinchi chizilishdagi qiymat —
- Maqsad qiymatlar —
- 200 ms ni Motion'da yozish:
duration: - Sukut bo'yicha
xqanday animatsiya qilinadi:
Yechim
initial— boshlanish,animate— maqsad.duration: 0.2— Motion vaqti soniyada.x,scale,rotate— sukut bo'yicha spring;opacityva rang — tween.
2-mashq (o'rta): progress chizig'i — scaleX bilan
Buyurtma holati: «Qabul» → «Oshxona» → «Yo'lda» → «Yetkazildi». «Keyingi bosqich» tugmasi chiziqni 25% ga to'ldirsin.
- Chiziq
widthbilan emas,scaleXbilan to'lsin;originX: 0— chapdan. transition— tween, 0.3 s,easeOut.- Animatsiya tugaganda konsolga yetib kelgan qiymat chiqsin.
- Chiziq ostida bosqich nomi yozilsin. Chiziq
role="progressbar"vaaria-valuenowbilan.
Ishora: animate={{ scaleX: step / 4 }}. originX — Motion'da transform-origin ning x qismi, style ga yoziladi.
Yechim
import { useState } from "react";
import { motion } from "motion/react";
const steps = ["Qabul", "Oshxona", "Yo'lda", "Yetkazildi"];
export default function App() {
const [step, setStep] = useState(1);
return (
<div>
<div
role="progressbar"
aria-valuemin={0}
aria-valuemax={4}
aria-valuenow={step}
aria-label="Buyurtma holati"
style={{ height: 8, background: "#e8edfb" }}
>
<motion.div
initial={false}
animate={{ scaleX: step / 4 }}
transition={{ duration: 0.3, ease: "easeOut" }}
onAnimationComplete={(target) =>
console.log("yetdi:", target.scaleX)
}
style={{ height: 8, background: "#1d4ed8", originX: 0 }}
/>
</div>
<p>{steps[step - 1]}</p>
<button
onClick={() => setStep((s) => Math.min(4, s + 1))}
disabled={step === 4}
>
Keyingi bosqich
</button>
</div>
);
}Konsolda:
yetdi: 0.5
yetdi: 0.75Ekranda:
Yo'lda
Keyingi bosqichinitial={false} — sahifa ochilganda chiziq allaqachon 25% da, animatsiyasiz. Har bosishda scaleX 0.25 ga oshadi va animatsiya o'sha nuqtadan boshlanadi. originX: 0 bo'lmasa, chiziq o'rtadan ikki tomonga o'sardi. disabled={step === 4} — oxirida tugma o'chadi.
3-mashq (qiyin): "Savatga qo'shildi" belgisi
Taom kartochkasidagi «Savatga» tugmasi bosilganda:
- Tugma yonida «+1» belgisi paydo bo'ladi: pastdan 10 px ko'tarilib, so'nib chiqadi (
opacityvay). - Keyin keyframes bilan bir marta "lip" etadi:
scale: [1, 1.2, 1]. - Har bosishda belgi qaytadan boshlanadi; ichida jami soni (
+1,+2…). - Belgi
aria-live="polite"hudud ichida: Malika "Savatda 2 ta" ni eshitsin. - Hamma narsa
MotionConfig reducedMotion="user"ichida.
Ishora: key={count}; initial={{ opacity: 0, y: 10, scale: 1 }}, animate={{ opacity: 1, y: 0, scale: [1, 1.2, 1] }}. Har qiymatga alohida transition: «Har xususiyatga alohida» bo'limi.
Yechim
import { useState } from "react";
import { MotionConfig, motion } from "motion/react";
export default function App() {
const [count, setCount] = useState(0);
return (
<MotionConfig reducedMotion="user">
<p>Osh — 35 000 so'm</p>
<button onClick={() => setCount(count + 1)}>
Savatga
</button>{" "}
<span aria-live="polite">
{count > 0 && (
<motion.span
key={count}
style={{ display: "inline-block" }}
initial={{ opacity: 0, y: 10, scale: 1 }}
animate={{ opacity: 1, y: 0, scale: [1, 1.2, 1] }}
transition={{
opacity: { duration: 0.15 },
y: { type: "spring", visualDuration: 0.2, bounce: 0 },
scale: { duration: 0.3, delay: 0.15 },
}}
onAnimationComplete={() => console.log("lip:", count)}
>
+{count} <span className="sr">(Savatda {count} ta)</span>
</motion.span>
)}
</span>
</MotionConfig>
);
}Konsolda:
lip: 1
lip: 2Ekranda:
Osh — 35 000 so'm
Savatga +2 (Savatda 2 ta)Uch qiymat — uch xil transition: opacity tez paydo bo'ladi, y sakrashsiz prujina bilan ko'tariladi, scale esa 0.15 s kutib (delay), keyin bir marta "lip" etadi. display: inline-block — span ga transform ta'sir qilishi uchun. Haqiqiy loyihada "(Savatda 2 ta)" qismi ko'zdan yashiriladi (sr-only sinfi, React'da accessibility), lekin ekran o'quvchi uni o'qiydi. Reduced-motion yoqilgan bo'lsa: y va scale o'chadi, belgi faqat so'nib paydo bo'ladi.
4-mashq: Vazifalar qadami
feat/motion branch'ida: motion@14.0.0 ni aniq versiya bilan o'rnating; src/ui/qator-harakati.ts — useQatorHarakati; src/ui/HarakatSozlamasi.tsx va Qobiq.tsx ni unga o'rash; Qator.tsx — to'liq ro'yxatda m.li. Commit qilmang.
Yechim
Tekshiruv ro'yxati:
package.jsonda"motion": "14.0.0"(^siz).- Vazifa qo'shing — yangi qator tepadan tushib so'nib chiqadi; sahifani yangilang — mavjud qatorlar jim.
- DevTools → Rendering →
prefers-reduced-motion: reduce— yangi qator darhol paydo bo'ladi. - Hamma joyda
m.*,motion.*emas — buni ko'z bilan tekshiring. Konsolga ishonmang:strictbrauzerda jim. Lint qoidasi Motion IV da qo'shiladi. npm run tip— 0 xato (HTMLMotionPropsturlari mos).
14. Real ishda
- Motion — React ekotizimidagi eng ko'p ishlatiladigan animatsiya kutubxonalaridan biri. Landing sahifalar, dashboard'lar, mobil-veb ilovalar. Intervyuda "Framer Motion bilan ishlaganmisiz?" ko'p so'raladi — endi to'g'ri javob: "ha, hozir u Motion,
motion/react". - Dizayn tizimlari —
transitionsozlamalari tokenlanadi (spring.snappy,duration.fast) vaMotionConfigorqali butun ilovaga beriladi. - Performans ko'rigi —
motion.*qayerlarda ishlatilgani va bundle hajmi. Har qatorgamotion.li— o'ylab qo'yiladigan qaror. - Intervyu savollari: "
initial,animate,transitionnima?", "spring va tween qachon?", "Motion qaysi qiymatlarni GPU'da animatsiya qiladi?", "reduced-motion'ni Motion'da qanday hurmat qilasiz?".
Xulosa
- Paket —
motion, import —motion/react(framer-motion— eski nom, API bir xil). motion.div:initial→animate,transitionbilan.initial={false}— birinchi chizilishda animatsiyasiz.animatestate'dan: qiymat o'zgarsa — joriy holatdan yangi maqsadga; to'xtatilgan animatsiyaningonAnimationCompletei chaqirilmaydi.transition: vaqt soniyada; tween (duration,ease) yoki spring (visualDuration,bounce/stiffness,damping); har qiymatga alohida —default.- Keyframes — massiv;
times,null. Qayta boshlash —key. MotionConfig reducedMotion="user"— transform o'chadi,opacityqoladi. Narx: to'liq +40.4 KB; kanonda 14.2 + 14.5 (keyin).
Keyingi dars: Motion II: variants, stagger va gestures — nomlangan holatlar, ota-bola orkestratsiyasi, whileHover, whileTap va sudrash; vazifalar da qaysi qator "yangi" ekanini hal qilamiz.
Manbalar
- Motion for React: Get started, Animation, Transitions, MotionConfig — motion.dev/docs/react (motion 14.0.0)
- Motion: Upgrade guide (
framer-motion→motion) — motion.dev/docs/react-upgrade-guide motion-dom14.0.0 manba kodi:supportsBrowserAnimation(WAAPI'ga topshiriladigan qiymatlar)- MDN: Web Animations API — developer.mozilla.org/docs/Web/API/Web_Animations_API
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!