ساخت انیمیشن های متن تقسیم شده

یک نمای کلی از نحوه ساخت انیمیشن های حروف و کلمه تقسیم شده.

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

نسخه ی نمایشی

اگر ویدیو را ترجیح می دهید، در اینجا یک نسخه YouTube از این پست وجود دارد:

نمای کلی

انیمیشن های متن تقسیم شده می توانند شگفت انگیز باشند. ما در این پست به سختی سطح پتانسیل انیمیشن را بررسی خواهیم کرد، اما پایه ای برای ساختن آن فراهم می کند. هدف این است که به تدریج متحرک سازی شود. متن باید به‌طور پیش‌فرض قابل خواندن باشد و انیمیشن روی آن ساخته شده باشد. افکت‌های حرکت متنی تقسیم‌شده می‌توانند عجیب و غریب و بالقوه مختل شوند، بنابراین ما فقط در صورتی HTML را دستکاری می‌کنیم یا سبک‌های حرکت را اعمال می‌کنیم که کاربر با حرکت خوب باشد.

در اینجا یک مرور کلی از گردش کار و نتایج آورده شده است:

  1. متغیرهای شرطی حرکت کاهش یافته را برای CSS و JS آماده کنید .
  2. ابزارهای تقسیم متن را در جاوا اسکریپت آماده کنید .
  3. شرایط و ابزارهای کاربردی را در بارگذاری صفحه هماهنگ کنید .
  4. انتقال CSS و انیمیشن برای حروف و کلمات بنویسید (بخش rad!).

در اینجا پیش نمایشی از نتایج مشروط را مشاهده می کنیم:

اسکرین شات از ابزارهای توسعه کروم با پانل Elements باز و حرکت کاهش یافته روی "کم کردن" تنظیم شده است و h1 بدون تقسیم نشان داده می شود
کاربر حرکت کاهش یافته را ترجیح می دهد: متن خوانا / تقسیم نشده است

اگر کاربر حرکت کاهش یافته را ترجیح می دهد، سند HTML را به حال خود رها می کنیم و هیچ انیمیشنی انجام نمی دهیم. اگر حرکت خوب بود، جلو می رویم و آن را تکه تکه می کنیم. در اینجا پیش نمایشی از HTML پس از تقسیم متن توسط جاوا اسکریپت به حروف آمده است.

اسکرین شات از ابزارهای توسعه کروم با پانل Elements باز و حرکت کاهش یافته روی "کم کردن" تنظیم شده است و h1 بدون تقسیم نشان داده می شود
کاربر با حرکت مشکلی ندارد. متن به چند عنصر <span> تقسیم می شود

آماده سازی شرط حرکت

پرس و جوی رسانه @ که به راحتی در دسترس است @media (prefers-reduced-motion: reduce) از CSS و جاوا اسکریپت در این پروژه استفاده خواهد شد. این درخواست رسانه شرط اولیه ما برای تصمیم گیری در مورد تقسیم یا عدم تقسیم متن است. پرس و جو رسانه CSS برای پنهان کردن انتقال ها و انیمیشن ها استفاده می شود، در حالی که پرس و جو رسانه جاوا اسکریپت برای جلوگیری از دستکاری HTML استفاده می شود.

آماده سازی CSS شرطی

من از PostCSS برای فعال کردن سینتکس Media Queries Level 5 استفاده کردم، جایی که می‌توانم یک query boolean رسانه را در یک متغیر ذخیره کنم:

@custom-media --motionOK (prefers-reduced-motion: no-preference);

آماده سازی JS شرطی

در جاوا اسکریپت، مرورگر راهی برای بررسی پرس و جوهای رسانه ارائه می دهد، من از ساختارشکنی برای استخراج و تغییر نام نتیجه بولی از بررسی پرس و جو رسانه استفاده کردم:

const {matches:motionOK} = window.matchMedia(
  '(prefers-reduced-motion: no-preference)'
)

سپس می‌توانم motionOK را آزمایش کنم و فقط در صورتی سند را تغییر دهم که کاربر درخواست کاهش حرکت را نداشته باشد.

