Для этой четвертой и последней статьи нашего небольшая серия по одноэлементным погрузчикам, мы собираемся исследовать 3D-паттерны. При создании 3D-элемента сложно представить, что всего одного HTML-элемента достаточно, чтобы имитировать что-то вроде всех шести граней куба. Но, может быть, нам сойдет с рук что-то более кубическое. такое как вместо этого показывая только три передние стороны фигуры — это вполне возможно, и это то, что мы собираемся сделать вместе.
Серия статей
- Загрузчики отдельных элементов: Spinner
- Загрузчики отдельных элементов: точки
- Одноэлементные загрузчики: стержни
- Загрузчики отдельных элементов: переход на 3D — Вы здесь
Загрузчик разделенных кубов
Вот 3D-загрузчик, в котором куб разделен на две части, но состоит только из одного элемента:
Каждая половина куба сделана с использованием псевдоэлемента:
Круто, правда?! Мы можем использовать конический градиент с помощью CSS. clip-path
на элементе ::before
и ::after
псевдонимы для имитации трех видимых граней трехмерного куба. Отрицательный запас — это то, что сближает два псевдообъекта, чтобы они перекрывались и имитировали полный куб. Остальная часть нашей работы в основном заключается в анимации этих двух половин, чтобы получить аккуратные загрузчики!
Давайте посмотрим на визуализацию, которая объясняет математику точек клип-пути, используемых для создания этого кубоподобного элемента:
У нас есть переменные и уравнение, так что давайте заставим их работать. Во-первых, мы установим наши переменные и установим размер для основного .loader
элемент:
.loader { --s: 150px; /* control the size */ --_d: calc(0.353 * var(--s)); /* 0.353 = sin(45deg)/2 */ width: calc(var(--s) + var(--_d)); aspect-ratio: 1; display: flex;
}
Пока ничего слишком сумасшедшего. У нас есть 150px
квадрат, настроенный как гибкий контейнер. Теперь устанавливаем наши псевдо:
.loader::before,
.loader::after { content: ""; flex: 1;
}
Это две половинки в .loader
контейнер. Нам нужно закрасить их, вот где наш конический градиент удары в:
.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}
Градиент есть, но это выглядит странно, Нам надо прикрепите его к элементу:
.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0); clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}
Давайте удостоверимся, что две половины перекрываются отрицательная маржа:
.loader::before { margin-right: calc(var(--_d) / -2);
} .loader::after { margin-left: calc(var(--_d) / -2);
}
Теперь заставим их двигаться!
.loader::before,
.loader::after { /* same as before */ animation: load 1.5s infinite cubic-bezier(0, .5, .5, 1.8) alternate;
} .loader::after { /* same as before */ animation-delay: -.75s
} @keyframes load{ 0%, 40% { transform: translateY(calc(var(--s) / -4)) } 60%, 100% { transform: translateY(calc(var(--s) / 4)) }
}
Вот финальная демонстрация еще раз:
Загрузчик куба прогресса
Давайте воспользуемся той же техникой для создания 3D-загрузчика прогресса. Да еще только один элемент!
Мы ничего не меняем в моделировании куба так же, как делали это раньше, за исключением изменения высоты загрузчика и соотношения сторон. Анимация, которую мы делаем, основана на удивительно простой технике, когда мы обновляем ширину левой стороны, в то время как правая сторона заполняет оставшееся пространство благодаря flex-grow: 1
.
Первый шаг — добавить прозрачности правой стороне, используя opacity
:
Это имитирует эффект, когда одна сторона куба заполнена, а другая пуста. Затем мы обновляем цвет левой стороны. Для этого мы либо обновляем три цвета внутри конического градиента, либо делаем это, добавляя цвет фона с помощью background-blend-mode
:
.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply;
}
Этот трюк позволяет нам обновить цвет только один раз. Правая часть загрузчика смешивается с тремя оттенками белого из конического градиента, чтобы создать три новых оттенка нашего цвета, хотя мы используем только одно значение цвета. Обман цвета!
Давайте анимируем ширину левой стороны загрузчика:
Упс, анимация вначале немного странная! Заметили, как это начинается за пределами куба? Это потому, что мы начинаем анимацию с 0%
ширина. Но из-за clip-path
и отрицательная маржа, которую мы используем, вместо этого нам нужно начать с нашего --_d
переменная, которую мы использовали для определения clip-path
баллы и отрицательная маржа:
@keyframes load { 0%, 5% {width: var(--_d); } 95%, 100% {width: 100%; }
}
Это немного лучше:
Но мы можем сделать эту анимацию еще более плавной. Вы заметили, что мы кое-что упустили? Позвольте мне показать вам скриншот, чтобы сравнить, как должна выглядеть окончательная демонстрация с последней демонстрацией:
Это нижняя грань куба! Поскольку второй элемент прозрачен, нам нужно увидеть нижнюю грань этого прямоугольника, как вы можете видеть в левом примере. Это тонко, но должно быть там!
Мы можем добавить градиент к основному элементу и обрезать его, как мы сделали с псевдоэлементами:
background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat;
Вот полный код, когда все собрано вместе:
.loader { --s: 100px; /* control the size */ --_d: calc(0.353*var(--s)); /* 0.353 = sin(45deg) / 2 */ height: var(--s); aspect-ratio: 3; display: flex; background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat; clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}
.loader::before,
.loader::after { content: ""; clip-path: inherit; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}
.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply; margin-right: calc(var(--_d) / -2); animation: load 2.5s infinite linear;
}
.loader:after { flex: 1; margin-left: calc(var(--_d) / -2); opacity: 0.4;
} @keyframes load { 0%, 5% { width: var(--_d); } 95%, 100% { width: 100%; }
}
Вот и все! Мы только что применили хитрую технику, использующую псевдоэлементы, конические градиенты, отсечение, смешивание фона и отрицательные поля, чтобы получить не один, а два симпатичные 3D-загрузчики с одним элементом в разметке.
Больше 3D
Мы можем пойти дальше и смоделировать бесконечное количество 3D-кубов, используя один элемент — да, это возможно! Вот сетка кубов:
Эта демонстрация и следующие демонстрации не поддерживаются в Safari на момент написания.
Сумасшедший, верно? Теперь мы создаем повторяющийся паттерн из кубов, сделанный из одного элемента… и никаких псевдонимов! Я не буду вдаваться в подробности математики, которую мы используем (здесь есть очень конкретные числа), но вот рисунок, показывающий, как мы сюда попали:
Сначала мы используем conic-gradient
чтобы создать повторяющийся узор куба. Повторение шаблона контролируется тремя переменными:
--size
: соответствует своему названию, управляет размером каждого куба.--m
: представляет количество столбцов.--n
: это количество строк.--gap
: это зазор или расстояние между кубами
.cube { --size: 40px; --m: 4; --n: 5; --gap :10px; aspect-ratio: var(--m) / var(--n); width: calc(var(--m) * (1.353 * var(--size) + var(--gap))); background: conic-gradient(from -90deg at var(--size) calc(0.353 * var(--size)), #249FAB 135deg, #81C5A3 0 270deg, #26609D 0) /* update the colors here */ 0 0 / calc(100% / var(--m)) calc(100% / var(--n));
}
Затем мы применяем слой-маску, используя другой шаблон того же размера. Это самая сложная часть этой идеи. Используя комбинацию из linear-gradient
и еще один conic-gradient
мы вырежем несколько частей нашего элемента, чтобы были видны только формы куба.
.cube { /* etc. */ mask: linear-gradient(to bottom right, #0000 calc(0.25 * var(--size)), #000 0 calc(100% - calc(0.25 * var(--size)) - 1.414 * var(--gap)), #0000 0), conic-gradient(from -90deg at right var(--gap) bottom var(--gap), #000 90deg, #0000 0); mask-size: calc(100% / var(--m)) calc(100% / var(--n)); mask-composite: intersect;
}
Код может показаться немного сложным, но благодаря переменным CSS все, что нам нужно сделать, это обновить несколько значений, чтобы управлять нашей матрицей кубов. Нужна сетка 10⨉10? Обновите --m
и --n
переменные для 10
. Нужен более широкий зазор между кубами? Обновите --gap
ценность. Значения цвета используются только один раз, поэтому обновите их для новой цветовой палитры!
Теперь, когда у нас есть еще одна 3D-техника, давайте воспользуемся ею для создания вариантов загрузчика, поэкспериментировав с различными анимациями. Например, как насчет повторяющегося шаблона кубов, бесконечно скользящих слева направо?
Этот загрузчик определяет четыре куба в одной строке. Это означает, что наш --n
Значение 4
и --m
равно 1
. Другими словами, они нам больше не нужны!
Вместо этого мы можем работать с --size
и --gap
переменные в контейнере сетки:
.loader { --size: 70px; --gap: 15px; width: calc(3 * (1.353 * var(--size) + var(--gap))); display: grid; aspect-ratio: 3;
}
Это наш контейнер. У нас есть четыре куба, но мы хотим показывать только три в контейнере за раз, чтобы у нас всегда был один вдвигающийся, а другой выдвигающийся. Вот почему мы учитываем ширину 3
и установить соотношение сторон 3
так же.
Давайте удостоверимся, что наш шаблон куба настроен на ширину четырех кубов. Мы собираемся сделать это на контейнере ::before
псевдоэлемент:
.loader::before { content: ""; width: calc(4 * 100% / 3); /* Code to create four cubes */
}
Теперь, когда у нас есть четыре куба в контейнере из трех кубов, мы можем выровнять шаблон куба до конца контейнера сетки, чтобы переполнить его, показывая последние три куба:
.loader { /* same as before */ justify-content: end;
}
Вот что у нас есть на данный момент, с красным контуром, показывающим границы контейнера сетки:
Теперь все, что нам нужно сделать, это переместить псевдоэлемент вправо, добавив нашу анимацию:
@keyframes load { to { transform: translate(calc(100% / 4)); }
}
Вы поняли суть анимации? Давайте завершим это, спрятав узор переливающегося куба и добавив немного маскировки, чтобы создать тот эффект затухания, который был в начале и в конце:
.loader { --size: 70px; --gap: 15px; width: calc(3*(1.353*var(--s) + var(--g))); display: grid; justify-items: end; aspect-ratio: 3; overflow: hidden; mask: linear-gradient(90deg, #0000, #000 30px calc(100% - 30px), #0000);
}
Мы можем сделать это намного более гибким, введя переменную, --n
, чтобы указать, сколько кубов одновременно отображается в контейнере. А так как общее количество кубиков в узоре должно быть на единицу больше, чем --n
, мы можем выразить это как calc(var(--n) + 1)
.
Вот полное:
ОК, еще один похожий 3D-загрузчик, но в котором кубы меняют цвет последовательно, а не скользят:
Мы будем полагаться на анимированный фон с background-blend-mode
для этого:
.loader { /* ... */ background: linear-gradient(#ff1818 0 0) 0% / calc(100% / 3) 100% no-repeat, /* ... */; background-blend-mode: multiply; /* ... */ animation: load steps(3) 1.5s infinite;
}
@keyframes load { to { background-position: 150%; }
}
Я удалил лишний код, который использовался для создания того же макета, что и в предыдущем примере, но с тремя кубами вместо четырех. Здесь я добавляю градиент, определенный с определенным цветом, который смешивается с коническим градиентом, точно так же, как мы делали ранее для 3D-загрузчика индикатора выполнения.
Оттуда он анимирует фоновый градиент background-position
в качестве трехэтапной анимации, чтобы кубики мигали цветами по одному.
Если вы не знакомы со значениями, которые я использую для background-position
и фоновый синтаксис, я настоятельно рекомендую одна из моих предыдущих статей и один из мои ответы на переполнение стека. Там вы найдете очень подробное объяснение.
Можем ли мы обновить количество кубов, чтобы сделать его переменным?
Да, у меня есть решение для этого, но я бы хотел, чтобы вы попробовали его, а не вставляли сюда. Возьмите то, что мы узнали из предыдущего примера, и попробуйте сделать то же самое с этим — затем поделитесь своей работой в комментариях!
Вариаций масса!
Как и в трех других статьях этой серии, я хотел бы вдохновить вас на создание собственных загрузчиков. Вот коллекция, которая включает в себя 3D-загрузчики, которые мы сделали вместе, а также несколько других, чтобы дать волю вашему воображению:
Это обертка
Я очень надеюсь, что вам понравилось проводить со мной время за созданием одноэлементных загрузчиков последние несколько недель. Это безумие, что мы начали с, казалось бы, простого счетчика, а затем постепенно добавляли новые части, чтобы работать самостоятельно, вплоть до 3D-техник, которые до сих пор используют только один элемент в разметке. Именно так выглядит CSS, когда мы используем его возможности: масштабируемый, гибкий и многоразовый.
Еще раз спасибо за чтение этой небольшой серии! Я подпишусь, напомнив вам, что у меня есть коллекция из более 500 погрузчиков если вы ищете больше идей и вдохновения.
Серия статей
- Загрузчики отдельных элементов: Spinner
- Загрузчики отдельных элементов: точки
- Одноэлементные загрузчики: стержни
- Загрузчики отдельных элементов: переход на 3D — Вы здесь
Загрузчики отдельных элементов: переход на 3D! первоначально опубликовано CSS-хитрости, Вам следует получить информационный бюллетень.
- "
- 10
- 3d
- 9
- 95%
- a
- О нас
- добавленный
- Все
- позволяет
- всегда
- Другой
- Применить
- около
- гайд
- статьи
- фон
- , так как:
- до
- за
- Лучшая
- между
- Немного
- строить
- Может получить
- код
- лыжных шлемов
- сочетание
- комплекс
- Container
- содержание
- контроль
- контрольная
- Создайте
- Создающий
- подробность
- подробный
- DID
- различный
- Дисплей
- расстояние
- Dropbox
- каждый
- эффект
- установить
- и т.д
- многое
- точно,
- пример
- Больше
- Face
- лица
- знакомый
- фигура
- конец
- First
- гибкого
- после
- от
- передний
- полный
- далее
- разрыв
- будет
- сетка
- имеющий
- высота
- здесь
- очень
- надежды
- Как
- HTTPS
- идея
- идеи
- воображение
- В других
- включает в себя
- Вдохновение
- введение
- IT
- Сохранить
- слой
- узнали
- Оставлять
- мало
- загрузка
- посмотреть
- искать
- сделанный
- сделать
- Создание
- маска
- математике
- матрица
- означает
- БОЛЕЕ
- двигаться
- отрицательный
- номер
- номера
- Другое
- собственный
- часть
- шаблон
- штук
- игры
- пунктов
- возможное
- предыдущий
- опубликованный
- Reading
- рекомендовать
- осталось
- представляет
- ОТДЫХ
- Safari
- то же
- масштабируемые
- Серии
- набор
- Форма
- формы
- Поделиться
- показывать
- подпись
- аналогичный
- просто
- с
- одинарной
- Размер
- So
- некоторые
- удалось
- Space
- конкретный
- Расходы
- раскол
- площадь
- стек
- Начало
- и политические лидеры
- начинается
- По-прежнему
- снижения вреда
- Ассоциация
- задача
- три
- время
- вместе
- трогать
- Transform
- Прозрачность
- прозрачный
- Обновление ПО
- us
- использование
- ценностное
- видимый
- Что
- в то время как
- Шире
- слова
- Работа
- письмо
- ВАШЕ