مقدمة إلى GSAP

GSAP (GreenSock Animation Platform) هي مكتبة جافاسكريبت قوية للتحريك تمكنك من التحكم الدقيق في الرسوم المتحركة على الويب. تم تطويرها بواسطة شركة GreenSock، وتتميز بالأداء العالي والمرونة وسهولة الاستخدام.

تم تصميم GSAP للتغلب على قيود التحريك القياسية باستخدام CSS و JavaScript الأصلي، مما يوفر للمطورين وسيلة متسقة وبسيطة لإنشاء تحريكات سلسة وتفاعلية.

يمكن لـ GSAP تحريك أي خاصية لأي كائن JavaScript تقريبًا - ليس فقط خصائص CSS والأنماط. يعمل مع SVG وCanvas و React و Vue وعناصر DOM القياسية والعديد من التقنيات الأخرى.

لماذا GSAP؟

أداء عالي

محسّنة لأقصى سرعة، حتى في المشاريع الكبيرة مع مئات التحريكات المتزامنة.

توافق واسع

تعمل بشكل موثوق في جميع المتصفحات الحديثة دون حلول بديلة معقدة.

مرونة غير محدودة

يمكنها تحريك أي خاصية لأي كائن، مع تحكم دقيق في التوقيت والمنحنيات.

مثال بسيط

إليك مثال بسيط للتحريك باستخدام GSAP:

// تحريك مربع من اليمين إلى اليسار مع تغيير اللون
gsap.to(".box", {
    x: 100,             // تحريك 100 بكسل للأمام على المحور X
    rotation: 360,      // دوران كامل (360 درجة)
    backgroundColor: "purple",  // تغيير اللون إلى الأرجواني
    duration: 2,        // تستغرق الحركة ثانيتين
    ease: "bounce.out"  // تأثير الارتداد عند النهاية
});

التثبيت والإعداد

هناك عدة طرق لإضافة GSAP إلى مشروعك. في ما يلي الطرق الأكثر شيوعًا:

1. استخدام CDN

الطريقة الأسرع والأسهل هي استخدام CDN. ما عليك سوى إضافة وسم script في رأس صفحتك:

<!-- GSAP Core -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>

<!-- Plugins (اختياري) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/MotionPathPlugin.min.js"></script>

2. التثبيت باستخدام npm

لمشاريع Node.js، يمكنك استخدام npm:

npm install gsap

ثم استيراده في ملفاتك:

// استيراد GSAP بالكامل
import gsap from "gsap";

// استيراد الوحدات المساعدة
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

// تسجيل الوحدات المساعدة
gsap.registerPlugin(ScrollTrigger);

3. تنزيل الملفات

يمكنك أيضًا تنزيل ملفات GSAP مباشرة من موقع GreenSock الرسمي وتضمينها في مشروعك.

ملاحظة مهمة حول الترخيص

النسخة الأساسية من GSAP مجانية للاستخدام في المشاريع التجارية وغير التجارية. ومع ذلك، توفر بعض الوحدات المساعدة المتقدمة مثل MorphSVG و DrawSVG فقط للمشتركين المدفوعين في نادي "Club GreenSock". تحقق من صفحة الترخيص للحصول على تفاصيل كاملة.

المفاهيم الأساسية

قبل الغوص في التفاصيل، من المهم فهم بعض المفاهيم الأساسية في GSAP:

Tweens وTimelines

Tween: هي تحريك فردي من قيمة إلى أخرى. على سبيل المثال، تحريك مربع من اليسار إلى اليمين.

Timeline: هي حاوية لتنظيم مجموعة من Tweens بترتيب زمني محدد. تتيح لك Timelines إنشاء تسلسلات معقدة من التحريكات.

الخصائص المدعومة

يمكن لـ GSAP تحريك:

  • خصائص CSS (width, height, opacity, etc.)
  • خصائص التحويل (x, y, rotation, scale, etc.)
  • خصائص SVG
  • المتغيرات العددية في الكائنات العادية
  • الألوان وخصائص الظل
  • الخصائص المخصصة من خلال وحدات خارجية

أنماط التحريك

  • to() - التحريك إلى قيم محددة
  • from() - التحريك من قيم محددة
  • fromTo() - تحديد قيم البداية والنهاية
  • set() - تعيين قيم فوري بدون تحريك

يمكن استخدام هذه الأنماط مباشرة من كائن GSAP أو داخل timeline.

