بعدها · فصل ٦

التلميع — حركة أقل، ومقاسات، وإزاي تبني نظام حركة

prefers-reduced-motion · reduced-motion class · motion tokens · durations
🎯 الهدف: تحترم اللي طالب حركة أقل زي Filee، وتطلع بنظام حركة صغير تستخدمه في أي مشروع.

حركة أقل: Filee بيسمع الكلام

ناس كتير بتدوخ من الحركة. ويندوز وماك ولينكس فيهم إعداد “قلّل الحركة”. Filee بيقرا الإعداد ده من النظام، وكمان حاطط زرار في صفحة الثيم لو عايز تغيّره بإيدك.

اللي بيعمله بسيط: كلاس واحد على الشباك اسمه reduced-motion، وكل الـ transitions بتتشال لما يكون موجود:

Styles/Soft.axaml (Filee)
<Style Selector="Window.reduced-motion :is(Button),                 Window.reduced-motion :is(ToggleButton),                 Window.reduced-motion Border.chip,                 Window.reduced-motion ListBoxItem">  <Setter Property="Transitions" Value="{x:Null}" /></Style>

والدونت؟ في الـ loop بتاعه بيسأل Motion.Enabled. لو الحركة مقفولة، بيحط كل القيم على هدفها علطول ومفيش spring:

if (!Motion.Enabled){    for (var i = 0; i < _hover.Length; i++)    {        _hover[i].Value = i == ActiveIndex ? 1 : 0;        _hover[i].Velocity = 0;    }    Array.Fill(_open, _closing ? 0 : 1);}

على الويب

@media (prefers-reduced-motion: reduce) {  *, *::before, *::after {    transition-duration: 0.01ms !important;    animation-duration: 0.01ms !important;    transition-delay: 0s !important;  }}
const reduce = matchMedia("(prefers-reduced-motion: reduce)").matches;if (reduce) {  spring.value = target; // روح للهدف علطول  spring.velocity = 0;}

نظام حركة صغير تاخده معاك

لو جمعت كل اللي في Filee، هتلاقي إنه بيستخدم ٣ منحنيات و حوالي ٥ مدد بس. حطهم في مكان واحد:

motion.css
:root {  /* المنحنيات */  --ease-back: cubic-bezier(0.34, 1.56, 0.64, 1); /* حاجة صغيرة بتتداس أو تظهر */  --ease-out: cubic-bezier(0.33, 1, 0.68, 1);     /* حاجة كبيرة: صفحة، لوحة */  --ease-in: cubic-bezier(0.32, 0, 0.67, 0);      /* القفل */  /* المدد (من أرقام Filee) */  --dur-color: 0.15s;  /* ألوان وظلال */  --dur-press: 0.22s;  /* زراير */  --dur-hover: 0.25s;  /* chips و sidebar */  --dur-page: 0.28s;   /* صفحة */  --dur-pop: 0.35s;    /* toast و dialog */  --dur-close: 0.16s;  /* أي قفل */  --stagger: 28ms;}
الحاجةالمنحنىالمدةالحركة
زرار اتداس--ease-back--dur-pressscale(0.95)
hover على chip--ease-back--dur-hoverscale(1.05)
hover في sidebar--ease-back--dur-hovertranslateX(3px)
لون أو ظل(عادي)--dur-colorلون
toast أو dialog بيظهر--ease-back--dur-popopacity + زحلقة أو scale
صفحة--ease-out--dur-pageopacity + 10px
أي حاجة بتقفل--ease-in--dur-closeعكس الفتح
حاجة بتتبع الماوسspring(ملهاش مدة)320 / 20

غلطات بتبوّظ الطراوة

الحركة تحسها تقيلةالمدة أطول من 400ms. قصّرها
الصفحة بتترقصBackEaseOut على حاجة كبيرة. استخدم CubicEaseOut
الأبلكيشن بيقطّعبتحرّك width أو top. حرّك transform
اللون بيرمشBackEaseOut على لون. الألوان من غير نطة
القفل مستفزالقفل زي الفتح. خلّيه أسرع ومن غير نطة
الحركة بتقطع لما الماوس يتحرك بسرعةeasing بمدة ثابتة. استخدم spring
الـ spring بتطير على جهاز بطيءقسّم dt لخطوات أقصاها 1/120
CPU شغال والأبلكيشن واقفالـ loop مش بيقف. وقّفه لما كله يهدى

خلّصت الفصل لما

🧠 اختبر نفسك
١) Filee بيقفل الحركة إزاي؟
كلاس reduced-motion على الشباك بيشيل الـ Transitions، والدونت بيسأل Motion.Enabled ويحط القيم على هدفها علطول.
٢) إيه اللي يفضل شغال لما الحركة تتقفل؟
تغيير الألوان والحالة. اللي بيتشال هو التكبير والزحلقة والنطة.
٣) ليه نحط المدد والمنحنيات في متغيرات؟
عشان الأبلكيشن كله يتحرك بنفس الإحساس، ولو حبيت تغيّر حاجة تغيّرها في مكان واحد، زي SoftEase في Filee.