Создаем крутую анимацию «след частиц» на JavaScript

    анимация «след частиц» на JavaScript

    Вы когда-нибудь задумывались о том, чтобы увлекать посетителей вашего веб-сайта на несколько секунд причудливой, блестящей анимацией, в то время как некоторые данные загружаются в фоновом режиме? К счастью, нет необходимости углубляться в графическое программирование с использованием 3D-библиотек, таких как three.js. Все, что вам нужно, это базовые знания CSS и JavaScript и легкая библиотека анимации, такая как anime.js. В итоге мы должны получить следующий результат:

    анимация «след частиц» на JavaScript
    анимация «след частиц» на JavaScript

    Скачиваем и внедряем Anime.Js

    Вы можете скачать библиотеку anime.js с официального сайта GitHub. Загрузите файл anime.js или anime.min.js для использования в своем проекте.

    В этом примере файл HTML выглядит следующим образом:

    <!DOCTYPE html>
    <html lang="en" >
    <head>
      <meta charset="UTF-8">
      <title>Anime.js Particles</title>
      <!--or use anime.min.js-->
      <script src="anime.js"></script>
      <link rel="stylesheet" href="style.css">
    </head>
    <body>
    <div class="anime-container">
    </div>
    <script src="script.js"></script>
    </body>
    </html>

    Файл CSS styles.css определяет цвет фона для страницы и для отдельных частиц. Настройки позиционирования необходимы, чтобы мы могли позже свободно размещать частицы на странице, используя свойства CSS left и top.

    body {
     background-color: hsl(30, 3%, 14%);
    }
    .anime-container {
      position: relative;
    }
     
    .anime-container .dot{
      position: absolute;
      /*draw particles as circles:*/
      border-radius: 50%;
      background-color: hsl(60, 100%, 80%);
    }

    Генерация «частиц»

    Как следует из названия, анимация частиц состоит из множества мелких частиц, движущихся в пространстве по определенной схеме. Все частицы генерируются одновременно до начала анимации.

    Для следующего объяснения будет полезна официальная документация по anime.js.

    В этом примере частицы расположены на архимедовой спирали. x и y положение частицы на экране (они же left и top в CSS) рассчитывается исходя из позиции angle по спирали:

    x=a*angle*cos(angle)
    y=a*angle*sin⁡(angle)

    Количество углов и, следовательно, длина спирали определяется параметром l. С помощью параметра a вы можете контролировать плотность спирали.

    var container = document.querySelector(".anime-container");
    var n = 15;
    var a = 20;
    var l = 110;
    for (var i = 0; i <= l; i += 1) {
      var angle = 0.1 * i;
      //shift the particles to the center of the window 
      //by adding half of the screen width and screen height
      var x = (a*angle) * Math.cos(angle) + window.innerWidth / 2;
      var y = (a*angle) * Math.sin(angle) + window.innerHeight / 2;
      var dot = document.createElement("div");
      dot.classList.add("dot");
      container.appendChild(dot);
      var size = 5;
      dot.style.width = size + "px";
      dot.style.height = size + "px";
      dot.style.left = x + "px";
      dot.style.top = y + "px";
      dot.style.backgroundColor = "hsl(60, 100%, 80%)";
      }
    }
    генерация частиц
    Вот, что мы получим в начале

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

    anime.random(minValue, maxValue);

    Размер частиц также изменяется случайным образом:

    for (var i = 0; i <= l; i += 1) {
      var angle = 0.1 * i;
      //shift particles to the center of the window 
      //by adding half of the screen width and screen height
      var x = (a*angle) * Math.cos(angle) + window.innerWidth / 2;
      var y = (a*angle) * Math.sin(angle) + window.innerHeight / 2;
      var n = 15;
      
      //create n particles for each angle
      for (var j = 0; j < n; j++) {
        var dot = document.createElement("div");
        dot.classList.add("dot");
        container.appendChild(dot);
        var size = anime.random(5, 10); 
        dot.style.width = size + "px";
        dot.style.height = size + "px";
        dot.style.left = x + anime.random(-15, 15) + "px";
        dot.style.top = y + anime.random(-15, 15) + "px";
        dot.style.backgroundColor = "hsl(60, 100%, 80%)";
      }
    }
    Спираль со случайно расположенными частицами
    Спираль со случайно расположенными частицами

    Перед началом анимации все частицы должны быть невидимыми. Поэтому добавим:

    dot.style.opacity = "0";

    Основные настройки анимации

    Основные настройки анимации сделаны следующим образом:

    • Анимация должна повторяться непрерывно (loop: true),
    • Ослабление является линейным (но можно попробовать различные значения),
    • Целевыми элементами являются элементы с классом .dot
    anime({
      loop: true,
      easing: "linear",
      targets: document.querySelectorAll(".dot"),
    });

    На следующем шаге будем анимировать различные свойства CSS. Основные шаги для CSS-анимации можно найти в документации anime.js.

    Анимация непрозрачности

    Вот как выглядит наша первая анимация, в которой все частицы медленно становятся видимыми в течение 50 мс:

    anime({
      loop: true,
      easing: "linear",
      targets: document.querySelectorAll(".dot"),
      opacity: { value: 1, duration: 50}
    });

    И теперь мы наконец раскроем трюк, который создает спиральное движение частиц! Идея состоит в том, чтобы сделать частицы видимыми с определенной временной задержкой (например, с интервалом в 2 мс). Частицы в середине спирали сначала становятся видимыми, а затем все остальные частицы изнутри наружу. Функция пошагового изменения в anime.js идеально подходит для этого.

    opacity: { value: 1, duration: 50, delay: anime.stagger(2) }

    Чтобы создать иллюзию следа, частицы должны начать медленно исчезать, как только они появились. К счастью, anime.js предоставляет инструменты для этого:

    opacity: [
        { value: 1, duration: 50, delay: anime.stagger(2) },
        { value: 0, duration: 1200}
      ],

    Анимация размера

    След кометы должен казаться больше на переднем плане, чем на заднем. Для этого частицы сжимаются в течение 500 мс до диаметра 2 пикселя. Важно выбрать ту же задержку, что и для анимации непрозрачности, чтобы каждая частица начинала уменьшаться только после того, как она появилась:

    width: { value: 2, duration: 500, delay: anime.stagger(2) },
    height: { value: 2, duration: 500, delay: anime.stagger(2) },

    Индивидуальное движение частиц

    Типичная вещь в анимации частиц — это индивидуальное, непредсказуемое поведение частиц. Теперь наконец оживим частицы с индивидуальным движением в x и y направлении:

    translateX: {
        value: function() {
          return anime.random(-30, 30);
        },
        duration: 1500,
        delay: anime.stagger(2)
      },
    
    translateY: {
        value: function() {
          return anime.random(-30, 30);
        },
        duration: 1500,
        delay: anime.stagger(2)
      }

    Опять же, важно, чтобы движение начиналось с той же временной задержкой, что и появление частиц.

    Кроме того, в этом случае необходимо рассчитать значения для translateX и translateY.

    Вы можете увидеть окончательный результат:

    анимация «след частиц» на JavaScript
    Конечный результат

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

    opacity: [
        { value: 1, duration: 50, delay: anime.stagger(2) },
        { value: 0, duration: function(){return anime.random(500,1500);}}
    ],

    Время до исчезновения частицы теперь устанавливается для каждой частицы отдельно. Это делает нашу анимацию визуально еще более сложной.

    Теперь вы познакомились с прекрасной библиотекой anime.js

    Конечный вариант файла script.js:

    var container = document.querySelector(".anime-container");
    
    var a = 20;
    var l = 110;
    
    for (var i = 0; i <= l; i += 1) {
      var angle = 0.1 * i;
      var x = (a*angle) * Math.cos(angle) + window.innerWidth / 2;
      var y = (a*angle) * Math.sin(angle) + window.innerHeight / 2;
    
      var n = 15;
      
      for (var j = 0; j < n; j++) {
        var dot = document.createElement("div");
        dot.classList.add("dot");
        container.appendChild(dot);
    
        var size = anime.random(5, 10);
       
        dot.style.width = size + "px";
        dot.style.height = size + "px";
       
        dot.style.left = x + anime.random(-15, 15) + "px";
        dot.style.top = y + anime.random(-15, 15) + "px";
        
        dot.style.opacity = "0";
      
      }
    }
    
    anime({
      loop: true,
      easing: "linear",
      opacity: [
        { value: 1, duration: 50, delay: anime.stagger(2) },
        { value: 0, duration: function(){return anime.random(500,1500);}}
      ],
      width: { value: 2, duration: 500, delay: anime.stagger(2) },
      height: { value: 2, duration: 500, delay: anime.stagger(2) },
      
      targets: document.querySelectorAll(".dot"),
     
      translateX: {
        value: function() {
          return anime.random(-30, 30);
        },
        duration: 1500,
        delay: anime.stagger(2)
      },
      translateY: {
        value: function() {
          return anime.random(-30, 30);
        },
        duration: 1500,
        delay: anime.stagger(2)
      }
    });

    Добавить комментарий