نصيحة: عند العمل مع CSS transforms، GSAP يوفر خصائص مختصرة مثل x و y و rotation بدلاً من استخدام transform مباشرة. هذا يجعل الشفرة أكثر إيجازًا ويحسن الأداء.

Tweens

الـ Tween (اختصار لـ in-betweening) هي الوحدة الأساسية للتحريك في GSAP. تعني حرفيًا "الحركة بين نقطتين" - النقطة الأولى والنقطة الأخيرة. دعنا نستكشف طرق إنشاء Tweens المختلفة.

gsap.to()

gsap.to() يحرك العناصر إلى القيم المحددة، بدءًا من حالتها الحالية. هذه هي الطريقة الأكثر استخدامًا لإنشاء التحريكات.

// الصيغة الأساسية
gsap.to(target, {vars});

// أمثلة عملية
// تحريك عنصر بمعرف "box" لمسافة 200 بكسل إلى اليمين
gsap.to("#box", {x: 200, duration: 1});

// تحريك جميع العناصر ذات الصنف "circle" بخصائص متعددة
gsap.to(".circle", {
    y: 50,                   // تحريك 50 بكسل للأسفل
    scale: 1.5,              // تكبير بمقدار 1.5x
    opacity: 0.7,            // تعتيم قليلاً
    duration: 2,             // مدة التحريك ثانيتين
    ease: "power2.inOut"     // دالة التسهيل
});

المعاملات:

المعامل الوصف
target العنصر أو العناصر المستهدفة للتحريك. يمكن أن يكون:
  • سلسلة محدد CSS مثل ".box" أو "#element"
  • عنصر DOM مثل document.querySelector(".box")
  • مصفوفة من العناصر
  • NodeList
  • كائن JavaScript عادي
{vars} كائن يحتوي على:
  • الخصائص المراد تحريكها: مثل x، opacity، rotation إلخ.
  • خصائص التحكم: مثل duration، delay، ease، onComplete إلخ.

gsap.from()

gsap.from() يحرك العناصر من القيم المحددة إلى حالتها الحالية. هذا مفيد للتأثيرات عند دخول العناصر.

// الصيغة الأساسية
gsap.from(target, {vars});

// أمثلة
// تحريك مربع إلى موقعه الحالي من موقع بعيد على اليسار
gsap.from("#box", {x: -200, duration: 1});

// تأثير ظهور مع عدة خصائص
gsap.from(".panel", {
    y: 100,                // يبدأ من 100 بكسل للأسفل
    opacity: 0,            // يبدأ غير مرئي
    scale: 0.8,            // يبدأ بحجم أصغر
    duration: 1.5,
    stagger: 0.2,          // تأخير 0.2 ثانية بين كل عنصر
    ease: "back.out(1.7)"  // تأثير ارتداد للخلف
});

ملاحظة: بعد اكتمال التحريك، تعود العناصر إلى حالتها الأصلية (ما كانت عليه قبل بدء التحريك).

gsap.fromTo()

gsap.fromTo() يعطيك تحكمًا كاملاً من خلال تحديد كل من قيم البداية والنهاية. هذا مفيد عندما تحتاج إلى تحديد تحريك بشكل دقيق.

// الصيغة الأساسية
gsap.fromTo(target, {fromVars}, {toVars});

// مثال - تحريك عنصر من الشفاف في الأعلى إلى المرئي في الموقع الحالي
gsap.fromTo(".card", 
    {                      // قيم البداية
        y: -50,
        opacity: 0
    }, 
    {                      // قيم النهاية والإعدادات
        y: 0,
        opacity: 1,
        duration: 1,
        ease: "power1.out"
    }
);

ملاحظة مهمة: مع fromTo()، يجب تضمين جميع خيارات التحكم (مثل duration و ease) في كائن toVars (الكائن الثاني) وليس في كائن fromVars.

gsap.set()

gsap.set() يقوم بتعيين قيم على الفور بدون أي تحريك. يمكن استخدامه لتعيين القيم الأولية قبل بدء التحريك.

// الصيغة الأساسية
gsap.set(target, {vars});

// أمثلة
// تعيين موضع أولي
gsap.set(".box", {x: 100, opacity: 0});

// إعادة تعيين العناصر إلى حالة معينة قبل تحريكها
gsap.set(".item", {clearProps: "all"}); // يزيل جميع التحويلات والتنسيقات المطبقة بواسطة GSAP

