用JavaScript 實現酷炫的粒子追蹤動畫

做者:Anna Prenzel

翻譯:瘋狂的技術宅javascript

原文:https://www.smashingmagazine....css

未經容許嚴禁轉載html

你是否曾經想過用花哨的、閃閃發光的粒子動畫分吸引你網站用戶的注意力,而同時又在後臺加載一些數據呢?幸運的是,沒有必要用諸如 Three.js 之類的 3D 庫進行很是深刻的圖形編程。相反,你須要的是 CSS 和 JavaScript 的一些基本知識以及輕便的動畫庫(例如 anime.js)。最後咱們應該獲得如下結果前端

4-partical-trail-animation-javascript.gif

Anime.Js 的下載和集成

你能夠從官方 GitHub 下載 anime.js 庫。從lib/文件夾下載文件anime.jsanime.min.jsjava

在個人例子中,HTML 部分以下所示:git

<!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 屬性 lefttop 在頁面上自由放置粒子。程序員

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%);
}

生成粒子

顧名思義,粒子動畫由許多遵循特定模式在空間中移動的小粒子組成。在動畫開始以前,同時生成全部粒子。github

對於如下解釋,anime.js的官方文檔 對你很是有用。面試

在個人例子中,粒子位於阿基米德螺旋上。屏幕上粒子的 x 和 y 位置(在 CSS 中又稱爲 lefttop)是根據其在螺旋上的位置 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%)";
  }
}

5-partical-trail-animation-javascript.png

這樣,咱們獲得一個螺旋,每一個位置只有一個粒子,可是隻有在每一個位置生成一個以上的粒子時,才能實現真正的拖尾效果。爲了使軌跡顯得濃密,各個粒子的位置必須略有不一樣。動畫庫爲此提供了實用的輔助函數:

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%)";
  }
}

3-partical-trail-animation-javascript.png

在這裏,你能夠嘗試中間結果:

請參閱 CodePen 上的 js 粒子動畫 wip:https://codepen.io/smashingma...

在動畫開始以前,全部粒子都必須是不可見的。因此我將添加:

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 ms 的間隔)可見。首先使螺旋中間的粒子可見,而後從內到外的使全部其餘粒子可見。 anime.js 的 stagger 函數很是適合此功能。我認爲,交錯是該庫的最大優點之一,它使你能夠實現出色的效果。

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

爲了產生飛行軌跡的錯覺,粒子一旦出現就必須開始緩慢消失。幸運的是 anime.js 提供了屬性的關鍵幀符號

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

在這裏,你能夠看到中間結果:

請參閱 CodePen 上的 js 粒子動畫 wip 2:https://codepen.io/smashingma...

動畫大小

彗星蹤影出現時應該比消失前更大。爲此,我讓粒子在 500ms 內縮小到 2px 的直徑。選擇與不透明度動畫相同的時間延遲很重要,這樣每一個粒子只有在出現後纔開始收縮:

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

個體運動

粒子動畫的典型特徵是粒子的獨立性、不可預測的行爲。最後,我經過沿 xy 方向的運動將粒子帶入動畫:

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)
  }

一樣,重要的是運動開始的時間應該與粒子的出現有相同的時間延遲。

另外在這種狀況下,絕對有必要用 functions 來計算 translateXtranslateY 的值。在這裏,咱們將參數用做基於函數的參數,其值是針對每一個目標單所獨肯定的。不然全部目標移動相同的量都會是相同的(儘管是隨機肯定的)。

最後的想法

你能夠在此處查看最終結果:

請參閱查看 CodePen 上的 js 動畫粒子:https://codepen.io/smashingma...

你能夠經過簡單地調整這些值來根據本身的喜愛修改動畫。關於最後的修飾有一個小技巧:如今咱們熟悉了基於函數的參數,能夠稍微改善動畫的透明度:

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

如今分別爲每一個粒子設置粒子消失以前的持續時間。這可以使動畫在視覺上更加精緻。

我建議你訪問 CodePen,在這裏你能夠看到更多使人印象深入的例子。


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索