أنشئ منزلق صفحة كاملة مخصصًا باستخدام CSS و JavaScript
نشرت: 2022-03-11أعمل كثيرًا مع تخطيطات ملء الشاشة المخصصة ، عمليًا بشكل يومي. عادةً ما تتضمن هذه التخطيطات قدرًا كبيرًا من التفاعل والحركة. سواء أكان ذلك عبارة عن مخطط زمني معقد للتحولات أو مجموعة من الأحداث القائمة على التمرير ، في معظم الحالات ، تتطلب واجهة المستخدم أكثر من مجرد استخدام حل مكون إضافي مع بعض التعديلات والتغييرات . من ناحية أخرى ، أرى أن العديد من مطوري JavaScript يميلون إلى الوصول إلى مكون JS الإضافي المفضل لديهم لتسهيل عملهم ، على الرغم من أن المهمة قد لا تحتاج إلى كل الأجراس والصفارات التي يوفرها مكون إضافي معين.
إخلاء المسؤولية: استخدام أحد المكونات الإضافية العديدة المتاحة له مزايا بالطبع. ستحصل على مجموعة متنوعة من الخيارات التي يمكنك استخدامها لتعديل احتياجاتك دون الحاجة إلى القيام بالكثير من الترميز. أيضًا ، يعمل معظم مؤلفي الإضافات على تحسين التعليمات البرمجية الخاصة بهم ، وجعلها متوافقة مع المستعرضات وعبر الأنظمة الأساسية ، وما إلى ذلك. ولكن مع ذلك ، تحصل على مكتبة بالحجم الكامل مدرجة في مشروعك ربما لشيء واحد أو شيئين مختلفين فقط يوفرهما. أنا لا أقول إن استخدام مكون إضافي تابع لجهة خارجية من أي نوع يعد أمرًا سيئًا بطبيعة الحال ، فأنا أفعل ذلك يوميًا في مشروعاتي ، فقط لأنه من الجيد عمومًا تقييم إيجابيات وسلبيات كل نهج كما هو ممارسة جيدة في الترميز. عندما يتعلق الأمر بفعل الشيء الخاص بك بهذه الطريقة ، فإنه يتطلب معرفة وخبرة أكثر قليلاً في الترميز لمعرفة ما تبحث عنه ، ولكن في النهاية ، يجب أن تحصل على جزء من التعليمات البرمجية التي تقوم بشيء واحد وشيء واحد فقط بالطريقة تريد ذلك.
تهدف هذه المقالة إلى إظهار نهج CSS / JS خالص في تطوير تخطيط منزلق يتم تشغيله بملء الشاشة مع رسوم متحركة مخصصة للمحتوى. في هذا النهج المصغر ، سأغطي بنية HTML الأساسية التي تتوقع أن يتم تسليمها من CMS الخلفية ، وتقنيات تخطيط CSS (SCSS) الحديثة ، وتشفير JavaScript الفانيليا للتفاعل الكامل. نظرًا لكونه مكشوفًا ، يمكن توسيع هذا المفهوم بسهولة ليشمل مكونًا إضافيًا على نطاق واسع و / أو استخدامه في مجموعة متنوعة من التطبيقات التي لا تحتوي على تبعيات في جوهرها.
التصميم الذي سنقوم بإنشائه هو عرض لمحفظة معمارية مبسطة مع صور وعناوين مميزة لكل مشروع. سيبدو شريط التمرير الكامل مع الرسوم المتحركة كما يلي:
يمكنك التحقق من العرض التوضيحي هنا ، ويمكنك الوصول إلى Github repo للحصول على مزيد من التفاصيل.
نظرة عامة على HTML
إذن ، هذا هو HTML الأساسي الذي سنعمل معه:
<div> <div class="mask"> <!-- Textual logo will go here --> </div> <div> <div class="slides"> <!-- Featured image slides will go here --> </div> <div class="slides mask"> <!-- Slide titles will go here --> </div> </div> <div> <!-- Static info on the right --> </div> <nav> <!-- Current slide indicator --> </nav> </div>
صاحبنا الرئيسي هو div بمعرّف hero-slider
. في الداخل ، ينقسم التصميم إلى أقسام:
- الشعار (قسم ثابت)
- عرض الشرائح الذي سنعمل عليه في الغالب
- معلومات (قسم ثابت)
- التنقل في شريط التمرير الذي سيشير إلى الشريحة النشطة حاليًا بالإضافة إلى العدد الإجمالي للشرائح
دعنا نركز على قسم عرض الشرائح لأن هذه هي نقطة اهتمامنا في هذه المقالة. هنا لدينا جزأين - main و aux . Main هو div الذي يحتوي على صور مميزة بينما يحمل aux عناوين الصور. هيكل كل شريحة داخل هذين الحاملين أساسي جدًا. هنا لدينا شريحة صورة داخل الحامل الرئيسي:
<div class="slide" data-index="0"> <div class="abs-mask"> <div class="slide-image"> </div> </div> </div>
سمة بيانات الفهرس هي ما سنستخدمه لتتبع مكاننا في عرض الشرائح. عنصر abs-mask div الذي سنستخدمه لإنشاء تأثير انتقال مثير للاهتمام وتحتوي صورة الشريحة div على الصورة المميزة المحددة. يتم تقديم الصور مضمنة كما لو كانت قادمة مباشرة من نظام إدارة المحتوى وتم تعيينها بواسطة المستخدم النهائي.
وبالمثل ، ينزلق العنوان داخل حامل aux:
<h2 class="slide-title slide" data-index="0"><a href="#">#64 Paradigm</a></h2>
كل عنوان شريحة هو علامة H2 مع سمة البيانات المقابلة ورابط لتتمكن من الوصول إلى الصفحة الفردية لهذا المشروع.
باقي ملفات HTML الخاصة بنا واضحة جدًا أيضًا. لدينا شعار في الجزء العلوي ، معلومات ثابتة تخبر المستخدم بالصفحة التي يتواجدون بها ، وبعض الوصف ، ومؤشر التيار / الإجمالي المنزلق.
نظرة عامة على CSS
تمت كتابة كود CSS المصدر في SCSS ، وهو معالج CSS مسبق يتم تجميعه بعد ذلك في CSS عادي يمكن للمتصفح تفسيره. يمنحك SCSS ميزة استخدام المتغيرات ، والاختيار المتداخل ، والمزج ، والأشياء الرائعة الأخرى ، ولكن يجب تجميعها في CSS ليقرأ المستعرض الكود كما ينبغي. لغرض هذا البرنامج التعليمي ، استخدمت Scout-App للتعامل مع التجميع حيث أردت الحصول على الأدوات بالحد الأدنى.
لقد استخدمت flexbox للتعامل مع التخطيط الأساسي جنبًا إلى جنب. الفكرة هي أن يكون عرض الشرائح على جانب واحد وقسم المعلومات على الجانب الآخر.
#hero-slider { position: relative; height: 100vh; display: flex; background: $dark-color; } #slideshow { position: relative; flex: 1 1 $main-width; display: flex; align-items: flex-end; padding: $offset; } #info { position: relative; flex: 1 1 $side-width; padding: $offset; background-color: #fff; }
دعنا نتعمق في تحديد المواقع ونركز مرة أخرى على قسم عرض الشرائح:
#slideshow { position: relative; flex: 1 1 $main-width; display: flex; align-items: flex-end; padding: $offset; } #slides-main { @extend %abs; &:after { content: ''; @extend %abs; background-color: rgba(0, 0, 0, .25); z-index: 100; } .slide-image { @extend %abs; background-position: center; background-size: cover; z-index: -1; } } #slides-aux { position: relative; top: 1.25rem; width: 100%; .slide-title { position: absolute; z-index: 300; font-size: 4vw; font-weight: 700; line-height: 1.3; @include outlined(#fff); } }
لقد قمت بتعيين شريط التمرير الرئيسي ليتم وضعه تمامًا وجعل صور الخلفية تمد المنطقة بأكملها باستخدام background-size: cover
. لتوفير مزيد من التباين مع عناوين الشرائح ، قمت بتعيين عنصر زائف مطلق يعمل بمثابة تراكب. يتم وضع شريط التمرير المساعد الذي يحتوي على عناوين الشرائح في الجزء السفلي من الشاشة وفوق الصور.
نظرًا لأن شريحة واحدة فقط ستكون مرئية في كل مرة ، فقد قمت بتعيين كل عنوان ليكون مطلقًا أيضًا ، وتم حساب حجم الحامل عبر JS للتأكد من عدم وجود حدود نهائية ، ولكن المزيد عن ذلك في أحد الأقسام القادمة. يمكنك هنا مشاهدة استخدام ميزة SCSS تسمى التمديد:
%abs { position: absolute; top: 0; left: 0; height: 100%; width: 100%; }
نظرًا لأنني استخدمت تحديد المواقع المطلق كثيرًا ، فقد قمت بسحب CSS هذا إلى قابل للتمديد لإتاحته بسهولة في محددات مختلفة. أيضًا ، قمت بإنشاء مزيج يسمى "مخطط" لتوفير نهج جاف عند تصميم العناوين وعنوان شريط التمرير الرئيسي.
@mixin outlined($color: $dark-color, $size: 1px) { color: transparent; -webkit-text-stroke: $size $color; }
بالنسبة للجزء الثابت من هذا التخطيط ، فإنه لا يحتوي على أي شيء معقد حوله ولكن هنا يمكنك رؤية طريقة مثيرة للاهتمام عند وضع النص الذي يجب أن يكون على المحور Y بدلاً من التدفق الطبيعي:
.slider-title-wrapper { position: absolute; top: $offset; left: calc(100% - #{$offset}); transform-origin: 0% 0%; transform: rotate(90deg); @include outlined; }
أود أن ألفت انتباهك إلى خاصية transform-origin
حيث وجدت أنها غير مستخدمة بشكل كافٍ لهذا النوع من التخطيط. الطريقة التي يتم بها وضع هذا العنصر هي أن مرساة تبقى في الزاوية اليسرى العليا للعنصر ، وتعيين نقطة الدوران وجعل النص يتدفق باستمرار من تلك النقطة إلى أسفل دون أي مشاكل عندما يتعلق الأمر بأحجام شاشة مختلفة.
دعنا نلقي نظرة على جزء CSS أكثر إثارة للاهتمام - الرسوم المتحركة الأولية للتحميل:
عادة ، يتم تحقيق هذا النوع من سلوك الرسوم المتحركة المتزامن باستخدام مكتبة - GSAP ، على سبيل المثال ، هي واحدة من أفضل ما هناك ، حيث توفر إمكانات عرض ممتازة ، وسهلة الاستخدام ، ولديها وظيفة المخطط الزمني التي تمكن المطور من تسلسل العنصر برمجيًا انتقالات في بعضها البعض.
ومع ذلك ، نظرًا لأن هذا مثال CSS / JS خالص ، فقد قررت أن أذهب إلى الأساسيات هنا. لذلك يتم تعيين كل عنصر على موضع البداية بشكل افتراضي - إما مخفيًا عن طريق التحويل أو التعتيم ويظهر عند تحميل شريط التمرير الذي يتم تشغيله بواسطة JS الخاص بنا. يتم تعديل جميع خصائص الانتقال يدويًا لضمان تدفق طبيعي ومثير للاهتمام مع استمرار كل انتقال إلى آخر مما يوفر تجربة بصرية ممتعة.
#logo:after { transform: scaleY(0); transform-origin: 50% 0; transition: transform .35s $easing; } .logo-text { display: block; transform: translate3d(120%, 0, 0); opacity: 0; transition: transform .8s .2s, opacity .5s .2s; } .current, .sep:before { opacity: 0; transition: opacity .4s 1.3s; } #info { transform: translate3d(100%, 0, 0); transition: transform 1s $easing .6s; } .line { transform-origin: 0% 0; transform: scaleX(0); transition: transform .7s $easing 1s; } .slider-title { overflow: hidden; >span { display: block; transform: translate3d(0, -100%, 0); transition: transform .5s 1.5s; } }
إذا كان هناك شيء واحد أود أن تراه هنا ، فهو استخدام خاصية transform
. عند نقل عنصر HTML ، سواء كان انتقالًا أو رسمًا متحركًا ، يُنصح باستخدام خاصية transform
. أرى الكثير من الأشخاص الذين يميلون إلى الحيل إما الهامش أو الحشو أو حتى تعويضات - أعلى ، اليسار ، وما إلى ذلك والتي لا تعطي نتائج مناسبة عندما يتعلق الأمر بالعرض.
للحصول على فهم أكثر تعمقًا حول كيفية استخدام CSS عند إضافة سلوك تفاعلي ، لا يمكنني التوصية بالمقال التالي بشكل كافٍ.
إنه من تصميم Paul Lewis ، مهندس Chrome ، ويغطي إلى حد كبير كل ما يجب أن يعرفه المرء عن عرض البكسل في الويب سواء كان CSS أو JS.
نظرة عامة على JavaScript ومنطق شريط التمرير
ينقسم ملف JavaScript إلى وظيفتين مختلفتين.
وظيفة heroSlider
التي تهتم بجميع الوظائف التي نحتاجها هنا ، ووظيفة utils
حيث أضفت العديد من وظائف الأداة القابلة لإعادة الاستخدام. لقد علقت على كل من وظائف الأداة المساعدة هذه لتوفير سياق إذا كنت تتطلع إلى إعادة استخدامها في مشروعك.
يتم ترميز الوظيفة الرئيسية بطريقة لها فرعين: init
و resize
. تتوفر هذه الفروع عبر إعادة الوظيفة الرئيسية ويتم استدعاؤها عند الضرورة. init
هي تهيئة الوظيفة الرئيسية ويتم تشغيلها في حدث تحميل النافذة. وبالمثل ، يتم تشغيل فرع تغيير الحجم عند تغيير حجم النافذة. الغرض الوحيد من وظيفة تغيير الحجم هو إعادة حساب حجم شريط تمرير العنوان عند تغيير حجم النافذة ، حيث قد يختلف حجم خط العنوان.
في وظيفة heroSlider
، قمت بتوفير كائن منزلق يحتوي على جميع البيانات والمحددات التي سنحتاجها:
const slider = { hero: document.querySelector('#hero-slider'), main: document.querySelector('#slides-main'), aux: document.querySelector('#slides-aux'), current: document.querySelector('#slider-nav .current'), handle: null, idle: true, activeIndex: -1, interval: 3500 };
كملاحظة جانبية ، يمكن تكييف هذا النهج بسهولة إذا كنت تستخدم React على سبيل المثال ، حيث يمكنك تخزين البيانات في الحالة أو استخدام الخطافات المضافة حديثًا. للبقاء على هذه النقطة ، دعنا ننتقل إلى ما يمثله كل زوج من أزواج القيمة الرئيسية هنا:

- الخصائص الأربع الأولى هي مرجع HTML لعنصر DOM الذي سنتعامل معه.
- سيتم استخدام خاصية
handle
لبدء وإيقاف وظيفة التشغيل التلقائي. - خاصية
idle
هي علامة تمنع المستخدم من فرض التمرير أثناء انتقال الشريحة. - سيسمح لنا
activeIndex
بتتبع الشريحة النشطة حاليًا - يشير
interval
إلى فاصل التشغيل التلقائي لشريط التمرير
عند تهيئة شريط التمرير ، نستدعي وظيفتين:
setHeight(slider.aux, slider.aux.querySelectorAll('.slide-title')); loadingAnimation();
تصل وظيفة setHeight
إلى وظيفة الأداة المساعدة لتعيين ارتفاع شريط التمرير aux استنادًا إلى الحد الأقصى لحجم العنوان. بهذه الطريقة نضمن توفير الحجم المناسب ولن يتم اقتطاع أي عنوان للشريحة حتى عندما ينخفض محتواها إلى سطرين.
تضيف وظيفة الرسوم المتحركة فئة CSS إلى العنصر الذي يوفر انتقالات CSS المقدمة:
const loadingAnimation = function () { slider.hero.classList.add('ready'); slider.current.addEventListener('transitionend', start, { once: true }); }
نظرًا لأن مؤشر التمرير الخاص بنا هو العنصر الأخير في الجدول الزمني للانتقال في CSS ، فإننا ننتظر حتى انتهاء انتقاله واستدعاء وظيفة البداية. من خلال توفير معلمة إضافية ككائن ، نضمن تشغيل ذلك مرة واحدة فقط.
دعنا نلقي نظرة على وظيفة البداية:
const start = function () { autoplay(true); wheelControl(); window.innerWidth <= 1024 && touchControl(); slider.aux.addEventListener('transitionend', loaded, { once: true }); }
لذلك ، عند انتهاء التخطيط ، يتم تشغيل انتقاله الأولي عن طريق وظيفة loadingAnimation
وظيفة البداية المهمة. ثم يقوم بتشغيل وظيفة التشغيل التلقائي ، ويمكّن التحكم في العجلة ، ويحدد ما إذا كنا على جهاز يعمل باللمس أو سطح المكتب ، وينتظر الانتقال الأول لشريحة العناوين لإضافة فئة CSS المناسبة.
تشغيل تلقائي
إحدى الميزات الأساسية في هذا التخطيط هي ميزة التشغيل التلقائي. دعنا ننتقل إلى الوظيفة المقابلة:
const autoplay = function (initial) { slider.autoplay = true; slider.items = slider.hero.querySelectorAll('[data-index]'); slider.total = slider.items.length / 2; const loop = () => changeSlide('next'); initial && requestAnimationFrame(loop); slider.handle = utils().requestInterval(loop, slider.interval); }
أولاً ، قمنا بتعيين علامة التشغيل التلقائي على "صحيح" ، مما يشير إلى أن شريط التمرير في وضع التشغيل التلقائي. هذه العلامة مفيدة عند تحديد ما إذا كان سيتم إعادة تشغيل التشغيل التلقائي بعد تفاعل المستخدم مع شريط التمرير. نقوم بعد ذلك بالإشارة إلى جميع عناصر شريط التمرير (الشرائح) ، حيث سنقوم بتغيير فئتها النشطة وحساب إجمالي التكرارات التي سيحصل عليها شريط التمرير عن طريق إضافة جميع العناصر والقسمة على اثنين لأن لدينا تخطيطين متزامنين لشريط التمرير (رئيسي و aux) ولكن فقط "شريط تمرير" واحد في حد ذاته يغير كلاهما في وقت واحد.
الجزء الأكثر إثارة للاهتمام من الكود هنا هو وظيفة الحلقة. إنها تستدعي slideChange
، وتوفر اتجاه الشريحة الذي سننتقل إليه خلال دقيقة ، ومع ذلك ، فإن وظيفة الحلقة تسمى بضع مرات. دعنا نرى لماذا.
إذا تم تقييم الوسيطة الأولية على أنها صحيحة ، فسنستدعي وظيفة الحلقة باعتبارها requestAnimationFrame
callback. يحدث هذا فقط عند تحميل شريط التمرير الأول الذي يؤدي إلى تغيير الشريحة على الفور. باستخدام requestAnimationFrame
، نقوم بتنفيذ رد النداء المقدم قبل إعادة رسم الإطار التالي مباشرة.
ومع ذلك ، نظرًا لأننا نريد الاستمرار في استعراض الشرائح في وضع التشغيل التلقائي ، فسنستخدم استدعاء متكرر لهذه الوظيفة نفسها. يتم تحقيق ذلك عادةً باستخدام setInterval. لكن في هذه الحالة ، سنستخدم إحدى وظائف الأداة المساعدة requestInterval
. في حين أن setInterval
ستعمل بشكل جيد ، requestInterval
هو مفهوم متقدم يعتمد على requestAnimationFrame
ويوفر نهجًا أكثر أداءً. يضمن إعادة تشغيل هذه الوظيفة فقط إذا كانت علامة تبويب المتصفح نشطة.
يمكن العثور على المزيد حول هذا المفهوم في هذه المقالة الرائعة في حيل CSS. يرجى ملاحظة أننا نقوم بتعيين قيمة الإرجاع من هذه الوظيفة إلى خاصية slider.handle
الخاصة بنا. هذا المعرف الفريد الذي ترجع إليه الوظيفة متاح لنا وسنستخدمه لإلغاء التشغيل التلقائي لاحقًا باستخدام cancelAnimationFrame
.
تغيير الشرائح
وظيفة slideChange
هي الوظيفة الأساسية في المفهوم بأكمله. يغير الشرائح سواء كان ذلك عن طريق التشغيل التلقائي أو بواسطة مشغل المستخدم. إنه مدرك لاتجاه شريط التمرير ، ويوفر تكرارًا لذلك عندما تصل إلى الشريحة الأخيرة ، ستتمكن من المتابعة إلى الشريحة الأولى. إليك كيفية ترميزها:
const changeSlide = function (direction) { slider.idle = false; slider.hero.classList.remove('prev', 'next'); if (direction == 'next') { slider.activeIndex = (slider.activeIndex + 1) % slider.total; slider.hero.classList.add('next'); } else { slider.activeIndex = (slider.activeIndex - 1 + slider.total) % slider.total; slider.hero.classList.add('prev'); } //reset classes utils().removeClasses(slider.items, ['prev', 'active']); //set prev const prevItems = [...slider.items] .filter(item => { let prevIndex; if (slider.hero.classList.contains('prev')) { prevIndex = slider.activeIndex == slider.total - 1 ? 0 : slider.activeIndex + 1; } else { prevIndex = slider.activeIndex == 0 ? slider.total - 1 : slider.activeIndex - 1; } return item.dataset.index == prevIndex; }); //set active const activeItems = [...slider.items] .filter(item => { return item.dataset.index == slider.activeIndex; }); utils().addClasses(prevItems, ['prev']); utils().addClasses(activeItems, ['active']); setCurrent(); const activeImageItem = slider.main.querySelector('.active'); activeImageItem.addEventListener('transitionend', waitForIdle, { once: true }); }
الفكرة هي تحديد الشريحة النشطة بناءً على فهرس البيانات الذي حصلنا عليه من HTML. دعنا نتناول كل خطوة:
- تعيين علامة الخمول المنزلق على خطأ. يشير هذا إلى أن تغيير الشريحة قيد التقدم وأن إيماءات العجلة واللمس معطلة.
- تتم إعادة تعيين فئة CSS لاتجاه المنزلق السابق ونتحقق من الفئة الجديدة. يتم توفير معلمة الاتجاه إما افتراضيًا كـ "التالي" إذا كنا قادمين من وظيفة التشغيل التلقائي أو عن طريق استدعاء المستخدم للوظيفة
wheelControl
أوtouchControl
. - بناءً على الاتجاه ، نحسب فهرس الشريحة النشط ونقدم فئة CSS للاتجاه الحالي إلى شريط التمرير. تُستخدم فئة CSS هذه لتحديد تأثير الانتقال الذي سيتم استخدامه (على سبيل المثال من اليمين إلى اليسار أو من اليسار إلى اليمين)
- تحصل الشرائح على إعادة تعيين فئات CSS "الحالة" (السابقة والنشطة) باستخدام وظيفة أداة مساعدة أخرى تزيل فئات CSS ولكن يمكن استدعاؤها في NodeList ، بدلاً من مجرد عنصر DOM واحد. بعد ذلك ، الشرائح السابقة والنشطة فقط هي التي تضاف إليها فئات CSS. يسمح هذا لـ CSS باستهداف تلك الشرائح فقط وتوفير انتقال مناسب.
-
setCurrent
عبارة عن رد اتصال يقوم بتحديث مؤشر شريط التمرير بناءً على الفهرس النشط. - أخيرًا ، ننتظر حتى انتهاء انتقال شريحة الصورة النشطة من أجل تشغيل رد الاتصال
waitForIdle
الذي يعيد تشغيل التشغيل التلقائي إذا كان المستخدم قد قاطعه مسبقًا.
ضوابط المستخدم
بناءً على حجم الشاشة ، أضفت نوعين من عناصر تحكم المستخدم - العجلة واللمس. التحكم في العجلة:
const wheelControl = function () { slider.hero.addEventListener('wheel', e => { if (slider.idle) { const direction = e.deltaY > 0 ? 'next' : 'prev'; stopAutoplay(); changeSlide(direction); } }); }
هنا ، نستمع إلى العجلة حتى وإذا كان شريط التمرير حاليًا في وضع الخمول (لا يتم حاليًا تحريك تغيير الشريحة) ، فإننا نحدد اتجاه العجلة ، واستدعاء stopAutoplay
لإيقاف وظيفة التشغيل التلقائي إذا كانت قيد التقدم ، وتغيير الشريحة بناءً على الاتجاه. إن وظيفة stopAutoplay
ليست سوى وظيفة بسيطة تحدد علامة التشغيل التلقائي الخاصة بنا على القيمة الخاطئة وتلغي الفاصل الزمني عن طريق استدعاء وظيفة الأداة المساعدة cancelRequestInterval
بالمقبض المناسب:
const stopAutoplay = function () { slider.autoplay = false; utils().clearRequestInterval(slider.handle); }
على غرار wheelControl
، لدينا touchControl
الذي يعتني بإيماءات اللمس:
const touchControl = function () { const touchStart = function (e) { slider.ts = parseInt(e.changedTouches[0].clientX); window.scrollTop = 0; } const touchMove = function (e) { slider.tm = parseInt(e.changedTouches[0].clientX); const delta = slider.tm - slider.ts; window.scrollTop = 0; if (slider.idle) { const direction = delta < 0 ? 'next' : 'prev'; stopAutoplay(); changeSlide(direction); } } slider.hero.addEventListener('touchstart', touchStart); slider.hero.addEventListener('touchmove', touchMove); }
نستمع touchstart
: بداية اللمس touchmove
. ثم نحسب الفرق. إذا أرجع قيمة سالبة ، فإننا نغير إلى الشريحة التالية حيث قام المستخدم بالتمرير من اليمين إلى اليسار. من ناحية أخرى ، إذا كانت القيمة موجبة ، مما يعني أن المستخدم قد مرر سريعًا من اليسار إلى اليمين ، فإننا نقوم بتشغيل slideChange
مع الاتجاه الذي تم تمريره على أنه "سابق". في كلتا الحالتين ، تتوقف وظيفة التشغيل التلقائي.
هذا تطبيق بسيط جدًا لإيماءات المستخدم. للبناء على هذا ، يمكننا إضافة الأزرار السابقة / التالية لتشغيل slideChange
عند النقر أو إضافة قائمة نقطية للانتقال مباشرة إلى شريحة بناءً على فهرسها.
الخلاصة والأفكار النهائية حول CSS
إذن ، هناك طريقة CSS / JS خالصة لترميز تخطيط منزلق غير قياسي مع تأثيرات انتقال حديثة.
أتمنى أن تجد هذا النهج مفيدًا كطريقة تفكير ويمكن أن تستخدم شيئًا مشابهًا في مشاريعك الأمامية عند الترميز لمشروع لم يكن بالضرورة مصممًا بشكل تقليدي.
لأولئك منكم المهتمين بتأثير انتقال الصورة ، سأنتقل إلى هذا في الأسطر القليلة التالية.
إذا أعدنا زيارة هيكل HTML للشرائح الذي قدمته في قسم المقدمة ، فسنرى أن كل شريحة صورة بها div
حولها مع فئة CSS الخاصة abs-mask
. ما يفعله div
هو أنه يخفي جزءًا من الصورة المرئية بمقدار معين باستخدام overflow:hidden
ويعوضها في اتجاه مختلف عن الصورة. على سبيل المثال ، إذا نظرنا إلى طريقة ترميز الشريحة السابقة:
&.prev { z-index: 5; transform: translate3d(-100%, 0, 0); transition: 1s $easing; .abs-mask { transform: translateX(80%); transition: 1s $easing; } }
تحتوي الشريحة السابقة على إزاحة بنسبة 100٪ في محورها X ، مما يؤدي إلى تحريكها إلى يسار الشريحة الحالية ، ومع ذلك ، تتم ترجمة div abs-mask
الداخلي بنسبة 80٪ إلى اليمين ، مما يوفر إطار عرض أضيق. هذا ، بالإضافة إلى وجود فهرس z أكبر للشريحة النشطة ينتج عنه نوع من تأثير الغلاف - تغطي الصورة النشطة الصورة السابقة بينما تقوم في نفس الوقت بتمديد المنطقة المرئية عن طريق تحريك القناع الذي يوفر العرض الكامل.