if (motionOK) {
  // document split manipulations
}

می‌توانم همان مقدار را با استفاده از PostCSS برای فعال کردن نحو @nest از Nesting Draft 1 بررسی کنم. این به من امکان می دهد تمام منطق انیمیشن و سبک مورد نیاز آن برای والدین و فرزندان را در یک مکان ذخیره کنم:

letter-animation {
  @media (--motionOK) {
    /* animation styles */
  }
}

با ویژگی سفارشی PostCSS و بولین جاوا اسکریپت، ما آماده هستیم تا افکت را به صورت مشروط ارتقا دهیم. این ما را به بخش بعدی هدایت می کند که در آن جاوا اسکریپت را برای تبدیل رشته ها به عناصر تجزیه می کنم.

تقسیم متن

حروف متن، کلمات، خطوط و غیره را نمی توان به صورت جداگانه با CSS یا JS متحرک کرد. برای رسیدن به اثر، به جعبه هایی نیاز داریم. اگر بخواهیم هر حرف را متحرک کنیم، هر حرف باید یک عنصر باشد. اگر بخواهیم هر کلمه را متحرک کنیم، هر کلمه باید یک عنصر باشد.

  1. توابع ابزار جاوا اسکریپت را برای تقسیم رشته ها به عناصر ایجاد کنید
  2. استفاده از این ابزارها را هماهنگ کنید

عملکرد ابزار تقسیم حروف

یک مکان سرگرم کننده برای شروع، تابعی است که یک رشته را می گیرد و هر حرف را در یک آرایه برمی گرداند.

export const byLetter = text =>
  [...text].map(span)

نحو گسترش از ES6 واقعا کمک کرد که این کار سریع باشد.

عملکرد سودمند تقسیم کلمات

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

export const byWord = text =>
  text.split(' ').map(span)

متد split() در رشته های جاوا اسکریپت به ما اجازه می دهد تا مشخص کنیم کدام کاراکترها را برش دهیم. از یک فضای خالی گذشتم که نشان دهنده شکاف بین کلمات است.

ساخت جعبه عملکرد ابزار

این افکت به کادرهایی برای هر حرف نیاز دارد، و ما در آن توابع می بینیم که map() با یک تابع span() فراخوانی می شود. در اینجا تابع span() است.

const span = (text, index) => {
  const node = document.createElement('span')

  node.textContent = text
  node.style.setProperty('--index', index)

  return node
}

توجه به این نکته ضروری است که یک ویژگی سفارشی به نام --index با موقعیت آرایه تنظیم می شود. داشتن جعبه‌هایی برای انیمیشن‌های حروف عالی است، اما داشتن یک شاخص برای استفاده در CSS افزوده‌ای به ظاهر کوچک با تأثیر زیاد است. قابل توجه ترین در این تاثیر بزرگ خیره کننده است. ما می‌توانیم --index به عنوان راهی برای جبران انیمیشن‌ها برای یک ظاهر مبهم استفاده کنیم.

نتیجه گیری تاسیسات

ماژول splitting.js در حال تکمیل است:

const span = (text, index) => {
  const node = document.createElement('span')

  node.textContent = text
  node.style.setProperty('--index', index)

  return node
}

export const byLetter = text =>
  [...text].map(span)

export const byWord = text =>
  text.split(' ').map(span)

بعدی وارد کردن و استفاده از این توابع byLetter() و byWord() است.

تقسیم ارکستراسیون

با استفاده از ابزارهای تقسیم آماده استفاده، کنار هم قرار دادن همه آنها به این معنی است:

  1. یافتن عناصری که باید تقسیم شوند
  2. تقسیم آنها و جایگزینی متن با HTML

پس از آن، CSS کنترل می شود و عناصر / جعبه ها را متحرک می کند.

یافتن عناصر

من انتخاب کردم که از ویژگی ها و مقادیر برای ذخیره اطلاعات در مورد انیمیشن مورد نظر و نحوه تقسیم متن استفاده کنم. من دوست داشتم این گزینه های اعلامی را در HTML قرار دهم. ویژگی split-by از جاوا اسکریپت برای یافتن عناصر و ایجاد کادرهایی برای حروف یا کلمات استفاده می شود. ویژگی letter-animation یا word-animation از CSS برای هدف قرار دادن کودکان عناصر و اعمال تبدیل ها و انیمیشن ها استفاده می شود.

