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

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

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

إصدار تجريبي

في ما يلي إصدار YouTube من هذه المشاركة إذا كنت تفضّل الفيديوهات:

نظرة عامة

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

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

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

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

لقطة شاشة لمجموعة أدوات مطوّري البرامج في 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، يوفّر المتصفّح طريقة للتحقّق من استعلامات الوسائط، وقد استخدمت أداة destructur لاستخراج النتيجة المنطقية وإعادة تسميتها من التحقّق من استعلام الوسائط:

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)

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

المصدر

المزيد من العروض التوضيحية والإلهام

ريمكسات من المنتدى