استخدام مهم: gsap.set() مفيد بشكل خاص لتهيئة العناصر قبل بدء التحريكات الأخرى. على سبيل المثال، يمكنك إخفاء عناصر باستخدام gsap.set(".element", {opacity: 0}) ثم إظهارها لاحقًا باستخدام gsap.to().

خصائص التحريك الشائعة

فيما يلي بعض الخصائص الشائعة التي يمكنك استخدامها في تحريكات GSAP:

الخاصية الوصف مثال
x, y, z تحريك على المحور الأفقي (x)، العمودي (y)، أو العمق (z) x: 100, y: 50
rotation تدوير بالدرجات rotation: 360
rotationX, rotationY تدوير حول محور محدد rotationX: 180
scale تكبير/تصغير (1 = الحجم الطبيعي) scale: 1.5
scaleX, scaleY تكبير/تصغير على محور محدد scaleX: 2
opacity الشفافية (0 = شفاف، 1 = معتم) opacity: 0.5
backgroundColor لون الخلفية backgroundColor: "#f00"
width, height العرض والارتفاع width: "100px"
autoAlpha يجمع بين الشفافية وvisibility (0 = مخفي تمامًا) autoAlpha: 0

Timelines

Timelines هي أحد أقوى ميزات GSAP، حيث تسمح لك بجمع عدة تحريكات معًا وتنسيقها بسهولة. يمكنك التفكير في Timeline كحاوية لـ Tweens المختلفة، مرتبة في تسلسل زمني.

أساسيات Timeline

إنشاء Timeline بسيط:

// إنشاء timeline جديد
const tl = gsap.timeline();

// إضافة tweens إلى timeline
tl.to(".box1", {x: 100, duration: 1})
.to(".box2", {y: 50, duration: 0.5})
.to(".box3", {rotation: 360, duration: 1.5});
                    

في المثال أعلاه، سيتم تحريك .box1 أولاً، وبمجرد الانتهاء سيبدأ تحريك .box2، ثم .box3. هذا يختلف عن استدعاء gsap.to() مباشرة، حيث ستبدأ جميع التحريكات في نفس الوقت.

خيارات إنشاء Timeline

const tl = gsap.timeline({
defaults: {duration: 1, ease: "power2.inOut"}, // الإعدادات الافتراضية لجميع التحريكات في هذا الـ timeline
paused: true,    // ابدأ بحالة متوقفة
repeat: 2,       // كرر الـ timeline مرتين (3 مرات إجمالاً)
yoyo: true,      // اعكس التحريك في كل تكرار
onComplete: function() {
    console.log("timeline completed!");
}
});

التحكم في Timeline

يمكنك التحكم في التشغيل والإيقاف والرجوع وغيرها من العمليات على Timeline:

const tl = gsap.timeline({paused: true});
tl.to(".box", {x: 100, duration: 1})
.to(".box", {y: 50, duration: 1});

// التحكم في التشغيل
tl.play();        // تشغيل
tl.pause();       // إيقاف مؤقت
tl.reverse();     // عكس الاتجاه
tl.restart();     // إعادة التشغيل من البداية
tl.seek(1.5);     // الانتقال إلى وقت محدد (بالثواني)
tl.progress(0.5); // الانتقال إلى نقطة محددة (0-1)
tl.timeScale(2);  // زيادة سرعة التشغيل

معلمات الموضع في Timeline

إحدى أقوى ميزات Timelines هي القدرة على التحكم الدقيق في توقيت وتداخل التحريكات:

const tl = gsap.timeline();

// التتابع الافتراضي: يبدأ التحريك بعد انتهاء التحريك السابق
tl.to(".box1", {x: 100, duration: 1})

// يبدأ بعد 0.5 ثانية من بدء التحريك السابق
.to(".box2", {y: 50, duration: 1}, "-=0.5")

// يبدأ في نفس وقت بدء التحريك السابق
.to(".box3", {rotation: 360, duration: 1}, "<")

// يبدأ بعد 0.2 ثانية من بدء التحريك السابق
.to(".box4", {scale: 1.5, duration: 1}, "<0.2")

// يبدأ في وقت محدد منذ بداية Timeline (2 ثانية)
.to(".box5", {opacity: 0.5, duration: 1}, 2)

// يبدأ بعد نهاية جميع التحريكات السابقة
.to(".box6", {x: -100, duration: 1}, ">");