در اینجا نمونه ای از HTML است که این دو ویژگی را نشان می دهد:

<h1 split-by="letter" letter-animation="breath">animated letters</h1>
<h1 split-by="word" word-animation="trampoline">hover the words</h1>

یافتن عناصر از جاوا اسکریپت

من از سینتکس انتخابگر CSS برای حضور صفت برای جمع‌آوری لیست عناصری که می‌خواهند متنشان تقسیم شود استفاده کردم:

const splitTargets = document.querySelectorAll('[split-by]')

یافتن عناصر از CSS

من همچنین از انتخابگر خصیصه حضور در CSS استفاده کردم تا به همه انیمیشن های حروف سبک های پایه یکسانی بدهم. بعداً از مقدار ویژگی برای اضافه کردن سبک های خاص تر برای دستیابی به یک اثر استفاده می کنیم.

letter-animation {
  @media (--motionOK) {
    /* animation styles */
  }
}

تقسیم متن در جای خود

برای هر یک از اهداف تقسیم شده ای که در جاوا اسکریپت پیدا می کنیم، متن آنها را بر اساس مقدار مشخصه تقسیم می کنیم و هر رشته را به یک <span> نگاشت می کنیم. سپس می توانیم متن عنصر را با کادرهایی که ساخته ایم جایگزین کنیم:

splitTargets.forEach(node => {
  const type = node.getAttribute('split-by')
  let nodes = null

  if (type === 'letter') {
    nodes = byLetter(node.innerText)
  }
  else if (type === 'word') {
    nodes = byWord(node.innerText)
  }

  if (nodes) {
    node.firstChild.replaceWith(...nodes)
  }
})

نتیجه گیری ارکستراسیون

index.js در حال تکمیل:

import {byLetter, byWord} from './splitting.js'

const {matches:motionOK} = window.matchMedia(
  '(prefers-reduced-motion: no-preference)'
)

if (motionOK) {
  const splitTargets = document.querySelectorAll('[split-by]')

  splitTargets.forEach(node => {
    const type = node.getAttribute('split-by')
    let nodes = null

    if (type === 'letter')
      nodes = byLetter(node.innerText)
    else if (type === 'word')
      nodes = byWord(node.innerText)

    if (nodes)
      node.firstChild.replaceWith(...nodes)
  })
}

جاوا اسکریپت را می توان به انگلیسی زیر خواند:

  1. برخی از توابع ابزار کمکی را وارد کنید.
  2. بررسی کنید که آیا حرکت برای این کاربر خوب است یا نه، اگر نه هیچ کاری انجام ندهید.
  3. برای هر عنصری که می خواهد تقسیم شود.
    1. آنها را بر اساس نحوه تقسیم آنها تقسیم کنید.
    2. متن را با عناصر جایگزین کنید.

تقسیم انیمیشن ها و انتقال ها

دستکاری اسناد تقسیم بالا به تازگی بسیاری از انیمیشن ها و افکت های بالقوه را با CSS یا جاوا اسکریپت باز کرده است. چند پیوند در انتهای این مقاله وجود دارد که به شما کمک می کند تا پتانسیل تقسیم خود را تقویت کنید.

وقت آن است که نشان دهید با این چه کاری می توانید انجام دهید! من 4 انیمیشن و انتقال مبتنی بر CSS را به اشتراک خواهم گذاشت. 🤓

حروف را تقسیم کنید

به عنوان پایه ای برای افکت های تقسیم نامه، CSS زیر را مفید یافتم. من همه انتقال‌ها و انیمیشن‌ها را پشت درخواست رسانه متحرک قرار می‌دهم و سپس به هر یک از حرف‌های فرزند جدید یک ویژگی نمایش span یک سبک برای کارهایی که باید با فضاهای سفید انجام شود می‌دهم:

[letter-animation] > span {
  display: inline-block;
  white-space: break-spaces;
}

