Анимационные навыки и детали анимации, о которых вы могли не знать

анимация CSS
Анимационные навыки и детали анимации, о которых вы могли не знать

Автор: Bump Man - Арвин

введение

В веб-приложениях фронтенд-студенты часто используют несколько схем для достижения анимационных эффектов:

  1. css3 transition/animation — реализовать анимацию перехода
  2. setInterval/setTimeout — постоянно менять положение изображения, задавая интервал
  3. requestAnimationFrame — измените положение изображения с помощью функции обратного вызова, и система определяет время выполнения этой функции обратного вызова, которая имеет лучшую производительность, чем изменение времени, и нет явления потери кадров.

В большинстве требований CSS3transition / animationВсе может удовлетворить наши потребности, и по сравнению с реализацией js это может значительно повысить эффективность нашей разработки и снизить затраты на разработку.

Эта статья будет посвященаanimationПодводя итог использованию , если у вас есть дополнительные требования к анимации в вашей работе, я считаю, что эта статья может помочь вам что-то получить:

  • Анимация Общие свойства анимации
  • Анимация реализует непрерывную трансляцию
  • Анимация для достижения эффекта отскока
  • Анимация реализует аналогичный эффект прямого эфира ❤️
  • Какую искру создадут Animation и Svg? 🔥
    1. Загрузка компонента
    2. компонент индикатора выполнения
  • Шаги анимации () с использованием ⏰
    1. добиться эффекта набора текста
    2. рисовать кадр анимации

Анимация Общие свойства анимации

После знакомства с общими свойствами анимации, чтобы лучше понять и использовать эти свойства, далее будут подробно описаны некоторые демонстрации.

Анимация реализует непрерывную трансляцию

Реализовать непрерывную трансляцию DEMO

Эффект трансляции за счет изменения положения содержимого по оси Y в родительском элементе.

@keyframes scroll {
  0%{
    transform: translate(0, 0);
  }
  100%{
    transform: translate(0, -$height);
  }
}

.ul {
  animation-name: scroll;
  animation-duration: 5s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  /* animation: scroll 5s linear infinite; 动画属性简写 */
}

Здесь, чтобы сохранить непрерывность эффекта прокрутки трансляции и предотвратить прокрутку до последнего кадра без контента,Нужно добавить еще один дубликат данных для заполнения

<div class="ul">
  <div class="li">小刘同学加入了凹凸实验室</div>
  <div class="li">小邓同学加入了凹凸实验室</div>
  <div class="li">小李同学加入了凹凸实验室</div>
  <div class="li">小王同学加入了凹凸实验室</div>
	<!--   插入用于填充的数据数据 -->
  <div class="li">小刘同学加入了凹凸实验室</div>
</div>

Анимация для достижения эффекта отскока

Это достигается путем разделения анимации перехода на несколько этапов, в каждом из которых верхнее свойство остается в другом положении.

Реализуйте эффект отскока DEMO

/* 规定动画,改变top,opacity */
@keyframes animate {
  0% {
    top: -100%;
    opacity: 0;
  }
  25% {
    top: 60;
    opacity: 1;
  }
  50% {
    top: 48%;
    opacity: 1;
  }
  75% {
    top: 52%;
    opacity: 1;
  }
  100%{
    top: 50%;
    opacity: 1;
  }
}

Чтобы сделать эффект перехода более естественным, здесьcubic-bezier()Функция определяет кривую Безье для управления скоростью воспроизведения анимации.

После выполнения анимации перехода, чтобы применить к элементу значение атрибута последнего кадра анимации, нам нужно использоватьanimation-fill-mode: forwards

.popup {
  animation-name: animate;
  animation-duration: 0.5s;
  animation-timing-function: cubic-bezier(0.21, 0.85, 1, 1);
  animation-iteration-count: 1;
  animation-fill-mode: forwards;
  /* animation: animate 0.5s cubic-bezier(0.21, 0.85, 1, 1) 1 forwards; 动画属性简写 */
}

Анимация реализует подобный эффектOnline Code

Реализовать подобный эффект DEMO

Я считаю, что большинству студентов известен подобный эффект.Эта статья реализует простую версию подобного эффекта, в основном об идеях реализации:

  1. Чтобы пузыри были смещены вверх, нам нужно реализовать анимацию @keyframes, которая перемещается в направлении оси Y.
/* 规定动画,改变y轴偏移距离*/
@keyframes animation-y {
  0%{
   transform:  translate(-50%, 100px) scale(0);
  }
  50%{
   transform:  translate(-50%, -100px) scale(1.5);
  }
  100%{
    transform:  translate(-50%, -300px) scale(1.5);
  }
}
  1. Чтобы пузырек казался менее монотонным, когда он смещен вверх, мы можем реализовать другую анимацию @keyframes, которая перемещается в направлении оси x.