معلمات الموضع

المعلمة الوصف
"" (سلسلة فارغة) الافتراضي - يبدأ بعد انتهاء التحريك السابق
"+=0.5" يبدأ بعد 0.5 ثانية من نهاية التحريك السابق
"-=0.5" يبدأ قبل نهاية التحريك السابق بـ 0.5 ثانية
"<" يبدأ في نفس وقت بدء التحريك السابق
">" يبدأ بعد نهاية جميع التحريكات السابقة
2 (رقم) يبدأ في وقت محدد منذ بداية Timeline
"myLabel" يبدأ عند علامة مرجعية محددة (يمكن إضافتها باستخدام tl.addLabel("myLabel"))

نصيحة احترافية: استخدام العلامات المرجعية (Labels) هو طريقة رائعة لتنظيم Timeline معقدة. يمكنك إضافة علامة مرجعية باستخدام tl.addLabel("myLabel", position) ثم الإشارة إليها في التحريكات اللاحقة.

Timelines المتداخلة

يمكنك أيضًا دمج timeline داخل timeline أخرى، مما يسمح بإنشاء تحريكات معقدة ومنظمة بشكل جيد:

// timeline فرعية
const headerTL = gsap.timeline();
headerTL.from(".logo", {y: -50, opacity: 0, duration: 1})
    .from(".nav-item", {y: -20, opacity: 0, stagger: 0.1, duration: 0.5}, "-=0.5");

// timeline رئيسية
const mainTL = gsap.timeline();
mainTL.to(".curtain", {y: "-100%", duration: 1})
  .add(headerTL) // إضافة timeline فرعية
  .from(".content", {opacity: 0, duration: 1}, "-=0.5");

دوال التسهيل (Easing)

دوال التسهيل (Easing) تحدد المعدل الذي يتغير به التحريك عبر الزمن. بدلاً من التغير الخطي، يمكن أن تبدأ التحريكات ببطء ثم تتسارع، أو تبدأ سريعًا ثم تتباطأ، أو مزيج من ذلك.

أنواع دوال التسهيل الأساسية

  • "none" - تغير خطي، بمعدل ثابت
  • "power1", "power2", "power3", "power4" - قوة تدريجية
  • "back" - تجاوز قليل ثم عودة
  • "elastic" - تأثير ارتداد مرن
  • "bounce" - تأثير ارتداد وانعكاس
  • "circ", "expo", "sine" - تدرجات استنادًا إلى دوال رياضية

اتجاهات دوال التسهيل

  • ".in" - تتسارع من البداية (تبدأ ببطء)
  • ".out" - تتباطأ عند النهاية (تنتهي ببطء)
  • ".inOut" - تجمع بين in وout (تبدأ وتنتهي ببطء)

أمثلة: "power2.out", "back.inOut", "elastic.in"

// أمثلة لاستخدام دوال التسهيل المختلفة
gsap.to(".box1", {x: 200, duration: 2, ease: "none"});        // خطي
gsap.to(".box2", {x: 200, duration: 2, ease: "power2.out"});  // تتباطأ عند النهاية
gsap.to(".box3", {x: 200, duration: 2, ease: "back.out(1.7)"});  // تتجاوز الهدف قليلاً ثم تعود
gsap.to(".box4", {x: 200, duration: 2, ease: "elastic.out(1, 0.3)"});  // تأثير مرن
gsap.to(".box5", {x: 200, duration: 2, ease: "bounce.out"});  // تأثير ارتداد

// Custom ease باستخدام وحدة CustomEase (تتطلب تسجيل CustomEase plugin)
// gsap.to(".box6", {x: 200, duration: 2, ease: CustomEase.create("custom", "M0,0 C0.126,0.382 0.282,0.674 0.44,0.822 0.632,1.002 0.818,1.001 1,1")});

Power2.out

Elastic.out

Back.out

Bounce.out

استدعاءات الإرجاع (Callbacks)

توفر GSAP عدة طرق لتنفيذ دوال في نقاط محددة أثناء التحريك. هذه مفيدة للغاية عندما تحتاج إلى تزامن الشفرة مع الرسوم المتحركة.

gsap.to(".box", {
x: 200,
duration: 2,
onStart: function() {
    console.log("بدأ التحريك!");
},
onUpdate: function() {
    console.log("تحديث التحريك...");
},
onComplete: function() {
    console.log("اكتمل التحريك!");
},
onRepeat: function() {
    console.log("تكرار التحريك!");
}
});

