Анимированный CSS фоновый узор, скользящий бесконечно
Я пытаюсь создать анимированный повторяющийся узор (диагональные полосы скользят горизонтально) в качестве заполнителя для блока загрузки (li
в этом случае).
Как я могу сделать анимацию плавной / непрерывной, создавая иллюзию бесконечного скольжения рисунка?
- Как рассчитать элемент
width
так что картина непрерывна? (полосы не должны выглядеть сломанными / прерванными). - Как сделать так, чтобы петля выглядела так, будто она не перезапускается, а скорее скользит бесконечно? (кадр 100% должен пройти к кадру 0% без сбоев)
Цель состоит в том, чтобы иметь класс, который я могу добавить в любой блок и который будет выглядеть как загрузка / обработка.
Примечание: нет JS; чистый CSS.
li {
display: inline-block;
width: calc(20px * 8); /* how to calculate this, relative to the width (of the pattern or the step), to achieve pattern continuity exactly?
Of course without doing trying&error to know it should be 24.75px * 8.
*/
height: 200px;
background-color: blue;
background-image: repeating-linear-gradient(-45deg, transparent, transparent 10px, black 10px, black 20px
);
animation: loading-slide 1s linear infinite;
@keyframes loading-slide {
from { background-position: 0% 0% }
to { background-position: 100% 0% }
}
}
<ul>
<li>test
<li>test
</ul>
1 ответ
Правильная формула должна быть (20px / cos(45deg)) * N
, Тогда вы можете просто сделать background-size
быть 200% 100%
(вдвое больше, чем элемент), и вы можете легко анимировать слева направо:
li {
display: inline-block;
width: calc( (20px / 0.707) * 3); /*cos(45deg) = 0.707*/
height: 50px;
margin-bottom:10px;
background-color: blue;
background-image: repeating-linear-gradient(-45deg, transparent, transparent 10px, black 10px, black 20px);
background-size: 200% 100%;
background-color: blue;
animation: loading-slide 3s linear infinite;
}
@keyframes loading-slide {
from {
background-position: left;
}
to {
background-position: right;
}
}
.alt li {
width: calc( (20px / 0.707) * 6);
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul class="alt">
<li>test</li><li>test</li>
</ul>
Вы можете рассмотреть любую степень и скорректировать формулу по мере необходимости. (20px / cos(90deg - |Xdeg|)) * N
с X
между -90deg
а также 90deg
Пример с -60deg
li {
display: inline-block;
width: calc((20px / 0.866) * var(--n,3)); /*cos(30deg) = 0.866*/
height: 50px;
margin-bottom:10px;
background-color: blue;
background-image: repeating-linear-gradient(-60deg, transparent, transparent 10px, black 10px, black 20px);
background-size: 200% 100%;
background-color: blue;
animation: loading-slide 3s linear infinite;
}
@keyframes loading-slide {
from {
background-position: left;
}
to {
background-position: right;
}
}
.alt li {
--n:6;
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul class="alt">
<li>test</li><li>test</li>
</ul>
Пример с 30deg
li {
display: inline-block;
width: calc((20px / 0.5) * var(--n,8)); /*cos(60deg) = 0.5*/
height: 50px;
margin-bottom:10px;
background-color: blue;
background-image: repeating-linear-gradient(30deg, transparent, transparent 10px, black 10px, black 20px);
background-size: 200% 100%;
background-color: blue;
animation: loading-slide 3s linear infinite;
}
@keyframes loading-slide {
from {
background-position: left;
}
to {
background-position: right;
}
}
.alt li {
--n:12;
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul class="alt">
<li>test</li><li>test</li>
</ul>
Пример с 80deg
li {
display: inline-block;
width: calc((20px / 0.9848) * var(--n,8)); /*cos(10deg) = 0.9848*/
height: 50px;
margin-bottom:10px;
background-color: blue;
background-image: repeating-linear-gradient(80deg, transparent, transparent 10px, black 10px, black 20px);
background-size: 200% 100%;
background-color: blue;
animation: loading-slide 3s linear infinite;
}
@keyframes loading-slide {
from {
background-position: left;
}
to {
background-position: right;
}
}
.alt li {
--n:12;
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul class="alt">
<li>test</li><li>test</li>
</ul>
Вы можете четко определить тривиальный случай, когда X=+/-90deg
(вертикальные полосы), и мы будем иметь cos(0)=1
таким образом, формула будет 20px * N
, Также когда X=0
(горизонтальные полосы) у нас будет cos(90deg) = 0
и любая ширина будет работать, так как нет вертикального шаблона (формула больше не определена)
li {
display: inline-block;
width: calc(20px * var(--n,8));
height: 50px;
margin-bottom:10px;
background-color: blue;
background-image: repeating-linear-gradient(90deg, transparent, transparent 10px, black 10px, black 20px);
background-size: 200% 100%;
background-color: blue;
animation: loading-slide 3s linear infinite;
}
@keyframes loading-slide {
from {
background-position: left;
}
to {
background-position: right;
}
}
.alt li {
background-image:repeating-linear-gradient(0deg, transparent, transparent 10px, black 10px, black 20px);
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul class="alt">
<li>test</li><li>test</li>
</ul>
Как насчет ценности за пределами [-90deg,90deg]
?
Вышеупомянутый диапазон уже охватывает 180deg
и поскольку мы имеем дело с чем-то симметричным, все значения могут быть представлены внутри этого диапазона.
Пример: 110deg
такой же как -70deg
li {
display: inline-block;
width: calc((20px / 0.9396) * var(--n,8)); /*cos(20deg) = 0.9396*/
height: 50px;
margin-bottom:10px;
background-color: blue;
background-image: repeating-linear-gradient(110deg, transparent, transparent 10px, black 10px, black 20px);
background-size: 200% 100%;
background-color: blue;
animation: loading-slide 3s linear infinite;
}
.alt li {
--n:12;
background-image: repeating-linear-gradient(-70deg, transparent, transparent 10px, black 10px, black 20px);
}
@keyframes loading-slide {
from {
background-position: left;
}
to {
background-position: right;
}
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul class="alt">
<li>test</li><li>test</li>
</ul>
Пример: -150deg
такой же как 30deg
li {
display: inline-block;
width: calc((20px / 0.5) * var(--n,4)); /*cos(60deg) = 0.5*/
height: 50px;
margin-bottom:10px;
background-color: blue;
background-image: repeating-linear-gradient(-150deg, transparent, transparent 10px, black 10px, black 20px);
background-size: 200% 100%;
background-color: blue;
animation: loading-slide 3s linear infinite;
}
.alt li {
--n:6;
background-image: repeating-linear-gradient(30deg, transparent, transparent 10px, black 10px, black 20px);
}
@keyframes loading-slide {
from {
background-position: left;
}
to {
background-position: right;
}
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul class="alt">
<li>test</li><li>test</li>
</ul>
в основном мы добавляем / удаляем 180deg
пока мы не попадем внутрь [-90deg,90deg]
чтобы иметь возможность применять формулу.
Проверьте этот ответ для более подробной информации о том, как background-size
/ background-position
работает: /questions/28327775/ispolzovanie-protsentnyih-znachenij-s-background-position-na-linejnom-gradiente/28327778#28327778
Другой подход
Вот совершенно другая идея, на которую можно положиться skew
преобразование и псевдоэлемент. Хитрость в том, что вам не нужно определять ширину на основе полос, но полосы будут следовать ширине, которую вы определите, так что с ней будет легче работать.
li {
display: inline-block;
width: calc( 20px * 3); /* it's only 20px * N */
height: 50px;
margin-bottom:10px;
background-color: blue;
position:relative;
z-index:0;
overflow:hidden
}
li::before {
content:"";
position:absolute;
top:0;
bottom:0;
left:0;
width:400%;
/*we keep 0deg in the gradient*/
background-image: repeating-linear-gradient(90deg, transparent, transparent 10px, black 10px, black 20px);
transform:skewX(30deg);
transform-origin:bottom left;
animation: loading-slide 4s linear infinite;
}
@keyframes loading-slide {
to {
transform: translateX(-50%) skewX(30deg);
}
}
.alt li {
width: calc( 20px * 6);
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul class="alt">
<li>test</li><li>test</li>
</ul>
Как видите, мы сохраняем вертикальный градиент, определяем ширину элемента на основе ширины градиента. Мы делаем псевдоэлемент достаточно большим и применяем к нему перевод. Единственное, что вам нужно отрегулировать - это косое преобразование для контроля степени.
При таком подходе у вас также будет лучшая производительность, так как вы будете анимировать преобразование вместо background-size
,
Больше примеров:
li {
display: inline-block;
width: calc( 20px * var(--n,3)); /* it's only 20px * N */
height: 50px;
margin-bottom:10px;
background-color: blue;
position:relative;
z-index:0;
overflow:hidden
}
li::before {
content:"";
position:absolute;
top:0;
bottom:0;
left:-400%;
right:-800%;
/*we keep 0deg in the gradient*/
background-image: repeating-linear-gradient(90deg, transparent, transparent 10px, black 10px, black 20px);
transform:skewX(var(--d,30deg));
animation: loading-slide 12s linear infinite;
}
@keyframes loading-slide {
to {
transform: translateX(-50%) skewX(var(--d,30deg));
}
}
<ul>
<li>test</li><li>test</li>
</ul>
<ul style="--n:6;--d:45deg">
<li>test</li><li>test</li>
</ul>
<ul style="--n:8;--d:-70deg">
<li>test</li><li>test</li>
</ul>
<ul style="--n:8;--d:30deg">
<li>test</li><li>test</li>
</ul>