آکادمی بنو/آموزش CSS

Animation و Keyframes در CSS

بهنام نوبخت · ۱۴۰۵/۶/۲۸

در مقاله قبل با Transition آشنا شدیم و یاد گرفتیم چگونه تغییرات بین دو وضعیت، مانند حالت عادی و hover، را نرم و تدریجی کنیم.

اما Transition برای همه نیازهای ما کافی نیست.

فرض کنید بخواهیم یک دکمه:

  • به‌صورت خودکار حرکت کند،

  • چند مرحله مختلف داشته باشد،

  • چند بار تکرار شود،

  • به‌صورت بی‌نهایت اجرا شود،

  • در هر بار اجرا جهت خود را تغییر دهد،

  • یا بدون هیچ تعامل کاربر از ابتدا اجرا شود.

در چنین شرایطی CSS Animation ابزار مناسب‌تری است.

Animation به کمک keyframes اجازه می‌دهد مراحل مختلف یک حرکت را تعریف کنیم و سپس مشخص کنیم این Animation چه مدت اجرا شود، چند بار تکرار شود، با چه سرعتی حرکت کند و در پایان چه وضعیتی داشته باشد.

Animation در CSS چیست؟

Animation در CSS روشی برای تغییر تدریجی مقادیر CSS در طول زمان است.

تفاوت مهم آن با Transition این است که Animation می‌تواند یک توالی کامل از مراحل داشته باشد.

مثلاً:

شروع
 ↓
حرکت به راست
 ↓
بزرگ شدن
 ↓
چرخش
 ↓
کوچک شدن
 ↓
پایان

برای تعریف چنین مراحلی از keyframes استفاده می‌کنیم.

keyframes چیست؟

keyframes محل تعریف مراحل مختلف یک Animation است.

مثلاً:

@keyframes move-box {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(300px);
    }
}

در این مثال Animation دو مرحله دارد:

from → شروع
to   → پایان

from معادل 0% و to معادل 100% است. همچنین می‌توان به‌جای دو مرحله، درصدهای مختلفی مانند 25%، 50% و 75% تعریف کرد.

اجرای اولین Animation

فقط تعریف keyframes کافی نیست.

باید Animation را به یک عنصر متصل کنیم.

مثلاً:

.box {
    width: 100px;
    height: 100px;
    background-color: #f97316;

    animation-name: move-box;
    animation-duration: 2s;
}

@keyframes move-box {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(300px);
    }
}

در اینجا:

animation-name: move-box;

نام Animation را مشخص می‌کند.

و:

animation-duration: 2s;

مشخص می‌کند یک چرخه Animation دو ثانیه طول بکشد.

animation-name

ویژگی animation-name مشخص می‌کند کدام keyframes باید روی عنصر اجرا شود.

مثلاً:

.box {
    animation-name: move-box;
}

و:

@keyframes move-box {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(300px);
    }
}

نام باید با نام keyframes مطابقت داشته باشد.

مثلاً اگر بنویسیم:

animation-name: slide;

باید Animation زیر وجود داشته باشد:

@keyframes slide {
    ...
}

animation-duration

ویژگی animation-duration مدت زمان یک چرخه Animation را مشخص می‌کند.

مثلاً:

.box {
    animation-duration: 3s;
}

یعنی یک چرخه Animation سه ثانیه طول می‌کشد.

مثال:

.box {
    animation-name: move-box;
    animation-duration: 1s;
}

یا:

.box {
    animation-name: move-box;
    animation-duration: 500ms;
}

Animation چندمرحله‌ای

قدرت اصلی keyframes زمانی مشخص می‌شود که بیش از دو مرحله داشته باشیم.

مثلاً:

@keyframes move-box {
    0% {
        transform: translateX(0);
    }

    50% {
        transform: translateX(200px);
    }

    100% {
        transform: translateX(400px);
    }
}

در اینجا Animation سه مرحله دارد:

0%   → شروع
50%  → وسط
100% → پایان

این یعنی می‌توانیم رفتار عنصر را در نقاط مختلف Animation کنترل کنیم.

استفاده از درصدها

می‌توانیم مراحل بیشتری تعریف کنیم:

@keyframes example {
    0% {
        transform: translateX(0);
    }

    25% {
        transform: translateX(100px);
    }

    50% {
        transform: translateX(200px);
    }

    75% {
        transform: translateX(100px);
    }

    100% {
        transform: translateX(0);
    }
}

حالا عنصر:

0%
 ↓
25%
 ↓
50%
 ↓
75%
 ↓
100%

حرکت می‌کند.

این یکی از مهم‌ترین تفاوت‌های Animation و Transition است.

ساخت Animation با from و to

برای Animationهای ساده می‌توان از:

from
to

استفاده کرد.

مثلاً:

@keyframes fade-in {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

و:

.box {
    animation: fade-in 1s ease;
}

این روش برای Animationهای ساده و دو مرحله‌ای بسیار خوانا است.

Animation برای ظاهر شدن عنصر

یکی از کاربردهای بسیار رایج:

@keyframes fade-up {
    from {
        opacity: 0;
        transform: translateY(30px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

سپس:

.hero-content {
    animation: fade-up 0.8s ease-out;
}

نتیجه:

عنصر ابتدا:
شفاف + کمی پایین‌تر

        ↓

عنصر در پایان:
نمایان + در جای اصلی

این نوع Animation در Landing Pageها بسیار رایج است.

animation-timing-function

این ویژگی تعیین می‌کند Animation در طول زمان با چه منحنی سرعتی پیش برود.

مقادیر رایج:

linear
ease
ease-in
ease-out
ease-in-out

مثلاً:

.box {
    animation:
        move-box 2s ease-in-out;
}

linear

animation-timing-function: linear;

سرعت تقریباً ثابت است.

ease

animation-timing-function: ease;

حرکت در ابتدا و انتها نرم‌تر است.

ease-in

animation-timing-function: ease-in;

Animation آرام‌تر شروع می‌شود.

ease-out

animation-timing-function: ease-out;

Animation در پایان آرام‌تر می‌شود.

ease-in-out

animation-timing-function: ease-in-out;

شروع و پایان نرم‌تر هستند.

animation-delay

گاهی نمی‌خواهیم Animation بلافاصله شروع شود.

برای این کار از animation-delay استفاده می‌کنیم.

.box {
    animation-name: fade-in;
    animation-duration: 1s;
    animation-delay: 0.5s;
}

یعنی Animation پس از 0.5 ثانیه شروع می‌شود.

animation-iteration-count

این ویژگی مشخص می‌کند Animation چند بار اجرا شود. مقدار پیش‌فرض 1 است. همچنین می‌توان از infinite برای اجرای بی‌نهایت استفاده کرد.

مثلاً:

.box {
    animation-iteration-count: 3;
}

Animation سه بار اجرا می‌شود.

یا:

.box {
    animation-iteration-count: infinite;
}

Animation تا زمانی که عنصر در صفحه وجود داشته باشد، تکرار می‌شود.

Animation بی‌نهایت

مثلاً یک نقطه چشمک‌زن:

@keyframes blink {
    0% {
        opacity: 1;
    }

    50% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

.dot {
    animation: blink 1s ease-in-out infinite;
}

این Animation دائماً تکرار می‌شود.

برای مواردی مانند:

  • Loading

  • وضعیت آنلاین

  • اعلان‌ها

  • عناصر تزئینی

می‌تواند کاربرد داشته باشد.

animation-direction

ویژگی animation-direction مشخص می‌کند Animation در چه جهتی اجرا شود. حالت‌های اصلی آن عبارت‌اند از:

normal
reverse
alternate
alternate-reverse

normal

حالت پیش‌فرض:

animation-direction: normal;

Animation از ابتدا به انتها اجرا می‌شود.

0% → 100%

reverse

در این حالت Animation در جهت معکوس اجرا می‌شود:

animation-direction: reverse;
100% → 0%

alternate

یکی از کاربردی‌ترین حالت‌ها:

animation-direction: alternate;

اگر Animation چند بار تکرار شود:

→
←
→
←

مثلاً:

.box {
    animation:
        move-box 1s ease-in-out infinite alternate;
}

این روش برای حرکت رفت و برگشتی بسیار کاربردی است.

alternate-reverse

در این حالت اولین چرخه از جهت معکوس شروع می‌شود:

animation-direction: alternate-reverse;

ساخت Animation رفت و برگشتی

مثلاً یک توپ:

@keyframes bounce {
    from {
        transform: translateY(0);
    }

    to {
        transform: translateY(-80px);
    }
}

.ball {
    animation:
        bounce 0.7s ease-in-out infinite alternate;
}

نتیجه:

بالا
 ↓
پایین
 ↓
بالا
 ↓
پایین

بدون نیاز به تعریف چند Animation جداگانه.

animation-fill-mode

یکی از ویژگی‌های مهم Animation، animation-fill-mode است.

این ویژگی مشخص می‌کند استایل‌های Animation قبل از شروع و بعد از پایان چگونه روی عنصر اعمال شوند.

مقادیر مهم:

none
forwards
backwards
both

none

حالت پیش‌فرض است:

animation-fill-mode: none;

Animation قبل و بعد از اجرای خودش استایل‌های keyframe را حفظ نمی‌کند.

forwards

با:

animation-fill-mode: forwards;

عنصر پس از پایان Animation در وضعیت آخر Animation باقی می‌ماند.

مثلاً:

@keyframes fade-out {
    from {
        opacity: 1;
    }

    to {
        opacity: 0;
    }
}

.box {
    animation:
        fade-out 1s ease forwards;
}

پس از پایان Animation، عنصر در وضعیت opacity: 0 باقی می‌ماند.

backwards

با backwards، در زمان delay نیز استایل اولین Keyframe اعمال می‌شود.

.box {
    animation:
        fade-in 1s ease 1s backwards;
}

both

ترکیبی از forwards و backwards است:

animation-fill-mode: both;

یعنی رفتار هر دو حالت را در زمان مناسب اعمال می‌کند.

animation-play-state

این ویژگی برای کنترل وضعیت اجرای Animation استفاده می‌شود.

دو مقدار اصلی:

running
paused

مثلاً:

.box {
    animation: move-box 2s linear infinite;
}

.box:hover {
    animation-play-state: paused;
}

حالا Animation هنگام Hover متوقف می‌شود.

ساخت Loader با Animation

یکی از پروژه‌های کلاسیک CSS:

<div class="loader"></div>

CSS:

.loader {
    width: 50px;
    height: 50px;

    border: 5px solid #e5e7eb;
    border-top-color: #f97316;

    border-radius: 50%;

    animation: spin 0.8s linear infinite;
}

@keyframes spin {
    to {
        transform: rotate(360deg);
    }
}

در اینجا:

animation: spin 0.8s linear infinite;

یعنی:

  • Animation: spin

  • مدت: 0.8s

  • سرعت: linear

  • تکرار: بی‌نهایت

ساخت Pulse Effect

می‌توانیم یک عنصر را به‌صورت ضربانی نمایش دهیم.

@keyframes pulse {
    0% {
        transform: scale(1);
        opacity: 1;
    }

    50% {
        transform: scale(1.08);
        opacity: 0.7;
    }

    100% {
        transform: scale(1);
        opacity: 1;
    }
}

.pulse {
    animation: pulse 1.5s ease-in-out infinite;
}

این افکت برای:

  • دکمه‌های مهم

  • اعلان‌ها

  • وضعیت آنلاین

  • عناصر تبلیغاتی

قابل استفاده است.

البته نباید از چنین افکت‌هایی بیش از حد استفاده کرد.

ساخت Floating Animation

برای ایجاد حرکت آرام بالا و پایین:

@keyframes floating {
    0% {
        transform: translateY(0);
    }

    50% {
        transform: translateY(-12px);
    }

    100% {
        transform: translateY(0);
    }
}

.floating {
    animation: floating 3s ease-in-out infinite;
}

این افکت برای عناصر تزئینی Hero Section بسیار مناسب است.

ساخت انیمیشن چندمرحله‌ای

حالا یک Animation حرفه‌ای‌تر بسازیم.

@keyframes hero-card {
    0% {
        opacity: 0;
        transform: translateY(40px) scale(0.95);
    }

    50% {
        opacity: 0.7;
        transform: translateY(-10px) scale(1.02);
    }

    100% {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

و:

.hero-card {
    animation: hero-card 1s ease-out;
}

در این Animation چند ویژگی هم‌زمان تغییر می‌کنند:

opacity
transform
translateY
scale

این همان جایی است که قدرت واقعی keyframes مشخص می‌شود.

Animation Shorthand

مانند بسیاری از ویژگی‌های CSS، Animation نیز یک Shorthand دارد.

مثلاً:

animation-name: fade-up;
animation-duration: 0.8s;
animation-timing-function: ease-out;
animation-delay: 0.2s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: forwards;

می‌تواند به شکل کوتاه‌تر نوشته شود:

animation:
    fade-up
    0.8s
    ease-out
    0.2s
    1
    normal
    forwards;

یا در یک خط:

animation: fade-up 0.8s ease-out 0.2s 1 normal forwards;

ویژگی animation یک Shorthand برای مجموعه‌ای از ویژگی‌های Animation است.

در پروژه‌های واقعی معمولاً شکل کوتاه‌شده بسیار کاربردی‌تر است.

یک الگوی بسیار مهم برای پروژه‌ها

مثلاً:

.card {
    animation:
        fade-up 0.7s ease-out 0.2s both;
}

این خط را می‌توان به شکل زیر تحلیل کرد:

fade-up
   ↓
نام Animation

0.7s
   ↓
مدت Animation

ease-out
   ↓
نحوه سرعت

0.2s
   ↓
تأخیر

both
   ↓
Fill Mode

چند Animation روی یک عنصر

می‌توان چند Animation را روی یک عنصر اجرا کرد.

مثلاً:

.box {
    animation:
        move 2s ease-in-out infinite alternate,
        rotate 4s linear infinite;
}

هر Animation با کاما از Animation بعدی جدا می‌شود. CSS از چند Animation در یک declaration پشتیبانی می‌کند.

این قابلیت بسیار قدرتمند است، اما باید با دقت استفاده شود تا حرکت‌های مختلف با یکدیگر تداخل ایجاد نکنند.

Animation و Transform

یکی از بهترین ویژگی‌هایی که می‌توان همراه Animation استفاده کرد:

transform

مثلاً:

@keyframes rotate {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(360deg);
    }
}

و:

.icon {
    animation: rotate 2s linear infinite;
}

یا:

@keyframes float {
    0% {
        transform: translateY(0);
    }

    50% {
        transform: translateY(-15px);
    }

    100% {
        transform: translateY(0);
    }
}

این ترکیب برای UI مدرن بسیار پرکاربرد است.

ساخت Hero Section با Animation

فرض کنید یک Hero Section داریم:

<section class="hero">

    <div class="hero-content">
        <span class="hero-badge">
            راهکارهای دیجیتال
        </span>

        <h1>
            زیرساخت دیجیتال
            کسب‌وکار شما
        </h1>

        <p>
            مجموعه‌ای از محصولات و خدمات مدرن
            برای رشد کسب‌وکار شما.
        </p>

        <a href="#" class="hero-button">
            مشاهده خدمات
        </a>
    </div>

</section>

حالا Animation:

@keyframes hero-content {
    from {
        opacity: 0;
        transform: translateY(30px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.hero-content {
    animation:
        hero-content 0.8s ease-out both;
}

حالا می‌توانیم عناصر را با تأخیرهای مختلف وارد کنیم.

.hero-badge {
    animation:
        hero-content 0.6s ease-out 0.1s both;
}

.hero h1 {
    animation:
        hero-content 0.7s ease-out 0.2s both;
}

.hero p {
    animation:
        hero-content 0.7s ease-out 0.35s both;
}

.hero-button {
    animation:
        hero-content 0.7s ease-out 0.5s both;
}

در نتیجه عناصر به‌صورت مرحله‌ای ظاهر می‌شوند:

Badge
  ↓
Title
  ↓
Description
  ↓
Button

این تکنیک را می‌توان برای ایجاد ورود تدریجی محتوا استفاده کرد.

Animation و Hover

Animation را می‌توان هنگام hover نیز فعال کرد.

مثلاً:

@keyframes shake {
    0% {
        transform: translateX(0);
    }

    25% {
        transform: translateX(-5px);
    }

    50% {
        transform: translateX(5px);
    }

    75% {
        transform: translateX(-5px);
    }

    100% {
        transform: translateX(0);
    }
}

.button:hover {
    animation: shake 0.4s ease;
}

با این حال، برای تغییرات ساده hover معمولاً Transition انتخاب ساده‌تری است.

Animation زمانی ارزش بیشتری پیدا می‌کند که به چند مرحله مختلف نیاز داشته باشیم.

تفاوت Transition و Animation

حالا تفاوت این دو را دقیق‌تر ببینیم.

ویژگی

Transition

Animation

نیاز به تغییر State

معمولاً بله

خیر

@keyframes

ندارد

دارد

چند مرحله

محدود به ابتدا و انتها

بسیار مناسب

اجرای خودکار

معمولاً خیر

بله

تکرار بی‌نهایت

مناسب نیست

بله

کنترل جهت

محدود

کامل‌تر

Delay

دارد

دارد

Loop

ندارد

دارد

مناسب Hover

بسیار مناسب

مناسب برای موارد خاص

یک قانون ساده:

اگر تغییر بین دو وضعیت دارید، ابتدا به Transition فکر کنید.

اگر یک توالی چندمرحله‌ای یا Animation مستقل دارید، از Animation و @keyframes استفاده کنید.

Animation و Accessibility

Animation جذاب است، اما نباید فراموش کنیم که همه کاربران تجربه یکسانی از حرکت ندارند.

برای کاربرانی که سیستم خود را روی کاهش حرکت تنظیم کرده‌اند، می‌توان Animation را کاهش داد یا حذف کرد.

مثلاً:

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

هدف این است که Motion غیرضروری کاهش پیدا کند.

در طراحی حرفه‌ای، Animation باید در خدمت تجربه کاربری باشد، نه اینکه تجربه کاربر را مختل کند.

اشتباهات رایج در Animation

۱. Animation بیش از حد

اگر تمام عناصر صفحه دائماً حرکت کنند:

عنوان
دکمه
کارت
تصویر
منو
آیکون
پس‌زمینه

صفحه می‌تواند بسیار شلوغ و آزاردهنده شود.

Animation باید هدف مشخصی داشته باشد.

۲. استفاده از Animation بسیار طولانی

مثلاً:

animation: fade-in 10s ease;

برای یک ورود ساده معمولاً بیش از حد طولانی است.

۳. استفاده بی‌دلیل از infinite

این کد:

animation: pulse 1s infinite;

تا زمانی که عنصر وجود دارد اجرا می‌شود.

اگر تعداد زیادی عنصر چنین Animationای داشته باشند، صفحه دائماً در حال حرکت خواهد بود.

پس infinite را فقط زمانی استفاده کنید که تکرار مداوم واقعاً بخشی از طراحی باشد.

۴. فراموش کردن animation-name

اگر فقط بنویسیم:

.box {
    animation-duration: 2s;
}

Animationی اجرا نمی‌شود، چون مشخص نکرده‌ایم کدام @keyframes باید استفاده شود.

باید مثلاً داشته باشیم:

animation-name: fade-in;

یا:

animation: fade-in 2s ease;

۵. اشتباه گرفتن Duration و Delay

این دو متفاوت هستند:

animation-duration: 2s;

یعنی:

Animation چقدر طول بکشد؟

اما:

animation-delay: 2s;

یعنی:

Animation چه زمانی بعد شروع شود؟

۶. استفاده نامناسب از transform

اگر چند Animation هم‌زمان بخواهند transform را کنترل کنند، ممکن است نتیجه مورد انتظار ایجاد نشود.

مثلاً یک Animation:

transform: translateX(...);

و Animation دیگر:

transform: rotate(...);

می‌توانند با یکدیگر تداخل ایجاد کنند.

در چنین شرایطی باید ساختار Animationها را با دقت طراحی کنید.

پروژه عملی: Animated Service Card

حالا یک کارت خدمات واقعی طراحی کنیم.

HTML

<article class="service-card">

    <div class="service-icon">
        🚀
    </div>

    <h3>
        طراحی سایت
    </h3>

    <p>
        طراحی سایت مدرن، سریع و Responsive
        برای کسب‌وکارهای امروزی.
    </p>

    <a href="#">
        مشاهده خدمات ←
    </a>

</article>

CSS

.service-card {
    padding: 30px;

    background-color: #ffffff;

    border-radius: 20px;

    border: 1px solid #e5e7eb;

    box-shadow:
        0 10px 30px rgba(0, 0, 0, 0.06);

    animation:
        card-enter 0.8s ease-out both;
}

@keyframes card-enter {
    from {
        opacity: 0;
        transform:
            translateY(30px)
            scale(0.96);
    }

    to {
        opacity: 1;
        transform:
            translateY(0)
            scale(1);
    }
}

حالا آیکون را نیز متحرک کنیم:

.service-icon {
    display: inline-block;

    animation:
        icon-floating 2s ease-in-out infinite alternate;
}

@keyframes icon-floating {
    from {
        transform: translateY(0);
    }

    to {
        transform: translateY(-8px);
    }
}

در این مثال:

  • خود کارت هنگام ورود ظاهر می‌شود.

  • آیکون به‌صورت مداوم حرکت بسیار آرام دارد.

این نمونه‌ای از ترکیب چند نوع Animation در یک رابط کاربری است.

تمرین‌های مقاله

تمرین ۱ — Fade In

یک عنصر ایجاد کنید که از:

opacity: 0;

شروع شود و به:

opacity: 1;

برسد.

Animation باید یک ثانیه طول بکشد.

تمرین ۲ — حرکت از پایین

یک Animation بسازید که عنصر از:

transform: translateY(50px);
opacity: 0;

به:

transform: translateY(0);
opacity: 1;

برسد.

تمرین ۳ — چرخش

یک Loader بسازید که دائماً بچرخد.

از:

animation-iteration-count: infinite;

استفاده کنید.

تمرین ۴ — رفت و برگشت

یک عنصر بسازید که به سمت راست حرکت کند و دوباره به سمت چپ برگردد.

از این ترکیب کمک بگیرید:

animation-direction: alternate;
animation-iteration-count: infinite;

تمرین ۵ — Animation چندمرحله‌ای

یک Animation پنج مرحله‌ای بسازید:

0%
25%
50%
75%
100%

در هر مرحله مقدار transform را تغییر دهید.

جمع‌بندی

در این مقاله با سیستم Animation در CSS آشنا شدیم.

مهم‌ترین بخش Animation، @keyframes است. با استفاده از آن می‌توانیم مراحل مختلف یک حرکت را تعریف کنیم. from و to برای Animationهای ساده مناسب هستند و درصدهایی مانند 0%، 50% و 100% امکان ساخت Animationهای چندمرحله‌ای را فراهم می‌کنند.

سپس یاد گرفتیم Animation را با ویژگی‌هایی مانند:

animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
animation-fill-mode
animation-play-state

کنترل کنیم. این ویژگی‌ها در قالب Shorthand animation نیز قابل ترکیب هستند.

همچنین دیدیم که Animation می‌تواند برای ساخت:

  • Fade In

  • Slide In

  • Loader

  • Spinner

  • Pulse

  • Floating Effect

  • Hero Animation

  • کارت‌های متحرک

استفاده شود.

اما یک نکته مهم را همیشه به خاطر داشته باشید:

Animation خوب، انیمیشنی نیست که بیشترین حرکت را داشته باشد؛ انیمیشنی است که به درک بهتر رابط کاربری و تجربه بهتر کاربر کمک کند.

در مقاله بعدی وارد یکی دیگر از قابلیت‌های مهم CSS3 می‌شویم و با Filterها در CSS آشنا خواهیم شد؛ ویژگی‌هایی که به کمک آن‌ها می‌توان روی تصاویر و عناصر مختلف افکت‌هایی مانند Blur، Brightness، Contrast، Grayscale و دیگر جلوه‌های بصری ایجاد کرد.

۱۰

نظرات

کد در دسترس نیست

هنوز نظری ثبت نشده است.