استدعاءات الإرجاع المتاحة

الاستدعاء الوصف
onStart يتم استدعاؤه عند بدء التحريك لأول مرة
onUpdate يتم استدعاؤه في كل إطار أثناء التحريك
onComplete يتم استدعاؤه عند اكتمال التحريك (بما في ذلك جميع التكرارات)
onRepeat يتم استدعاؤه في كل مرة يتكرر فيها التحريك
onReverseComplete يتم استدعاؤه عند اكتمال التحريك في الاتجاه المعاكس

معلمات الاستدعاء

تمرر GSAP أيضًا معلمات إلى دوال الاستدعاء التي يمكن أن تكون مفيدة:

gsap.to(".box", {
x: 200,
duration: 2,
onUpdate: function() {
    // هذا يشير إلى tween نفسه
    console.log("التقدم: " + this.progress()); // قيمة بين 0 و 1
},
onComplete: function() {
    console.log("اكتمل التحريك!");
    // يمكنك الوصول إلى المستهدف
    console.log(this.targets());
}
});

سياق this: في دوال الاستدعاء، يشير this إلى كائن التحريك (tween) نفسه، وليس إلى العنصر المستهدف. يمكنك استخدام this.targets() للوصول إلى الأهداف.

التحريك المتدرج (Staggers)

تسمح خاصية stagger بتحريك مجموعة من العناصر بتأخير بينها، مما ينتج تأثيرًا متتاليًا متدرجًا. هذه طريقة رائعة لتحريك مجموعات من العناصر مثل عناصر القائمة أو الشبكات.

// تحريك متدرج بسيط - تأخير 0.2 ثانية بين كل عنصر
gsap.to(".box", {
y: 100,
opacity: 1,
duration: 1,
stagger: 0.2 // كل عنصر يبدأ بعد 0.2 ثانية من العنصر السابق
});

// خيارات متقدمة للتحريك المتدرج
gsap.from(".grid-item", {
y: 100,
opacity: 0,
duration: 1,
stagger: {
    amount: 1,        // الوقت الإجمالي للتدرج (توزيع التأخير على إجمالي هذا الوقت)
    from: "center",   // نقطة البداية (يمكن أن تكون: "start", "end", "center", "edges" أو رقم)
    grid: [3, 5],     // إذا كانت العناصر في شبكة [أعمدة, صفوف]
    ease: "power2.inOut"  // دالة تسهيل للتأخير نفسه
}
});

خيارات التدرج

الخاصية الوصف
amount إجمالي الوقت بالثواني لتوزيع جميع التأخيرات (بدلاً من تحديد التأخير لكل عنصر)
from من أين يبدأ التدرج:
  • "start" (الافتراضي) - من البداية
  • "end" - من النهاية
  • "center" - من الوسط
  • "edges" - من الأطراف إلى الوسط
  • index - رقم المؤشر المحدد
grid مصفوفة [أعمدة, صفوف] لإنشاء تدرج ثنائي الأبعاد. مفيد للشبكات.
ease دالة تسهيل للتدرج نفسه (كيف يتوزع التأخير)
axis عند استخدام grid، حدد المحور: "x" أو "y"

التحكم في التحريكات

تقدم GSAP مجموعة شاملة من الطرق للتحكم في التحريكات بعد إنشائها. يمكنك تشغيل، إيقاف، إيقاف مؤقت، عكس، وتغيير سرعة التحريكات.

// تخزين مرجع للتحريك
const myTween = gsap.to(".box", {
x: 200,
duration: 2,
paused: true // إنشاؤه متوقفًا
});

// التحكم في التشغيل
myTween.play();      // تشغيل
myTween.pause();     // إيقاف مؤقت
myTween.resume();    // استئناف بعد الإيقاف المؤقت
myTween.reverse();   // عكس الاتجاه
myTween.restart();   // إعادة التشغيل من البداية
myTween.seek(1);     // الانتقال إلى نقطة زمنية محددة (بالثواني)
myTween.progress(0.5); // الانتقال إلى نسبة معينة من التقدم (0-1)
myTween.timeScale(2);  // تحديد سرعة التشغيل (2 = ضعف السرعة)

// إيقاف وحذف
myTween.kill();      // إيقاف التحريك وتحريره من الذاكرة

