إنشاء صور متحركة مقسّمة باستخدام نص

نظرة عامة أساسية حول كيفية إنشاء صور متحركة مقسَّمة للأحرف والكلمات

في هذه المشاركة، أريد أن أشارك أفكارًا حول طرق حلّ المشاكل المتعلقة بالصور المتحركة والتفاعلات التي تتضمّن نصًا مقسّمًا على الويب، والتي تكون بسيطة وسهلة الاستخدام وتعمل على جميع المتصفّحات. جرِّب العرض التوضيحي.

العرض التوضيحي

إذا كنت تفضّل مشاهدة فيديو، إليك نسخة من هذا المنشور على YouTube:

نظرة عامة

يمكن أن تكون الصور المتحركة للنصوص المقسّمة رائعة. سنقدّم في هذه المشاركة لمحة بسيطة عن إمكانات الرسوم المتحركة، ولكنّها ستوفّر لك أساسًا يمكنك البناء عليه. والهدف هو تحريك العناصر بشكل تدريجي. يجب أن يكون النص قابلاً للقراءة تلقائيًا، مع إنشاء الرسوم المتحركة فوقه. يمكن أن تكون تأثيرات الحركة على النص المنقسم باهظة الثمن ومزعجة، لذا لن نعدّل سوى HTML، أو سنطبّق أنماط الحركة إذا كان المستخدم موافقًا على الحركة.

في ما يلي نظرة عامة على سير العمل والنتائج:

  1. إعداد متغيرات شرطية للحدّ من الحركة في CSS وJavaScript
  2. إعداد أدوات تقسيم النصوص في JavaScript
  3. تنسيق الشروط والأدوات المساعدة عند تحميل الصفحة
  4. كتابة انتقالات وحركات CSS للحروف والكلمات (الجزء الرائع!).

في ما يلي معاينة للنتائج الشرطية التي نسعى إلى تحقيقها:

لقطة شاشة لأدوات مطوّري البرامج في Chrome مع فتح لوحة "العناصر" وضبط خيار "تقليل الحركة" على "تقليل"، ويظهر العنوان h1 بدون تقسيم
يفضّل المستخدم تقليل الحركة: النص مقروء / غير مقسّم

إذا كان المستخدم يفضّل تقليل الحركة، لن نعدّل مستند HTML ولن نعرض أي رسوم متحركة. إذا كانت الحركة مناسبة، سنقسمها إلى أجزاء. في ما يلي معاينة لرمز HTML بعد أن يقسّم JavaScript النص حسب الحرف.

لقطة شاشة لأدوات مطوّري البرامج في Chrome مع فتح لوحة "العناصر" وضبط خيار "تقليل الحركة" على "تقليل"، ويظهر العنوان h1 بدون تقسيم
المستخدم لا يمانع في الحركة؛ تم تقسيم النص إلى عناصر <span> متعددة

إعداد شروط الحركة

سيتم استخدام طلب البحث عن الوسائط @media (prefers-reduced-motion: reduce) المتاح بسهولة من CSS وJavaScript في هذا المشروع. طلب البحث عن الوسائط هذا هو الشرط الأساسي الذي نستخدمه لتحديد ما إذا كان سيتم تقسيم النص أم لا. سيتم استخدام طلب البحث عن الوسائط في CSS لحجب عمليات الانتقال والحركات، بينما سيتم استخدام طلب البحث عن الوسائط في JavaScript لحجب التعديل على HTML.

إعداد الشرط CSS

استخدمتُ PostCSS لتفعيل بنية المستوى 5 من طلبات البحث عن الوسائط، حيث يمكنني تخزين قيمة منطقية لطلب البحث عن الوسائط في متغير:

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

إعداد الشرط في JavaScript

في JavaScript، يوفّر المتصفّح طريقة للتحقّق من طلبات البحث عن الوسائط، وقد استخدمت تفكيك البنية لاستخراج وإعادة تسمية النتيجة المنطقية من عملية التحقّق من طلب البحث عن الوسائط:

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

يمكنني بعد ذلك اختبار motionOK، وتغيير المستند فقط إذا لم يطلب المستخدم تقليل الحركة.