/* 规定动画,改变x轴偏移距离 */
@keyframes animation-x {
  0%{
    margin-left: 0px;
  }
  25%{
    margin-left: 25px;
  }
  75%{
    margin-left: -25px;
  }
  100%{
    margin-left: 0px;
  }
}

Вот я понимаю:

  • Хотя это является修改 marginдля изменения расстояния смещения по оси X, но на самом деле это то же самое, что и修改 transformНе большая разница в производительности
  • потому что через@keyframes animation-yсерединаtransformсоздал новый渲染层 ( PaintLayers )
  • animationАтрибут позволяет повысить уровень этого слоя рендеринга до合成层(Compositing Layers)иметь отдельный图形层 ( GraphicsLayer ), то есть включено аппаратное ускорение, на другие слои рендеринга оно не повлияетpaint、layout
  • за合成层(Compositing Layers)Студенты, которые не очень хорошо владеют соответствующими знаниями, могут прочитать эту статьюАнализ принципа оптимизации динамических эффектов css3 с уровня рендеринга браузера
  • Как показано ниже:

Если понимание автора здесь неверно, я также прошу читателей указать на это, большое спасибо~

  1. Примените две анимации @keyframes, которые мы реализовали к пузырю.
.bubble {
  animation: animation-x 3s -2s linear infinite,animation-y 4s 0s linear 1;
/*  给 bubble 开启了硬件加速 */
}
  1. В подобном случае динамически добавляйте/удаляйте элементы пузыря с помощью операций js.
function like() {
  const likeDom = document.createElement('div');
  likeDom.className = 'bubble'; // 添加样式
  document.body.appendChild(likeDom);  // 添加元素
  setTimeout( () => {
    document.body.removeChild(likeDom);  // 移除元素
  }, 4000)
}

Компоненты загрузки/индикатора загрузки анимации и рисования Svg 🔥Online Code

Компонент загрузки/индикатора загрузки анимации и Svg-рисования 🔥 DEMO

  1. Во-первых, мы используем svg, чтобы нарисовать круг с окружностью2 * 25 * PI = 157круг
<svg with='200' height='200' viewBox="0 0 100 100"  >
  <circle cx="50" cy="50" r="25"  fill="transparent" stroke-width="4" stroke="#0079f5" ></circie>
</svg>

  1. Нарисуйте сплошной круг как пунктирный круг, здесь вам нужно использоватьstoke-dasharray:50, 50 (可简写为50)свойство рисовать пунктирные линии,сток-дашаррай
  • Его значение представляет собой последовательность чисел, разделенных запятыми или пробелами, указывающую短划线(50px)и缺口(50px)длина.
  • так как50(短划线) + 50(缺口) + 50(段划线) = 150, 150 < 157, полный круг нельзя нарисовать, поэтому правая сторона будет существовать缺口(7px)
<svg with='200' height='200' viewBox="0 0 100 100"  >
  <circle cx="50" cy="50" r="25"  fill="transparent" stroke-width="4" stroke-dasharray="50" stroke="#0079f5" ></circie>
</svg>

  1. stroke-dashoffsetСвойство может компенсировать штрихи и пробелы в круге, а добавление анимации @keyframes может добиться эффекта с нуля.stoke-dashoffset Ссылки
  • настраиватьstroke-dasharray="157 157", уточнить短划线(157px)и缺口(157px)длина.
  • Добавить анимацию @keyframes修改stroke-dashoffset值, значение正数Время逆时针偏移🔄, значение равно负数час,顺时针偏移🔃
@keyframes loading {
  0%{
    stroke-dashoffset: 0;
  }
  100%{
    stroke-dashoffset: -157; /* 线条顺时针偏移 */
  }
}
circle{
    animation: loading 1s 0s ease-out infinite;
}

  1. Изменить значения тире и пробела
  • Чтобы сделать линии загрузки компонентов видимыми, нам нужен50pxтире, наборstroke-dasharray="50"
  • Чтобы черточка полностью исчезла после смещения,缺口需要大于或等于圆周长157,настраиватьstroke-dasharray="50 157"
  • Добавлена ​​анимация @keyframes, чтобы сделать动画结束时仍处理动画开始位置,необходимость修改 stroke-dashoffset:-207(短划线+缺口长度)
  • Индикатор выполнения также представляет собой аналогичный принцип, помогающий понятьstroke-dashoffsetАтрибут, см. конкретную реализациюПример