// الحصول على معلومات التحريك
console.log(myTween.time());      // الوقت الحالي بالثواني
console.log(myTween.progress());  // نسبة التقدم (0-1)
console.log(myTween.duration());  // مدة التحريك
console.log(myTween.totalDuration()); // المدة الإجمالية (مع التكرار)
console.log(myTween.isActive());  // هل التحريك نشط حاليًا؟

إيقاف جميع التحريكات

يمكنك إيقاف جميع التحريكات باستخدام طرق عامة من GSAP:

// إيقاف جميع التحريكات
gsap.killAll();

// إيقاف تحريكات عناصر معينة
gsap.killTweensOf(".box");
gsap.killTweensOf(document.querySelector(".box"));

// إيقاف خصائص معينة فقط
gsap.killTweensOf(".box", "x,y");  // إيقاف فقط التحريكات التي تؤثر على x وy

ScrollTrigger

ScrollTrigger هي واحدة من أقوى الوحدات الإضافية في GSAP. تتيح لك ربط التحريكات بموضع التمرير، مما يسمح بإنشاء تأثيرات تستجيب للتمرير مثل تحريك التمرير (parallax)، تحريك العناصر عند الوصول إليها، وأكثر.

أساسيات ScrollTrigger

// التأكد من تسجيل ScrollTrigger
gsap.registerPlugin(ScrollTrigger);

// مثال بسيط: تشغيل تحريك عند التمرير إلى عنصر
gsap.to(".box", {
    x: 300,
    duration: 1,
    scrollTrigger: {
        trigger: ".box",    // العنصر الذي يطلق التحريك
        start: "top center", // متى يبدأ (أعلى العنصر يصل إلى وسط الشاشة)
        end: "bottom center", // متى ينتهي (أسفل العنصر يصل إلى وسط الشاشة)
        toggleActions: "play pause reverse reset", // الإجراءات عند (دخول، خروج، دخول مرة أخرى، خروج مرة أخرى)
        markers: true,      // عرض علامات للتوضيح (مفيد للتطوير)
    }
});

خصائص ScrollTrigger الرئيسية:

الخاصية الوصف أمثلة
trigger العنصر الذي يطلق التحريك ".box", myElement
start متى يبدأ التحريك، كنسبة أو وحدات بكسل من أعلى النافذة "top center", "top 80%", "50px 40%"
end متى ينتهي التحريك (للتحريكات تابعة لمدى التمرير) "bottom 20%", "+=300" (300 بكسل بعد start)
markers عرض علامات للتوضيح (لأغراض التطوير) true, false
scrub ربط التقدم بالتمرير (تحكم في التحريك بالتمرير) true, 1 (تأخير بالثواني)
pin تثبيت عنصر أثناء التمرير true, ".element"
toggleActions تحديد الإجراءات عند دخول/خروج المشغل "play pause reverse reset"

تقنيات متقدمة في ScrollTrigger

تأثير تمرير Scrub

الخاصية scrub تربط تقدم التحريك بموضع التمرير، مما يتيح تحكمًا دقيقًا في التحريك من خلال التمرير.

// تحريك مربط بالتمرير
gsap.to(".element", {
    x: 500,
    rotation: 360,
    duration: 1,
    scrollTrigger: {
        trigger: ".element",
        start: "top 80%",
        end: "top 20%",
        scrub: true,      // ربط خطي دقيق بالتمرير
        // scrub: 0.5,    // إضافة تأخير زمني (بالثواني) للحصول على تأثير أكثر سلاسة
        markers: true
    }
});

تثبيت العناصر (Pinning)

يمكنك تثبيت عناصر أثناء التمرير لإنشاء تأثيرات متقدمة:

// تثبيت عنصر أثناء التمرير
ScrollTrigger.create({
    trigger: ".panel",
    start: "top top", // عندما يصل أعلى العنصر إلى أعلى الشاشة
    end: "+=500",     // استمر في التثبيت لمسافة 500 بكسل من التمرير
    pin: true,        // تثبيت العنصر المحدد في trigger
    pinSpacing: true, // الاحتفاظ بمساحة العنصر في تدفق الصفحة بعد التثبيت
});

استخدام مع Timeline

يمكن دمج ScrollTrigger مع Timeline لإنشاء تسلسلات تحريك معقدة:

// إنشاء timeline مرتبطة بالتمرير
const tl = gsap.timeline({
    scrollTrigger: {
        trigger: ".container",
        start: "top center",
        end: "bottom center",
        scrub: 1,
        pin: true,
        markers: true
    }
});

