Build a React Marquee Component from Scratch

Build a React Marquee Component from Scratch

Machine-readable: Markdown · JSON API · Site index

Поделиться Telegram VK Бот
Транскрипт Скачать .md
Анализ с AI

Оглавление (3 сегментов)

Segment 1 (00:00 - 05:00)

Привет! В этом видео я покажу вам, как создать эффект «Марк» с помощью React. Для этого мы сначала создадим наш начальный компонент, затем добавим анимацию «Марк», разберемся с функцией умножения, рендерингом серверов с учетом их размера и, наконец, рассмотрим несколько различных анимаций, которые мы можем использовать. Давайте посмотрим на нашу начальную настройку: у нас есть приложение XJS и простая страница, которая отображает текст «Привет». Сначала нам нужно создать компонент «Марк». Мы можем назвать его «Крутой бегущей строкой». Пока что я экспортирую простой компонент из этого файла, и из-за структуры папок я повторно экспортирую его в файл index. ts. Теперь, когда мы создали наш компонент «Марк», мы можем использовать его на странице. Давайте проверим, работает ли это хорошо. Мы видим наш компонент на странице. Теперь давайте создадим этот классный компонент Marquee. Во-первых, ему нужно присвоить свойство children. Свойство children необходимо, поскольку мы хотим, чтобы этот компонент был универсальным, так как мы пока не передаем ему никаких дочерних элементов. На данный момент на странице ничего не видно. Я скачал несколько логотипов брендов и сохранил их в этой папке. Мы можем использовать их для создания эффекта Marquee. Давайте создадим страницу. постоянный. Создайте TS-файл и сохраните здесь наши бренды. Если это константная переменная, я обычно предпочитаю использовать верхний регистр. Мы добавим только названия брендов, а питомец будет динамическим. Теперь, когда у нас есть массив брендов, мы можем использовать функцию map для создания компонента изображения для каждого бренда. Поскольку я использую nexj при указании источника IM, я могу считать папку public корневой. С этими изменениями мы видим наши бренды, но у каждого из них разный размер. Давайте исправим эту проблему, добавив им немного CSS. Я буду использовать model в качестве CSS, поскольку это удобнее, но вы можете сделать то же самое в обычном CSS-файле. Я создам класс с именем brand и импортирую его на свою страницу. Используйте TSX-файл в элементах изображений — это отлично, наши изображения будут более организованы. И да, не забудьте присвоить свойства вашим изображениям. Хорошо, всё готово для создания эффекта бегущей строки. В этой части мы создадим анимацию. Сначала создайте CSS-файл ModelS или обычный CSS-файл для компонента бегущей строки. В этом файле создайте новый класс с именем container. Он будет иметь следующие свойства CSS: мы хотим использовать Flex layout, чтобы предотвратить совместное использование дочерних элементов. Мы установим Flex sharing равным нулю, чтобы предотвратить их рост. Мы установим Flex grow равным нулю. Мы устанавливаем Flex bases равным Auto, чтобы начальный размер дочерних элементов определялся автоматически. Это свойство CSS важно. Мы устанавливаем overflow равным Hidden. Когда логотипы брендов начнут скользить, мы не будем видеть бренды за пределами контейнера. Наконец, мы устанавливаем with равным 100, чтобы контейнер мог заполнить доступное пространство. Давайте добавим CSS в наш компонент. Сначала нам нужно импортировать его, а затем добавить в наш компонент. Из-за свойств Flex логотипы брендов собраны в первом ряду, и из-за overflow hidden мы не можем видеть некоторые логотипы. Теперь, когда у нас есть необходимая компоновка, мы можем добавить анимацию бегущей строки. Я буду использовать frame motion. Для создания анимации нам нужно окутать наших детей движением. Для корректной работы анимации в компоненте div нам необходимо передать объект animate в компонент motion. Давайте создадим этот объект и назовем его Mark animation. Первое свойство, которое мы добавим, — это X, поскольку мы хотим, чтобы наши логотипы двигались справа налево. Мы начнем с 0% и будем двигаться со значением -100%. Для этой анимации справа налево мы зададим несколько значений перехода: Duration определит, сколько времени займет анимация от начала до конца, E определит темп анимации. Мы установим Infinity в свойство Repeat, поскольку хотим, чтобы эта анимация никогда не заканчивалась. Давайте добавим этот объект анимации в наше движение. При обновлении страницы мы видим эту ошибку. Это происходит потому, что мы используем Next. js и маршрутизатор. В данный момент Next. js рассматривает наш компонент как серверный компонент. Для корректной работы анимации нам необходимо указать этот компонент как клиентский. Кстати, я готовлю видео о маршрутизаторе, серверных и клиентских компонентах, так что, если вы не хотите его пропустить, подпишитесь на мой канал. После обновления страницы мы видим, что наша анимация работает не так, как нам нужно, но это нормально. Чтобы исправить проблему с макетом, нам нужно создать еще один класс для наших анимированных контейнеров. Мы можем назвать этот класс Marquee. Он будет иметь те же свойства Flex, что и наш контейнер. Единственное отличие — это свойство средней ширины. Теперь, когда мы создали этот класс, давайте добавим его к нашему анимированному контейнеру. Ура! После этих изменений мы видим, как наш бренд скользит справа налево, однако это не непрерывный поток, поэтому давайте это исправим. Исправление простое: нам нужно просто скопировать и вставить наш анимированный контейнер, и после обновления страницы мы видим непрерывный поток брендов, скользящих

