در این آموزش، ما یاد خواهیم گرفت که چگونه متن یک عنصر را به کاراکترهای جداگانه تقسیم کنیم، که سپس آنها را متحرک می کنیم تا جلوه پیچشی به ما بدهد.
چیزی که ما خواهیم ساخت
بدون مقدمه بیشتر، بیایید بررسی کنیم که چه چیزی می سازیم:
در مورد ما، دو نوع انیمیشن وجود خواهد داشت:
- اولین انیمیشن هر بار که عنوانی در معرض دید قرار می گیرد اتفاق می افتد.
- انیمیشن دوم هر بار که کاربر ماوس را روی یک لینک میگذارد اتفاق میافتد.
1. با نشانه گذاری HTML شروع کنید
ما سه بخش را تعریف می کنیم. هر بخش دارای یک عنوان، یک پاراگراف و یک پیوند خواهد بود.
را اضافه می کنیم data-split
به عناصری که متحرک خواهند شد نسبت دهید. اضافی data-split-type
ویژگی نوع انیمیشن را تعیین می کند. مقادیر ممکن هستند hover
و scroll
.
در اینجا نشانه گذاری مورد نیاز است:
<section> <div> <h2 data-split data-split-type="scroll">...</h2> <p>...</p> <a href="" data-split data-split-type="hover">...</a> </div> </section> <section> <div> <h2 data-split data-split-type="scroll">...</h2> <p>...</p> <a href="" data-split data-split-type="hover">...</a> </div> </section> <section> <div> <h2 data-split data-split-type="scroll">...</h2> <p>...</p> <a href="" data-split data-split-type="hover">...</a> </div> </section>
2. تقسیم متن
را splitCharacters()
تابع وظیفه تقسیم متن تمام عناصر با data-split
صفت و قرار دادن هر یک از شخصیت های آنها در یک span
عنصر
بنابراین، با فرض اینکه در ابتدا، این عنصر را داریم:
<a href="" data-split data-split-type="hover">Hover me →</a>
پس از اجرای تابع، نشانه گذاری عنصر فوق به این شکل تبدیل می شود:
<a href="" data-split data-split-type="hover"> <span class="inner"> <span class="front"> <span class="char" style="--index: 1;">H</span> <span class="char" style="--index: 2;">o</span> <span class="char" style="--index: 3;">v</span> <span class="char" style="--index: 4;">e</span> <span class="char" style="--index: 5;">r</span> <span> </span> <span class="char" style="--index: 6;">m</span> <span class="char" style="--index: 7;">e</span> <span> </span> <span class="char" style="--index: 8;">→</span> </span> <span class="back"> <span class="char" style="--index: 1;">H</span> <span class="char" style="--index: 2;">o</span> <span class="char" style="--index: 3;">v</span> <span class="char" style="--index: 4;">e</span> <span class="char" style="--index: 5;">r</span> <span> </span> <span class="char" style="--index: 6;">m</span> <span class="char" style="--index: 7;">e</span> <span> </span> <span class="char" style="--index: 8;">→</span> </span> </span> </a>
نتیجه نهایی مانند قبل از اجرای عملکرد ظاهر می شود.
در اینجا چند نکته قابل توجه است:
- در داخل عنصر هدف ما را تعریف می کنیم
.inner
عنصری که شامل.front
و.back
عناصر. این لفاف را اضافه می کنیمspan
برای جداسازی سبک های عنصر هدف (به عنوان مثال پیوند) و اجتناب از هر کدام - ناسازگاری ها (مثلاً اگر به پیوند بالشتک اضافه کنیم).
- هر دو
.front
و.back
عناصر حاوی متن اولیه عنصر خواهند بودspan
عناصر. - به طور پیش فرض، محتویات
.front
عنصر قابل مشاهده خواهد بود. بسته به نوع انیمیشن، محتویات.back
زمانی که ماوس را بر روی عنصر مورد نظر نگه می داریم یا تا زمانی که نمایان شود پیمایش کنیم، یکی ظاهر می شود. - همانطور که در یک بیت خواهیم دید، ما از آن استفاده خواهیم کرد
transition-delay
ویژگی برای متحرک سازی متوالی شخصیت ها. برای ایجاد تاخیرهای مختلف بین آنها، از این استفاده می کنیمindex
متغیر CSS هر کاراکتر، به غیر از یک خالی (فاصله سفید)، به عنوان مقدار این متغیر یک عدد افزایشی دریافت می کند که نشان دهنده موقعیت / شاخص کاراکتر در والد آنها است.
با در نظر گرفتن همه اینها، در اینجا اعلامیه کامل است splitCharacters()
عملکرد:
function splitCharacters() { const targets = document.querySelectorAll("[data-split]"); for (const target of targets) { let string = '<span class="inner"><span class="front" let counter = 0; const targetContent = target.textContent; const words = targetContent.trim().split(" "); words.forEach(function (word, wordIndex, wordArray) { const chars = word.split(""); chars.forEach(function (char, charIndex, charArray) { string += `<span class="char" style="--index: ${++counter};">${char}</span>`; if ( wordIndex === wordArray.length - 1 && charIndex === charArray.length - 1 ) { counter = 0; } }); if (wordIndex !== wordArray.length - 1) { string += "<span> </span>"; } }); string += "</span>"; string += '<span class="back" words.forEach(function (word, wordIndex, wordArray) { const chars = word.split(""); chars.forEach(function (char) { string += `<span class="char" style="--index: ${++counter};">${char}</span>`; }); if (wordIndex !== wordArray.length - 1) { string += "<span> </span>"; } }); string += "</span>"; string += "</span>"; target.innerHTML = string; } }
3. اضافه کردن سبک ها
برای سادگی، ما فقط توجه خود را بر روی سبک های اصلی متمرکز خواهیم کرد. علاوه بر این، شما می توانید همه آنها را با کلیک کردن بر روی آن بررسی کنید CSS برگه نسخه ی نمایشی
در اینجا موارد قابل توجه است:
- را
.back
عنصر یک عنصر مطلق خواهد بود. - به طور پیش فرض، بین انیمیشن هر کاراکتر 0.015 ثانیه تفاوت وجود خواهد داشت. که گفت، شخصیت اول از
.front
و.back
عناصر دارای تاخیر انتقال 0.015 ثانیه، دومی 0.03 ثانیه، سومی 0.045 ثانیه و غیره خواهند بود. فضای خالی هیچ تاخیری نخواهد داشت. - شخصیت های داخل
.back
عنصر به طور پیش فرض مخفی می شود و زیر متن به صورت زیر قرار می گیرد:
سبک های مرتبط:
[data-split], [data-split] span { display: inline-block; } [data-split] .inner { display: block; position: relative; overflow: hidden; } [data-split] .back { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } [data-split] .char { transition: all 0.4s cubic-bezier(0.2, 0.63, 0.4, 1.02); transition-delay: calc(0.015s * var(--index)); } [data-split] .back .char { opacity: 0; transform: translateY(101%) skewX(55deg); } [data-split-type="hover"] .char { transition-duration: 0.25s; }
انیمیشن شناور
همانطور که ماوس را روی یک عنصر با نشان می دهیم [data-split-type="hover"]
ویژگی، شخصیت های .back
عنصر ظاهر خواهد شد در حالی که آنهایی که از .front
عنصر با حرکت به سمت بالا به این صورت پنهان می شود:
در اینجا سبک های مربوطه وجود دارد:
[data-split-type="hover"]:hover .back .char { opacity: 1; transform: none; } [data-split-type="hover"]:hover .front .char { opacity: 0; transform: translateY(-101%) skewX(-55deg); }
4. متحرک سازی در اسکرول
همانطور که صفحه را اسکرول می کنیم، همه عناصر با [data-split-type="scroll"]
ویژگی به محض اینکه در viewport قابل مشاهده باشد متحرک می شود. در مثال ما، فقط سرفصل ها این رفتار را خواهد داشت.
برای انجام این کار، کدی را از این آموزش قرض می گیریم که از آن استفاده می کند Intersection Observer API.
بنابراین، wاگر حداقل 50 درصد از هر عنوان در نظر گرفته شود، آن را دریافت خواهد کرد is-animated
کلاس در غیر این صورت، این کلاس را از دست می دهد و انیمیشن به حالت اولیه خود باز می گردد.
در زیر ما تابع مسئول این موارد را اعلام می کنیم:
animateOnScroll(); function animateOnScroll() { const targets = document.querySelectorAll('[data-split-type="scroll"]'); const isAnimatedClass = "is-animated"; const threshold = 0.5; function callback(entries, observer) { entries.forEach((entry) => { const elem = entry.target; if (entry.intersectionRatio >= threshold) { elem.classList.add(isAnimatedClass); } else { elem.classList.remove(isAnimatedClass); } }); } const observer = new IntersectionObserver(callback, { threshold }); for (const target of targets) { observer.observe(target); } }
و در اینجا سبک هایی وجود دارد که در این شرایط ایجاد می شوند:
[data-split-type="scroll"].is-animated .back .char { opacity: 1; transform: none; } [data-split-type="scroll"].is-animated .front .char { opacity: 0; transform: translateY(-101%) skewX(-55deg); }
نتیجه
این همه برای امروز است، مردم! در طول این تمرین، روشی را برای تقسیم متن یک عنصر به کاراکترهای جداگانه و متحرک سازی آنها در اسکرول و شناور ارائه کردیم. امیدوارم دانش جدیدی کسب کرده باشید که از آن برای بهبود این نسخه نمایشی یا ایجاد افکت های متنی مشابه در پروژه های خود استفاده کنید. اگر چنین است، فراموش نکنید که نسخه نمایشی ما را دوست داشته باشید 🙂
بیایید یک بار دیگر به خلقت خود نگاه کنیم:
اگر به راه حل کامل تر و قوی تری برای متحرک سازی کلمات، کاراکترها، خطوط و غیره نیاز دارید، می توانید یک کتابخانه جاوا اسکریپت مانند Splitting.js یا GSAP SplitText.js (اگرچه رایگان نیست).
مثل همیشه، خیلی ممنون که خواندید!