// إضافة تحريكات إلى timeline
tl.to(".box1", {x: 200, duration: 1})
  .to(".box2", {y: 100, duration: 1})
  .to(".box3", {rotation: 360, scale: 1.5, duration: 1});

// سيتم تشغيل كل هذه التحريكات بالتتابع أثناء تمرير المنطقة المحددة

الأحداث والاستدعاءات

يمكنك الاستماع إلى أحداث ScrollTrigger:

ScrollTrigger.create({
    trigger: ".element",
    start: "top center",
    onEnter: () => console.log("دخول!"),
    onLeave: () => console.log("خروج!"),
    onEnterBack: () => console.log("دخول مرة أخرى!"),
    onLeaveBack: () => console.log("خروج مرة أخرى!")
});

الوحدات الإضافية الأخرى

بالإضافة إلى ScrollTrigger، توفر GSAP مجموعة من الوحدات الإضافية القوية لتوسيع وظائفها. بعض هذه الوحدات متاحة في الإصدار المجاني، والبعض الآخر يتطلب اشتراكًا في Club GreenSock.

وحدات إضافية مجانية

  • MotionPath

    تحريك العناصر على طول مسار معين، خاصة مسارات SVG.

    gsap.registerPlugin(MotionPathPlugin);
    gsap.to(".element", {
      motionPath: {
        path: "#path", // SVG path
        align: "#path",
        autoRotate: true
      },
      duration: 5
    });
  • TextPlugin

    تحريك محتوى النص، بما في ذلك تأثيرات الكتابة.

    gsap.registerPlugin(TextPlugin);
    gsap.to(".text", {
      duration: 2,
      text: "نص جديد تمامًا"
    });
  • EasePack

    دوال تسهيل إضافية للتحريكات.

وحدات إضافية لأعضاء Club GreenSock

  • MorphSVG

    تحويل شكل SVG بسلاسة إلى شكل آخر.

  • DrawSVG

    تحريك خطوط SVG كما لو كان يتم رسمها.

  • SplitText

    تقسيم النص إلى أحرف، كلمات، أو سطور لتحريكها بشكل فردي.

  • ScrambleText

    تأثير تبديل للنص بين قيمتين.

  • Physics2D

    تطبيق فيزياء واقعية على التحريكات.

نصيحة: تذكر أن تقوم دائمًا بتسجيل الوحدات الإضافية قبل استخدامها باستدعاء gsap.registerPlugin(PluginName). للوحدات المدفوعة، ستحتاج إلى الاشتراك في Club GreenSock.

تقنيات متقدمة

مع GSAP، يمكن تنفيذ تقنيات وأنماط متقدمة لإنشاء تحريكات معقدة وديناميكية.

أنماط متقدمة

تقنية الحالة البدائية (FLIP Technique)

تقنية FLIP (First, Last, Invert, Play) تسمح بتحريكات عالية الأداء بين حالتين مختلفتين للعناصر:

// مثال بسيط لتقنية FLIP
const element = document.querySelector(".box");
const state1 = { x: 0, y: 0 }; // الحالة الأولى
const state2 = { x: 200, y: 100 }; // الحالة الثانية

// تطبيق الحالة النهائية فورًا
gsap.set(element, state2);

// حساب الفرق وعكسه
const inverse = {
    x: state1.x - state2.x,
    y: state1.y - state2.y
};

// تطبيق العكس فورًا (سيعود العنصر إلى وضعه الأصلي)
gsap.set(element, { x: inverse.x, y: inverse.y });

// تحريك إلى الحالة النهائية (من 'صفر')
gsap.to(element, {
    x: 0,
    y: 0,
    duration: 1,
    ease: "power2.out"
});

الرسوم المتحركة المتزامنة مع الصوت

يمكنك مزامنة التحريكات مع الأصوات:

// إعداد الصوت
const sound = new Audio("sound.mp3");

// ابدأ التحريك مع الصوت
const tl = gsap.timeline({
    onStart: function() {
        sound.play();
    }
});

tl.to(".element1", { x: 100, duration: 1 })
  .to(".element2", { y: 50, duration: 0.5 })
  // يمكنك استخدام أوقات محددة لمزامنة مع أجزاء معينة من الصوت
  .to(".element3", { rotation: 360, duration: 1 }, 2.5);

تحريكات قائمة على البيانات