Segment 2 (05:00 - 10:00)

справа налево. Давайте добавим им немного места, добавив отступы к нашему классу бренда. Я буду использовать сокращенную запись `padding`, поэтому это будет... После всей этой работы мы наконец-то получили компонент бегущей строки, но это еще не все. Все работает отлично с нашей текущей структурой, но что, если начальный размер контента меньше размера контейнера? Если я оставлю только логотип Discord, наш компонент Marky будет работать не так, как мы ожидаем. Чтобы исправить эту проблему, нам нужно умножать дочерние элементы до тех пор, пока их размер не станет больше размера контейнера. Чтобы получить размер контейнера и контента, мы можем использовать пользовательский F-хук. Нам нужно состояние для хранения того, сколько раз нам нужно умножить наш контент. Я назову это состояние множителем. Начальное значение будет равно единице, потому что если оно меньше единицы, контент не будет виден. Теперь, когда у нас есть необходимая переменная, мы можем создать функцию для вычисления множителя. Первое, что нам нужно проверить, это пуста ли наша ссылка на контейнер или ссылка на Marky. Если да, то мы не можем выполнить никаких вычислений. Тогда мы используем функцию getbounding client direct, чтобы получить объект, предоставляющий информацию о размере элемента. В этом объекте есть значение wi, которое мы будем использовать в наших вычислениях. Нам нужна ширина как контейнера, так и Marky. Теперь, когда у нас есть все необходимое, мы можем выполнить наши вычисления. Первый случай: если ширина контейнера меньше его ширины. Допустим, у нас есть контейнер размером 350 пикселей, а содержимое — 75 пикселей. Если разделить контейнер на содержимое, получим 4,6. Если умножить содержимое только четыре раза, останется пустое пространство, поэтому мы всегда будем округлять числа в большую сторону. Давайте запишем нашу логику: поскольку мы хотим округлять в большую сторону, мы будем использовать ключевое слово `met`. Если ширина элемента уже больше ширины контейнера, умножать не нужно. Мы создали функцию вычисления, но нигде ее не вызывали. Нам нужно выполнить это вычисление только один раз, поэтому мы можем использовать функцию эффекта. Я добавлю вывод в консоль, чтобы проверить значение вычисленного множителя. Когда я обновлю страницу и открою веб-консоль, мы увидим значение множителя равным единице. Что-то не так. Проблема в том, что мы создали два хука US Rep, но не подключили их ни к одному элементу. Давайте сделаем это. Мы подключим ссылку на контейнер к родительскому контейнеру, а ссылку на Marquee — к новому элементу, который мы создадим. Это потому, что анимированный контейнер может иметь более одного дочернего элемента. Нам нужен только один, чтобы проверить ширину. Нам также нужно добавить CSS к этому элементу. Итак, давайте создадим новый класс и назовем его сначала Marquee. Он будет иметь те же классы Flex, что и другой класс Marquee. После создания класса мы должны добавить это имя класса к нашему компоненту. Хорошо, теперь давайте добавим вывод в консоль и еще раз проверим, правильно ли вычисляется множитель. Отлично, мы видим правильное значение после подключения хука US Ref к компонентам. Мы знаем, сколько раз нужно умножить, но у нас нет функции для умножения дочерних элементов. Давайте создадим такую ​​функцию. Это простая функция, которая принимает один аргумент. Аргумент будет определять, сколько раз мы будем умножать. Мы добавим условие к размеру нашего массива: если значение множителя отрицательное, размер массива будет равен нулю. Я делаю обходной путь, чтобы создать массив с заданным размером. Мы отобразим каждый элемент массива и преобразуем его в компонент React Fragment. Не забудьте добавить свойство key в каждый фрагмент. Мы отрисуем наши дочерние элементы, и это наша функция умножения дочерних элементов. Поскольку эта функция использует дочерние элементы, нам нужно передать дочерние элементы в наш массив зависимостей. И теперь мы можем вызвать эту функцию для первого анимированного контейнера. Мы вызовем ее с умножением минус один. Поскольку у нас уже есть отрисованные дочерние элементы для второго анимированного контейнера, мы можем использовать множитель напрямую. С этими изменениями логотип Discord умножается достаточно, чтобы наша бесконечная анимация Mark работала без сбоев. Однако есть одна маленькая проблема. Позвольте мне показать вам, когда я нажимаю кнопку обновления на секунду, я вижу только два логотипа Discord. Давайте посмотрим, как мы можем исправить эту проблему в следующей части. Хорошо, прежде чем исправлять это. Проблема в том, что Nextjs отображает компонент как на стороне сервера, так и на стороне клиента. Однако на сервере наши хуки эффектов не срабатывают, и поскольку начальное значение множителя равно единице, оно не применяется к дочерним элементам. Если мы предотвратим рендеринг нашего компонента Nextjs на стороне сервера, проблема будет решена. Для этого предположим, что новое состояние называется ` mounted`. Значение по умолчанию будет `false`, и если оно не `true`, мы не будем отображать