if (motionOK) {
  // document split manipulations
}

يمكنني التحقّق من القيمة نفسها باستخدام PostCSS لتفعيل بنية @nest من المسودة 1 لميزة "التداخل". يتيح لي ذلك تخزين كل المعلومات المنطقية المتعلقة بالرسوم المتحركة ومتطلبات الأسلوب الخاصة بالعنصر الرئيسي والعناصر الفرعية في مكان واحد:

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

باستخدام خاصية PostCSS المخصّصة وقيمة منطقية في JavaScript، أصبحنا جاهزين لترقية التأثير بشكل مشروط. يقودنا ذلك إلى القسم التالي حيث سأشرح بالتفصيل رمز JavaScript لتحويل السلاسل إلى عناصر.

تقسيم النص

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

  1. إنشاء دوال مساعدة في JavaScript لتقسيم السلاسل إلى عناصر
  2. تنظيم استخدام هذه الأدوات المساعدة

دالة مساعدة لتقسيم الأحرف

يمكنك البدء بدالة تأخذ سلسلة وتعرض كل حرف في مصفوفة.

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

لقد ساعدت صيغة spread من ES6 في جعل هذه المهمة سريعة.

دالة مساعدة لتقسيم الكلمات

على غرار تقسيم الأحرف، تأخذ هذه الدالة سلسلة وتعرض كل كلمة في صفيف.

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

تتيح لنا طريقة split() في سلاسل JavaScript تحديد الأحرف التي نريد تقسيم السلسلة عندها. لقد مررتُ بمساحة فارغة، ما يشير إلى تقسيم بين الكلمات.

إنشاء دالة مساعدة للمربّعات

يتطلّب التأثير مربّعات لكل حرف، ونرى في هذه الدوال أنّه يتم استدعاء 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 من JavaScript للعثور على العناصر وإنشاء مربعات للأحرف أو الكلمات. يتم استخدام السمة 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>

العثور على عناصر من JavaScript

استخدمتُ بنية أداة اختيار لغة CSS لتحديد ما إذا كانت السمة متوفّرة من أجل جمع قائمة بالعناصر التي تريد تقسيم نصها:

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

العثور على عناصر من CSS

استخدمتُ أيضًا أداة اختيار وجود السمة في CSS لمنح جميع الرسوم المتحركة للأحرف الأنماط الأساسية نفسها. لاحقًا، سنستخدم قيمة السمة لإضافة أنماط أكثر تحديدًا لتحقيق تأثير معيّن.

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

تقسيم النص في مكانه

بالنسبة إلى كل هدف مقسّم نعثر عليه في JavaScript، سنقسم النص استنادًا إلى قيمة السمة ونربط كل سلسلة بـ <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)
  })
}

يمكن قراءة JavaScript باللغة الإنجليزية على النحو التالي:

  1. استورِد بعض دوال الأداة المساعدة.
  2. تحقَّق مما إذا كان يمكن للمستخدم استخدام ميزة "التقاط الحركة"، وإذا لم يكن ذلك ممكنًا، لا تتّخذ أي إجراء.
  3. لكل عنصر تريد تقسيمه
    1. قسِّمها حسب الطريقة التي تريد تقسيمها بها.
    2. استبدال النص بالعناصر

تقسيم الحركات وتأثيرات الانتقال

لقد أتاحت عملية تقسيم المستندات المذكورة أعلاه إمكانية إنشاء العديد من الصور المتحركة والمؤثرات باستخدام CSS أو JavaScript. تتضمّن هذه المقالة بعض الروابط في أسفلها لمساعدتك في استلهام أفكار حول تقسيم المحتوى.

حان الوقت لإظهار ما يمكنك فعله باستخدام هذه الميزة. سأشارك 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 أو استضافة عرضك التوضيحي الخاص، ثم إرسال تغريدة إليّ تتضمّن العرض، وسأضيفه إلى قسم &quot;ريمكسات من المنتدى&quot; أدناه.

المصدر

المزيد من العروض التوضيحية والأفكار

ريمكسات من إنشاء المنتدى