استخدام البيانات لإنشاء تحريكات ديناميكية:

// بيانات مثال
const data = [
    { id: 1, value: 50 },
    { id: 2, value: 120 },
    { id: 3, value: 80 },
    { id: 4, value: 200 }
];

// تحديث الرسم البياني باستخدام التحريك
function updateChart() {
    data.forEach((item, index) => {
        // تحريك كل عنصر إلى القيمة المقابلة
        gsap.to(`#bar-${item.id}`, {
            height: item.value,
            duration: 1,
            ease: "power1.out",
            delay: index * 0.1 // تأخير تدريجي
        });
    });
}

تحريك SVG المتقدم

GSAP ممتاز مع تحريكات SVG:

// تحريك عناصر SVG
gsap.timeline()
    .from("svg path", {
        drawSVG: 0,        // يتطلب وحدة DrawSVG (Club GreenSock)
        duration: 2,
        stagger: 0.1
    })
    .to("svg circle", {
        fill: "#ff0000",
        scale: 1.5,
        transformOrigin: "center center",
        duration: 1
    });

مشكلات شائعة وحلولها

على الرغم من أن GSAP سهلة الاستخدام نسبيًا، إلا أن هناك بعض المشكلات الشائعة التي قد تواجهها. إليك بعض الحلول:

مشكلة: التحريكات لا تعمل

الأسباب المحتملة:

  • لم يتم تحميل مكتبة GSAP
  • محدد العنصر غير صحيح
  • العنصر غير موجود في الصفحة عند تنفيذ التعليمات البرمجية

الحلول:

// تحقق مما إذا كان GSAP متاحًا
if (typeof gsap !== "undefined") {
    // GSAP متاح
}

// تأكد من وجود العنصر قبل التحريك
const element = document.querySelector(".my-element");
if (element) {
    gsap.to(element, {x: 100, duration: 1});
}

// انتظر حتى يكتمل تحميل الصفحة
document.addEventListener("DOMContentLoaded", function() {
    // الآن يمكنك تحريك العناصر بأمان
    gsap.from(".element", {opacity: 0, y: 50, duration: 1});
});

مشكلة: تحريك transform لا يعمل كما هو متوقع

غالبًا ما تتداخل خصائص transform مع بعضها البعض عند استخدام CSS المباشر.

الحل: استخدم الخصائص المختصرة في GSAP:

// بدلاً من
gsap.to(".element", {transform: "translateX(100px) rotate(45deg)"});

// استخدم هذا
gsap.to(".element", {x: 100, rotation: 45});

مشكلة: مشكلات في الأداء

إذا كانت التحريكات بطيئة أو متقطعة، جرب هذه الاستراتيجيات:

  • قلل عدد العناصر المتحركة في نفس الوقت
  • استخدم خصائص رخيصة حسابيًا مثل opacity و transform
  • تجنب تحريك width و height قدر الإمكان واستخدم scale بدلاً من ذلك
  • تجنب تحريك الخطوط العريضة في SVG إذا أمكن
// بدلاً من
gsap.to(".element", {width: 200, height: 200});

// استخدم هذا (أفضل للأداء)
gsap.to(".element", {scale: 2, transformOrigin: "top left"});

مشكلة: ScrollTrigger لا يعمل بشكل صحيح

المشكلات الشائعة مع ScrollTrigger وحلولها:

  • نسيان تسجيل الوحدة
  • تغير أبعاد الصفحة أثناء التمرير
  • مشكلات مع تغيير حجم النافذة
// تأكد من تسجيل الوحدة
gsap.registerPlugin(ScrollTrigger);

// إعادة تحديث ScrollTrigger عند تغيير حجم النافذة
window.addEventListener("resize", function() {
    ScrollTrigger.refresh();
});

// للمحتوى الديناميكي
ScrollTrigger.refresh(true); // تحديث جميع مشغلات ScrollTrigger

الخلاصة

GSAP هي مكتبة قوية وعالية الأداء ومرنة للتحريك في JavaScript، تمكنك من إنشاء تحريكات مذهلة ومعقدة بسهولة.

تعلمت في هذا التوثيق أساسيات GSAP، من Tweens البسيطة إلى Timelines المتقدمة، وكيفية استخدام ScrollTrigger وغيرها من الوحدات الإضافية.

للمزيد من المعلومات والأمثلة، يمكنك زيارة توثيق GSAP الرسمي ومنتديات المجتمع.