Segment 3 (10:00 - 11:00)

наш компонент, поскольку мы нигде не обновляем это значение. Наш компонент исчезнет. Если бы мы использовали фиктивный хук и установили `mounted` в `true` в этом пользовательском эффекте, наш компонент отображался бы только на стороне клиента, поскольку пользовательский эффект не срабатывает на стороне сервера. Хорошо, давайте проверим, сработало ли это. И если нет, то почему? Потому что нам нужно обновить наш пользовательский кукер, где мы вызываем функцию вычисления множителя. Если `mounted` равно `false`, мы не выполняем никаких вычислений, и мы знаем, что `mounted` также добавлено в наш массив зависимостей. Хорошо, это работает, ничего плохого не произойдет, если я обновлю страницу. Что происходит? Давайте исправим эту проблему в следующей части. Чтобы исправить эту проблему, нам нужно отслеживать наш контент и контейнер для этого мы можем использовать API Resize Observer. По сути, Resize Observer запускает функцию вычисления множителя при изменении размеров Marquee или контейнера. Мы не хотим продолжать наблюдение, когда этот компонент исчезает, поэтому мы отключаемся в нашей функции возврата пользовательского эффекта, когда компонент установлен, и используем Resize Observer. Мы больше не видим два логотипа Discord на начальном рендере. Перед завершением видео я хочу показать вам преимущества Framer Motion. Если я удалю опцию Ease, мы увидим, как скорость анимации уменьшается и увеличивается с разной скоростью. Frame Motion дает мне много возможностей, если я захочу, я могу добавить дополнительные ключевые кадры и изменить ощущение анимации, и всегда могу вернуть EAS Linear. Вот и все. Спасибо за просмотр этого видео. Если вы досмотрели до этого момента, не забудьте подписаться, так как появятся новые уроки.

Другие видео автора — Frontend Basics

Ctrl+V

Экстракт Знаний в Telegram

Экстракты и дистилляты из лучших YouTube-каналов — сразу после публикации.

Подписаться

Дайджест Экстрактов

Лучшие методички за неделю — каждый понедельник