تحريك مكونات React باستخدام GreenSock
نشرت: 2022-03-10خلال الأيام الأولى لشبكة الويب العالمية ، كانت الأمور ثابتة إلى حد ما ومملة. كانت صفحات الويب تعتمد في الغالب على التصميم الجرافيكي والتخطيطات من عالم الطباعة حتى يتم تقديم الرسوم المتحركة. يمكن للرسوم المتحركة أن تجذب انتباه الناس وتجذب انتباههم لفترة أطول من صفحة الويب الثابتة وتوصل فكرة أو مفهومًا بشكل أكثر وضوحًا وفعالية.
ومع ذلك ، في حالة عدم القيام بذلك بشكل صحيح ، يمكن أن تعيق الرسوم المتحركة تفاعلات المستخدم مع منتجك وتؤثر سلبًا على الجر. تعد GreenSock Animation Platform AKA (GSAP) مكتبة جافا سكريبت قوية تمكن مطوري الواجهة الأمامية ورسامي الرسوم المتحركة والمصممين من إنشاء رسوم متحركة فعالة قائمة على الخط الزمني. يسمح لعشاق الرسوم المتحركة بالتحكم الدقيق في تسلسلات الرسوم المتحركة الخاصة بهم بدلاً من keyframe
المقيدة أحيانًا وخصائص animation
التي توفرها CSS.
في هذه المقالة ، سأقدم لك بعض ميزات GSAP مثل scrollTriggers
و Timelines
و Easing
وما إلى ذلك ، في النهاية سنقوم ببناء واجهة مستخدم بديهية من خلال تحريك تطبيق React بهذه الميزات. تحقق من المشروع النهائي على كودو صندوق.
ستكون هذه المقالة مفيدة لك إذا:
- لقد قمت بإنشاء رسوم متحركة على تطبيقات الويب باستخدام HTML و CSS و JavaScript.
- أنت تقوم بالفعل بإنشاء صفحات ويب متحركة في تطبيقات React مع حزم مثل animate.css و React-motion و Framer-motion و React-Spring ، بالإضافة إلى أنك تريد التحقق من البدائل.
- أنت متحمس لـ React ، وترغب في إنشاء رسوم متحركة معقدة على تطبيقات الويب القائمة على React.
سننظر في كيفية إنشاء مجموعة متنوعة من الرسوم المتحركة من مشروع ويب موجود. دعنا نذهب اليها!
ملاحظة : تفترض هذه المقالة أنك مرتاح لاستخدام HTML و CSS و JavaScript و React.js.
ما هو GSAP؟
منصة GreenSock Animation Platform المعروفة أيضًا باسم GSAP عبارة عن رسوم متحركة فائقة الأداء وذات درجة احترافية للويب الحديث تسمح للمطورين بتحريك تطبيقاتهم بطريقة معيارية وتوضيحية وقابلة لإعادة الاستخدام. إنه غير محدد الإطار ويمكن استخدامه عبر أي مشروع قائم على JavaScript ، وله حجم حزمة ضئيل للغاية ولن يؤدي إلى تضخيم تطبيقك.
يمكن لـ GSAP تنفيذ رسوم متحركة للوحة ، تُستخدم لإنشاء تجارب WebGL ، وإنشاء رسوم متحركة SVG ديناميكية ودعم متصفح رائع.
لماذا نستخدم GSAP؟
ربما لم تكن مستعدًا تمامًا لخيانة الأطر الأخرى بعد ، أو لم تكن مقتنعًا باحتضان الأشياء الجيدة التي تأتي مع GSAP. اسمح لي أن أقدم لك بعض الأسباب التي تجعلك ترغب في التفكير في GSAP.
يمكنك إنشاء رسوم متحركة معقدة
تتيح مكتبة GSAP JavaScript للمطورين إنشاء رسوم متحركة بسيطة إلى معقدة للغاية قائمة على الفيزياء كما في حالة هذه المواقع ، فهي تتيح للمطورين والمصممين تسلسل الحركة والتحكم في الرسوم المتحركة ديناميكيًا. يحتوي على الكثير من المكونات الإضافية مثل DrawSVGPlugin و MorphSVGPlugin والمزيد ، مما يجعل إنشاء رسوم متحركة مبنية على SVG ورسوم متحركة ثنائية / ثلاثية الأبعاد حقيقة واقعة. إلى جانب دمج GSAP في عناصر DOM ، يمكنك استخدامها في الرسوم المتحركة المستندة إلى السياق WebGL / Canvas / Three.js.
علاوة على ذلك ، تعد سعة التخفيف لـ GSAP معقدة للغاية ، مما يجعل من الممكن إنشاء تأثيرات متقدمة باستخدام العديد من البيزر مقارنةً بالرسوم المتحركة العادية لـ CSS.
أداء
يتميز GSAP بأداء عالٍ مذهل عبر المتصفحات المختلفة.
وفقًا لفريق GSAP ، في موقعه على الويب ، "GSAP أسرع 20 مرة من jQuery ، بالإضافة إلى GSAP هي أسرع أداة رسوم متحركة مكتوبة كاملة الميزات على هذا الكوكب. بل إنه أسرع من الرسوم المتحركة والتحولات في CSS3 في كثير من الحالات ". تأكيد مقارنة السرعة لنفسك.
علاوة على ذلك ، تعمل رسوم GSAP المتحركة بسهولة على كل من أجهزة الكمبيوتر المكتبية والأجهزة اللوحية والهواتف الذكية. ليست هناك حاجة لإضافة قائمة طويلة من البادئات ، كل هذا يتم الاهتمام به تحت الغطاء بواسطة GSAP.
يمكنك التحقق من المزيد من الفوائد على GSAP أو الاطلاع على ما تقوله Sarah Drasner عنها هنا.
سلبيات GSAP
هل تقول أنه يجب علي دائمًا استخدام GSAP لكل مشروع؟ بالطبع لا! أشعر أن هناك سببًا واحدًا قد يجعلك لا ترغب في استخدام GSAP. هيا نكتشف!
- GSAP هي مكتبة رسوم متحركة تعتمد على JavaScript فقط ، ومن ثم فهي تتطلب بعض المعرفة بمعالجة JavaScript و DOM للاستفادة الفعالة من أساليبها وواجهات برمجة التطبيقات. يترك الجانب السلبي لمنحنى التعلم مجالًا أكبر للمضاعفات للمبتدئين الذين يبدأون باستخدام JavaScript.
- لا يلبي GSAP الرسوم المتحركة المستندة إلى CSS ، وبالتالي إذا كنت تبحث عن مكتبة لمثل هذا ، فيمكنك أيضًا استخدام
keyframes
في الرسوم المتحركة لـ CSS.
إذا كان لديك أي سبب آخر ، فلا تتردد في مشاركته في قسم التعليقات.
حسنًا ، الآن بعد أن تم حل شكوكك ، دعنا ننتقل إلى بعض التفاصيل الدقيقة في GSAP.
أساسيات GSAP
قبل إنشاء الرسوم المتحركة الخاصة بنا باستخدام React ، دعنا نتعرف على بعض الأساليب والكتل الأساسية لـ GSAP.
إذا كنت تعرف بالفعل أساسيات GSAP ، فيمكنك تخطي هذا القسم والانتقال مباشرةً إلى قسم المشروع ، حيث سنقوم بعمل انحراف في الصفحة المقصودة أثناء التمرير.
توين
توين هو حركة واحدة في الرسوم المتحركة. في GSAP ، يحتوي tween على البنية التالية:
TweenMax.method(element, duration, vars)
دعونا نلقي نظرة على ما يمثله هذا النحو ؛
- تشير
method
إلى طريقة GSAP التي ترغب في استخدامها. -
element
هو العنصر الذي تريد تحريكه. إذا كنت تريد إنشاء مراهقات لعناصر متعددة في نفس الوقت ، يمكنك تمرير مجموعة من العناصر إلىelement
. -
duration
هي مدة توينك. إنه عدد صحيح بالثواني (بدون اللاحقةs
!). -
vars
هو كائن من الخصائص التي تريد تحريكها. المزيد عن هذا لاحقًا.
طرق GSAP
يوفر GSAP طرقًا عديدة لإنشاء الرسوم المتحركة. في هذه المقالة ، نذكر القليل فقط مثل gsap.to
، gsap.from
، gsap.fromTo
. يمكنك التحقق من طرق أخرى رائعة في وثائقهم. سيتم استخدام الطرق التي تمت مناقشتها في هذا القسم في بناء مشروعنا لاحقًا في هذا البرنامج التعليمي.
-
gsap.to()
القيم التي يجب تحريك الكائن إليها ، مثل قيم خاصية النهاية لكائن متحرك - كما هو موضح أدناه:gsap.to('.ball', {x:250, duration: 5})
لإثبات طريقة to
، يوضح العرض التوضيحي لملف الشفرة أدناه أن عنصرًا بفئة كرة 250px
سيتحرك عبر x-axis
في خمس ثوانٍ عند تركيب المكونات. إذا لم يتم تحديد المدة ، فسيتم استخدام الافتراضي 500 مللي ثانية.
ملاحظة : يمثل المحور x
و y-axis
الأفقي والعمودي على التوالي ، وأيضًا في خصائص تحويل CSS مثل translateX
و translateY
يتم تمثيلهما على أنهما x
و y
للتحويلات pixel-measured
بالبكسل و xPercent
و yPercent
على النسبة المئوية.
لعرض مقتطف الكود الكامل ، تحقق من ملعب الرمز.
-
gsap.from()
- يحدد القيم التي يجب تحريك الكائن منها - على سبيل المثال ، قيم البداية للرسوم المتحركة:gsap.from('.square', {duration:3, scale: 4})
يُظهر العرض التوضيحي لـ codepen كيف يتم تغيير حجم عنصر بفئة square
من مقياس 4 في 3 3seconds
عند تركيب المكونات. تحقق من وجود مقتطف الشفرة الكامل في هذا الرمز.
-
gsap.fromTo()
- يتيح لك تحديد قيم البداية والنهاية للرسوم المتحركة. وهي عبارة عن مزيج من الطريقةfrom()
to()
.
هنا كيف يبدو.
gsap.fromTo('.ball',{opacity:0 }, {opacity: 1 , x: 200 , duration: 3 }); gsap.fromTo('.square', {opacity:0, x:200}, { opacity:1, x: 1 , duration: 3 });
هذا الرمز يحرك العنصر بفئة ball
من عتامة 0 إلى عتامة 1
عبر x-axis
في 3 seconds
ويتم تحريك فئة square
من عتامة من 0
إلى 1
في 3 seconds
عبر x-axis
فقط عندما يتصاعد المكون. لمعرفة كيفية عمل طريقة fromTo
الشفرة الكامل ، تحقق من العرض التوضيحي على CodePen أدناه.
ملاحظة : عندما نقوم بتحريك الخصائص الموضعية ، مثل left
top
، يجب أن نتأكد من أن العناصر المعنية يجب أن تحتوي على خاصية موضع CSS إما relative
أو absolute
أو fixed
.
التخفيف
حددت وثائق GSAP الرسمية التخفيف كطريقة أساسية لتغيير توقيت المراهقين. يحدد كيف يغير الكائن موضعه في نقاط مختلفة. يتحكم Ease في معدل تغيير الرسوم المتحركة في GSAP ويستخدم لتعيين نمط الرسوم المتحركة للكائن.
يوفر GSAP أنواعًا مختلفة من التسهيلات والخيارات لمنحك مزيدًا من التحكم في الطريقة التي يجب أن تتصرف بها الرسوم المتحركة. يوفر أيضًا Ease Visualizer لمساعدتك في اختيار إعدادات السهولة المفضلة لديك.
هناك ثلاثة أنواع من التسهيلات ، وهي تختلف في عملياتها.
-
in()
- تبدأ الحركة ببطء ، ثم تلتقط السرعة في نهاية الرسم المتحرك. -
out()
- يبدأ الرسم المتحرك بسرعة ثم يتباطأ في نهاية الرسم المتحرك. -
inOut()
- يبدأ الرسم المتحرك ببطء ، ويزيد من السرعة في منتصف الطريق وينتهي ببطء.
في مثال التخفيف هذا ، قمنا بتقييد المراهقات الذين عرضوا الأنواع الثلاثة من bounce.in
، و bounce.out
، و bounce.inOut
، وقمنا بتعيين تأخير لعدد الثواني التي تستغرقها الرسوم المتحركة لإكمالها قبل البدء في المرحلة التالية فقط عندما المكون يتصاعد. هذا النمط متكرر ، في القسم التالي سنرى كيف يمكننا استخدام جدول زمني للقيام بذلك بشكل أفضل.
الجداول الزمنية
يعمل الخط الزمني كحاوية للعديد من المراهقات. ينشط المراهقات بترتيب تسلسلي ، ولا يعتمد على مدة التوين السابقة. يجعل الجدول الزمني من السهل التحكم في المراهقات ككل وإدارة توقيتهن بدقة.
يمكن كتابة المخططات الزمنية عن طريق إنشاء مثيل لجدول زمني مثل:
gsap.timeline();
يمكنك أيضًا ربط عدة مراهقات بجدول زمني بطريقتين مختلفتين ، في الكود أدناه:
##Method 1 const tl = gsap.timeline(); // create an instance and assign it a variable tl.add(); // add tween to timeline tl.to('element', {}); tl.from('element', {}); ##Method 2 gsap.timeline() .add() // add tween to timeline .to('element', {}) .from('element', {})
دعنا نعيد إنشاء المثال السابق بخط زمني:
const { useRef, useEffect } = React; const Balls = () => { useEffect(() => { const tl = gsap.timeline(); tl.to('#ball1', {x:1000, ease:"bounce.in", duration: 3}) tl.to('#ball2', {x:1000, ease:"bounce.out", duration: 3, delay:3 }) tl.to('#ball3', {x:1000, ease:"bounce.inOut", duration: 3, delay:6 }) }, []); } ReactDOM.render( , document.getElementById('app'));
const { useRef, useEffect } = React; const Balls = () => { useEffect(() => { const tl = gsap.timeline(); tl.to('#ball1', {x:1000, ease:"bounce.in", duration: 3}) tl.to('#ball2', {x:1000, ease:"bounce.out", duration: 3, delay:3 }) tl.to('#ball3', {x:1000, ease:"bounce.inOut", duration: 3, delay:6 }) }, []); } ReactDOM.render( , document.getElementById('app'));
داخل خطاف useEffect
، أنشأنا متغيرًا (tl)
يحتوي على مثيل لجدول زمني ، ثم استخدمنا متغير tl
لتحريك tween بالتسلسل دون الاعتماد على tween السابق للتحريك ، وتمرير نفس الخصائص كما كانت في المثال السابق. للحصول على مقتطف الشفرة الكامل لهذا العرض التوضيحي ، تحقق من ملعب الكود أدناه.
الآن بعد أن تعرفنا على بعض اللبنات الأساسية لـ GSAP ، دعنا نرى كيف يمكننا إنشاء رسم متحرك كامل في تطبيق React نموذجي في القسم التالي. لنبدأ الرحلة!
إنشاء صفحة مقصودة متحركة باستخدام React و GSAP
دعنا نحرك تطبيق React. تأكد من استنساخ الريبو قبل أن تبدأ وتشغيل npm install
من أجل تثبيت التبعيات.
ماذا نبني؟
حاليًا ، تحتوي صفحتنا المقصودة على عدد قليل من النصوص بخلفية بيضاء ، وهي قائمة لا تسقط ، مع عدم وجود رسوم متحركة حقًا. فيما يلي ما سنضيفه إلى الصفحة المقصودة ؛
- حرك النص والشعار على الصفحة الرئيسية ، بحيث يخفف عند تركيب المكون.
- حرك القائمة ، بحيث تنخفض لأسفل عند النقر فوق القائمة.
- اجعل الصور في صفحة المعرض
20deg
عند تمرير الصفحة.
تحقق من العرض على codeandbox.
سنقسم عملية الصفحة المقصودة إلى مكونات ، لذلك سيكون من السهل فهمها. ها هي العملية.
- تحديد طرق الرسوم المتحركة ،
- تحريك النص والشعار ،
- تبديل القائمة ،
- اجعل الصور
20deg
عند تمرير الصفحة.
عناصر
-
Animate.js
- تم تحديد جميع طرق الرسوم المتحركة ، -
Image.js
- استيراد صور لوح المطبخ ، -
Menu.js
- يحتوي على وظيفة تبديل القائمة ، -
Header.js
- يحتوي على روابط تنقل.
تحديد طرق الرسوم المتحركة
قم بإنشاء مجلد component
داخل دليل src
، وأنشئ ملف animate.js
. انسخ والصق الكود التالي فيه.
import gsap from "gsap" import { ScrollTrigger } from "gsap/ScrollTrigger"; //Animate text export const textIntro = elem => { gsap.from(elem, { xPercent: -20, opacity: 0, stagger: 0.2, duration: 2, scale: -1, ease: "back", }); };
هنا ، قمنا باستيراد gsap
. كتبنا وظيفة سهم مُصدَّر تعمل على تحريك النص في الصفحة المقصودة. تذكر أن طريقة gsap.from()
تحدد القيم التي يجب تحريك الكائن منها. تحتوي الوظيفة على معلمة elem
تمثل الفئة التي يجب أن تكون متحركة. يأخذ بعض الخصائص ويعين قيمًا مثل xPercent: -20
(يحول الكائن بنسبة -20٪) ، ولا يعطي الكائن أي عتامة ، ويجعل scale
الكائن بمقدار -1
، ويجعل الكائن ease
في 2sec
.
لمعرفة ما إذا كان هذا يعمل ، توجه إلى App.js
وقم بتضمين الكود التالي.
... //import textIntro import {textIntro} from "./components/Animate" ... //using useRef hook to access the textIntro DOM let intro = useRef(null) useEffect(() => { textIntro(intro) }, []) function Home() { return ( <div className='container'> <div className='wrapper'> <h5 className="intro" ref={(el) => (intro = el)}></h5> The <b>SHOPPER</b>, is a worldclass, innovative, global online ecommerce platform, that meets your everyday daily needs. </h5> </div> </div> ); }
هنا ، نقوم باستيراد طريقة textIntro
من المكون Aminate
. للوصول إلى DOM اعتدنا على useRef
Hook. أنشأنا intro
متغير تم ضبط قيمتها على قيمة null
. بعد ذلك ، داخل الخطاف useEffect
، أطلقنا على طريقة textIntro
ومتغير intro
. داخل المكون الرئيسي لدينا ، في علامة h5
، حددنا الخاصية ref
وقمنا بتمريرها في متغير intro
.
بعد ذلك ، لدينا قائمة ، لكنها لا تنخفض عند النقر عليها. دعونا نجعلها تعمل! داخل مكون Header.js
، أضف الكود أدناه.
import React, { useState, useEffect, useRef } from "react"; import { withRouter, Link, useHistory } from "react-router-dom"; import Menu from "./Menu"; const Header = () => { const history = useHistory() let logo = useRef(null); //State of our Menu const [state, setState] = useState({ initial: false, clicked: null, menuName: "Menu", }); // State of our button const [disabled, setDisabled] = useState(false); //When the component mounts useEffect(() => { textIntro(logo); //Listening for page changes. history.listen(() => { setState({ clicked: false, menuName: "Menu" }); }); }, [history]); //toggle menu const toggleMenu = () => { disableMenu(); if (state.initial === false) { setState({ initial: null, clicked: true, menuName: "Close", }); } else if (state.clicked === true) { setState({ clicked: !state.clicked, menuName: "Menu", }); } else if (state.clicked === false) { setState({ clicked: !state.clicked, menuName: "Close", }); } }; // check if out button is disabled const disableMenu = () => { setDisabled(!disabled); setTimeout(() => { setDisabled(false); }, 1200); }; return ( <header> <div className="container"> <div className="wrapper"> <div className="inner-header"> <div className="logo" ref={(el) => (logo = el)}> <Link to="/">SHOPPER.</Link> </div> <div className="menu"> <button disabled={disabled} onClick={toggleMenu}> {state.menuName} </button> </div> </div> </div> </div> <Menu state={state} /> </header> ); }; export default withRouter(Header);
في هذا المكون ، حددنا القائمة وحالة الزر ، داخل الخطاف useEffect
، استمعنا إلى تغييرات الصفحة باستخدام الخطاف useHistory
، إذا تغيرت الصفحة ، فقمنا بتعيين قيم الحالة التي تم clicked
و menuName
على false
و Menu
على التوالي.
للتعامل مع قائمتنا ، تحققنا مما إذا كانت قيمة حالتنا الأولية خاطئة ، وإذا كانت صحيحة ، نقوم بتغيير القيمة initial
، clicked
، و menuName
إلى null
، و true
، و Close
. وإلا فإننا نتحقق مما إذا كان الزر قد تم النقر عليه ، وإذا كان صحيحًا menuName
بتغيير اسم القائمة إلى Menu
. بعد ذلك ، لدينا وظيفة " disabledMenu
" التي تعطل الزر الخاص بنا لمدة 1sec
واحدة عند النقر فوقه.
أخيرًا ، في زرنا ، قمنا بتعيين disabled
إلى " disabled
" وهي قيمة منطقية ستعمل على تعطيل button
عندما تكون قيمته true
. ويكون معالج onClick
للزر مرتبطًا بوظيفة toggleMenu
. كل ما فعلناه هنا هو تبديل نص menu
ومرر الحالة إلى مكون Menu
، والذي سننشئه قريبًا. دعنا نكتب الطرق التي ستجعل القائمة المنسدلة لدينا قبل إنشاء مكون Menu
الفعلي. توجه إلى Animate.js
والصق هذا الرمز فيه.
.... //Open menu export const menuShow = (elem1, elem2) => { gsap.from([elem1, elem2], { duration: 0.7, height: 0, transformOrigin: "right top", skewY: 2, ease: "power4.inOut", stagger: { amount: 0.2, }, }); }; //Close menu export const menuHide = (elem1, elem2) => { gsap.to([elem1, elem2], { duration: 0.8, height: 0, ease: "power4.inOut", stagger: { amount: 0.07, }, }); };
هنا ، لدينا وظيفة تسمى menuShow
، والتي تحرف القائمة أفقيًا بمقدار 2 درجة ، وتسهل القائمة ، 2degrees
الرسوم المتحركة باستخدام خاصية stagger
، وتحول القائمة من right to top
في 0.7sec
، نفس الخصائص تذهب إلى menuHide
وظيفة. لاستخدام هذه الوظائف ، قم بإنشاء ملف Menu.js
داخل components
ولصق هذا الرمز فيه.
import React, {useEffect, useRef} from 'react' import { gsap } from "gsap" import { Link } from "react-router-dom" import { menuShow, menuHide, textIntro, } from './Animate' const Menu = ({ state }) => { //create refs for our DOM elements let menuWrapper = useRef(null) let show1 = useRef(null) let show2 = useRef(null) let info = useRef(null) useEffect(() => { // If the menu is open and we click the menu button to close it. if (state.clicked === false) { // If menu is closed and we want to open it. menuHide(show2, show1); // Set menu to display none gsap.to(menuWrapper, { duration: 1, css: { display: "none" } }); } else if ( state.clicked === true || (state.clicked === true && state.initial === null) ) { // Set menu to display block gsap.to(menuWrapper, { duration: 0, css: { display: "block" } }); //Allow menu to have height of 100% gsap.to([show1, show2], { duration: 0, opacity: 1, height: "100%" }); menuShow(show1, show2); textIntro(info); } }, [state]) return ( <div ref={(el) => (menuWrapper = el)} className="hamburger-menu"> <div ref={(el) => (show1 = el)} className="menu-secondary-background-color" ></div> <div ref={(el) => (show2 = el)} className="menu-layer"> <div className="container"> <div className="wrapper"> <div className="menu-links"> <nav> <ul> <li> <Link ref={(el) => (line1 = el)} to="/about-us" > About </Link> </li> <li> <Link ref={(el) => (line2 = el)} to="/gallery" > Gallery </Link> </li> <li> <Link ref={(el) => (line3 = el)} to="/contact-us" > Contact us </Link> </li> </ul> </nav> <div ref={(el) => (info = el)} className="info"> <h3>Our Vision</h3> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit.... </p> </div> </div> </div> </div> </div> </div> ); } export default Menu
ما فعلناه في مكون Menu
هو استيراد الوظائف المتحركة ، وهي menuShow
، و menuHide
، و textIntro
. بعد ذلك ، قمنا بتعيين متغيرات لكل refs
تم إنشاؤه لعناصر DOM
الخاصة بنا باستخدام الخطاف useRef
وتمرير القيمة null
كقيم لها. داخل خطاف useEffect
، نتحقق من حالة menu
، إذا تم clicked
فوق false
، فإننا نسمي وظيفة menuHide
، وإلا ، إذا كانت الحالة التي تم clicked
صحيحة ، فإننا نسمي وظيفة menuShow
. أخيرًا ، تأكدنا من تمرير عناصر DOM
المعنية refs
المحددة وهي menuWrapper
و show1
و show2
. مع ذلك ، لدينا قائمة متحركة لدينا.
دعونا نرى كيف يبدو.
آخر الرسوم المتحركة التي ننفذها هي جعل صورنا في معرضنا skew
عند التمرير. دعونا نرى حالة معرضنا الآن.
لتنفيذ الرسوم المتحركة المنحرفة في معرضنا ، دعنا ننتقل إلى Animate.js
ونضيف بعض الرموز إليها.
.... //Skew gallery Images export const skewGallery = elem1 => { //register ScrollTrigger gsap.registerPlugin(ScrollTrigger); // make the right edge "stick" to the scroll bar. force3D: true improves performance gsap.set(elem1, { transformOrigin: "right center", force3D: true }); let clamp = gsap.utils.clamp(-20, 20) // don't let the skew go beyond 20 degrees. ScrollTrigger.create({ trigger: elem1, onUpdate: (self) => { const velocity = clamp(Math.round(self.getVelocity() / 300)); gsap.to(elem1, { skew: 0, skewY: velocity, ease: "power3", duration: 0.8, }); }, }); }
أنشأنا وظيفة تسمى skewGallery
، ومررنا elem1
، ScrollTrigger
.
ScrollTrigger هو مكون إضافي في GSAP يمكّننا من تشغيل الرسوم المتحركة القائمة على التمرير ، كما هو الحال في هذه الحالة من تحريف الصور أثناء تمرير الصفحة.
لجعل الحافة اليمنى تلتصق بشريط التمرير ، قمنا بتمرير قيمة right center
إلى خاصية transformOrigin
، قمنا أيضًا بتعيين خاصية force3D
على true في أخرى لتحسين الأداء.
أعلنا عن متغير clamp
يقوم بحساب الانحراف لدينا ويضمن أنه لا يتجاوز 20degs
. داخل كائن ScrollTrigger
، قمنا بتعيين خاصية trigger
إلى معلمة elem1
، والتي ستكون العنصر الذي يجب تشغيله عند استدعاء هذه الوظيفة. لدينا دالة رد onUpdate
، بداخلها متغير velocity
يحسب السرعة الحالية ويقسمها على 300
.
أخيرًا ، نقوم بتحريك العنصر من قيمه الحالية عن طريق تعيين قيم أخرى. قمنا بتعيين skew
ليكون مبدئيًا عند 0
ويكون skewY
هو متغير velocity
عند 0.8
.
بعد ذلك ، علينا استدعاء هذه الوظيفة في ملف App.js
بنا.
.... import { skewGallery } from "./components/Animate" function Gallery() { let skewImage = useRef(null); useEffect(() => { skewGallery(skewImage) }, []); return ( <div ref={(el) => (skewImage = el)}> <Image/> </div> ) } ....
هنا ، قمنا باستيراد skewGalley
من ./components/Animate
، وقمنا بإنشاء مرجع skewImage
يستهدف عنصر الصورة. داخل خطاف useEffect
، أطلقنا على دالة skewGallery
بتمرير skewImage
ref كمعامل. أخيرًا ، مررنا skewImage
إلى ref
إلى السمة.
كنت تتفق معي أنها كانت رحلة رائعة حتى الآن. ها هي المعاينة على CodeSanbox
الريبو الداعم لهذه المقالة متاح على جيثب.
خاتمة
لقد اكتشفنا فاعلية GSAP في مشروع React ، لقد خدشنا السطح فقط في هذه المقالة ، ولا يوجد حد لما يمكنك فعله باستخدام GSAP فيما يتعلق بالرسوم المتحركة. يقدم موقع GSAP الرسمي نصائح إضافية لمساعدتك على اكتساب فهم شامل للطرق والمكونات الإضافية. هناك الكثير من العروض التوضيحية التي ستذهلك بعيدًا عما فعله الأشخاص باستخدام GSAP. أود أن أسمع تجربتك مع GSAP في قسم التعليقات.
موارد
- وثائق GSAP ، GreenSock
- "دليل المبتدئين لمنصة الرسوم المتحركة GreenSock ،" نيكولاس كرامر ، freeCodeCamp
- "مقدمة إلى الرسوم المتحركة باستخدام واجهة برمجة تطبيقات الرسوم المتحركة Greensock (GSAP)" ، زيل ليو