@keyframes loading {
  0%{
    stroke-dashoffset: 0;
  }
  100%{
    stroke-dashoffset: -207; /* 保证动画结束时仍处理动画开始位置 */
  }
}
circle{
    animation: loading 1s 0s ease-out infinite;
}

Приложение шагов анимации ()

steps()даanimation-timing-functionстоимость имущества

animation-timing-function : steps(number[, end | start])
  • Функция шагов задает ступенчатую функцию, которая принимает两个参数
  • 第一个参数接受一个整数值, указывая на то, что два ключевых кадра завершены в несколько шагов
  • 第二个参数有两个值 start or end. Значение по умолчанию — конец
  • step-start эквивалентно step(1, start). шаг-конец эквивалентен шагу (1, конец)

шаги предназначены для анимации по ключевым кадрам, первый параметр будет两个关键帧подразделяется наN帧, используется второй параметр, определяющий промежуточный интервал от одного кадра к другому开始帧все еще结束帧заполнять.

Посмотрите на изображение ниже, чтобы узнать:

  • steps(N, start)Разделить анимацию наN段, анимация в каждом сегменте起点Происходит шаг (то есть пустой круг на рисунке → сплошной круг), и анимация заканчивается на N-м кадре.
  • steps(N, end)Разделить анимацию наN段, анимация в каждом сегменте终点Происходит шаг (то есть пустой круг → сплошной круг на рисунке), и N-й кадр был пропущен в конце анимации (то есть пустой круг → сплошной круг на рисунке), и он остается на кадр N+1.

Практикуйте правду!

Анимация реализует эффект набора текста

Анимация реализует эффект набора текста DEMO

  • Вот пример английских букв (я O2man.), всего13символы. [После тестирования большинство китайских шрифтов имеют одинаковую ширину и высоту для каждого символа]
  • steps(13)Анимации @keyframes можно разделить на13阶段бежать, и每一阶段运行距离相等.

Эффект следующий:

/* 改变容器宽度 */
@keyframes animate-x {
  0%{
    width: 0;
  }
}

p {
    width: 125px;
    overflow: hidden;
    border-right: 1px solid transparent;
    animation: animate-x 3s 0s steps(13) 1 forwards;
}
  • Можно обнаружить, что этого недостаточно, символы усекаются во время выполнения анимации.Чтобы гарантировать, что символы текущего этапа могут отображаться точно после запуска каждого этапа, нам также необходимо обеспечить每个字符的width与动画每一阶段运行的距离相等
  • настраиватьMonacoСвойства шрифта для обеспечения每个字符的 width 相同, на конкретный пиксель влияетfontSizeэффект атрибута, ширина шрифта в примере около 9,6 пикселей,9.6px * 13(段数) = 124.8px (125px), поэтому, когда мы установим ширину контейнера на 125 пикселей, мы сможем достичь цели:每个字符的 width 与动画每一阶段运行的距离相等(约为 9.6px ).
p {
    /* 设置 Monaco 字体属性,字体大小为16px,用以保证每个字符的 width 相同,width 约为9.6p */
    font-family: Monaco;
    /* 9.6px * 13 = 124.8px (125px) */
    width: 125px ;
    font-size: 16px;
    overflow: hidden;
    border-right: 1px solid transparent;
    /* 同时应用动画 animate-x、cursor-x */
    animation: animate-x 3s 0s steps(13) 1 forwards,cursor-x 0.4s 0s linear infinite;
}

Анимация реализует покадровую анимацию ⏰

Animation реализует покадровую анимацию ⏰ DEMO

  • Здесь мы получили47帧изСпрайт (css дух), установить фоновое изображение
.main {
  width: 260px;
  height: 200px;
  background: url(url) no-repeat;
  background-size: 100%;
  background-position: 0 0;
}
  • добавить @ключевые кадры修改 background-position, чтобы переместить фоновое изображение
@keyframes animate {
    0% {
        background-position: 0 0;
    }

    100% {
        background-position: 0 100%;
    }
}
.main{
  width: 260px;
  height: 200px;
  background: url(url) no-repeat;
  background-size: 100%;
  background-position: 0 0;
  animation: animate 2s 1s steps(47) infinite alternate;
}
  • В то же время css также предоставляетanimation-play-stateИспользуется для управления приостановкой анимации.
input:checked+.main{
    animation-play-state: paused;
}

Статья длинная, спасибо за прочтение, надеюсь, вы сможете что-то почерпнуть из аудитории~ ~ ~


использованная литература

Анимация Общие свойства анимации Справочное руководство по CSS ссылка на шаги() Подробное объяснение stroke-dasharray и stroke-dashoffset для изучения SVG
Понимание steps() в анимации CSS3
[Перевод] Подробное объяснение использования steps() в анимации CSS
CSS Will Change