Анимированный CSS фоновый узор, скользящий бесконечно - PullRequest
0 голосов
/ 27 февраля 2019

Я пытаюсь создать анимированный повторяющийся узор (диагональные полосы, скользящие горизонтально) в качестве заполнителя для блока загрузки (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 Ответ

0 голосов
/ 27 февраля 2019

Правильная формула должна быть (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 работает: https://stackoverflow.com/a/51734530/8620333


Другой подход

Вот совершенно другая идея, на которую вы можете положиться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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...