سبک فضاهای سفید مهم است تا دهانه هایی که فقط یک فضا هستند توسط موتور چیدمان جمع نشود. در حال حاضر به چیزهای سرگرم کننده دولتی.

نمونه حروف تقسیم انتقال

این مثال از انتقال CSS به افکت متن تقسیم شده استفاده می کند. با انتقال، ما به حالت‌هایی نیاز داریم که موتور بین آنها متحرک شود، و من سه حالت را انتخاب کردم: بدون شناور، شناور در جمله، شناور روی یک حرف.

هنگامی که کاربر جمله ای را که با نام مستعار کانتینر نامیده می شود نگه می دارد، همه بچه ها را به سمت عقب می کشم، انگار که کاربر آنها را دورتر می راند. سپس، همانطور که کاربر یک نامه را نگه می دارد، آن را جلو می آورم.

@media (--motionOK) {
  [letter-animation="hover"] {
    &:hover > span {
      transform: scale(.75);
    }

    & > span {
      transition: transform .3s ease;
      cursor: pointer;

      &:hover {
        transform: scale(1.25);
      }
    }
  }
}

مثال حروف تقسیم شده را متحرک کنید

این مثال از یک انیمیشن از پیش تعریف شده @keyframe برای متحرک سازی بی نهایت هر حرف استفاده می کند و از شاخص خصوصیات سفارشی درون خطی برای ایجاد یک افکت گیج کننده استفاده می کند.

@media (--motionOK) {
  [letter-animation="breath"] > span {
    animation:
      breath 1200ms ease
      calc(var(--index) * 100 * 1ms)
      infinite alternate;
  }
}

@keyframes breath {
  from {
    animation-timing-function: ease-out;
  }
  to {
    transform: translateY(-5px) scale(1.25);
    text-shadow: 0 0 25px var(--glow-color);
    animation-timing-function: ease-in-out;
  }
}

کلمات را تقسیم کنید

در این مثال‌ها، Flexbox به‌عنوان یک نوع ظرف برای من کار می‌کرد، و به خوبی از واحد ch به عنوان یک طول شکاف سالم استفاده می‌کرد.

word-animation {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 1ch;
}
ابزارهای برنامه‌نویس Flexbox که شکاف بین کلمات را نشان می‌دهند

مثال تقسیم کلمات انتقالی

در این مثال انتقال من دوباره از شناور استفاده می کنم. از آنجایی که این افکت در ابتدا محتوا را تا زمان شناور پنهان می‌کند، مطمئن شدم که تعامل و سبک‌ها فقط در صورتی اعمال می‌شوند که دستگاه قابلیت شناور را داشته باشد.

@media (hover) {
  [word-animation="hover"] {
    overflow: hidden;
    overflow: clip;

    & > span {
      transition: transform .3s ease;
      cursor: pointer;

      &:not(:hover) {
        transform: translateY(50%);
      }
    }
  }
}

متحرک سازی کلمات تقسیم شده مثال

در این مثال انیمیشن، من دوباره از CSS @keyframes برای ایجاد یک انیمیشن نامحدود در یک پاراگراف معمولی از متن استفاده می‌کنم.

[word-animation="trampoline"] > span {
  display: inline-block;
  transform: translateY(100%);
  animation:
    trampoline 3s ease
    calc(var(--index) * 150 * 1ms)
    infinite alternate;
}

@keyframes trampoline {
  0% {
    transform: translateY(100%);
    animation-timing-function: ease-out;
  }
  50% {
    transform: translateY(0);
    animation-timing-function: ease-in;
  }
}

نتیجه گیری

حالا که می دانی من چگونه این کار را انجام دادم، شما چطور؟! 🙂

بیایید رویکردهایمان را متنوع کنیم و همه راه‌های ساخت در وب را بیاموزیم. یک Codepen ایجاد کنید یا نسخه نمایشی خود را میزبانی کنید، با آن برای من توییت کنید، و من آن را به بخش ریمیکس های انجمن در زیر اضافه می کنم.

منبع

دمو و الهام بیشتر

ریمیکس های انجمن