按下右側的「點擊預覽」按鈕能夠在當前頁面預覽,點擊連接能夠全屏預覽。javascript
https://codepen.io/comehope/pen/xJrOqdcss
此視頻是能夠交互的,你能夠隨時暫停視頻,編輯視頻中的代碼。html
請用 chrome, safari, edge 打開觀看。前端
https://scrimba.com/p/pEgDAM/cr6Vetmjava
每日前端實戰系列的所有源代碼請從 github 下載:git
https://github.com/comehope/front-end-daily-challengesgithub
定義 dom,容器中包含 6 個 內含 <span>
的 <div>
元素,每一個 <div>
元素表明 1 個粒子:chrome
<section class="container"> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> <div><span></span></div> </section>
居中顯示:app
body { margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center; background-color: black; }
定義容器尺寸:dom
.container { width: 70vmin; height: 70vmin; }
在容器中定位 <div>
,並在 <div>
中用 <span>
畫出粒子:
.container { display: flex; align-items: center; justify-content: center; } .container div { position: absolute; width: 10vmin; height: 10vmin; } .container div span { position: absolute; width: inherit; height: inherit; border-radius: 50%; background-color: limegreen; transform: translateX(300%); }
用變量定義粒子的旋轉角度,其中 --particles-per-circle 每圈的粒子數,由於每圈有 3 個粒子,因此圈中有 3 個位置,每一個位置有 2 個粒子重疊在一塊兒,此時看起來是隻有 3 個粒子的樣子:
.container { --particles-per-circle: 3; } .container div { transform: rotate(calc(var(--n) / var(--particles-per-circle) * -360deg)); } .container div:nth-child(1) { --n: 1; } .container div:nth-child(2) { --n: 2; } .container div:nth-child(3) { --n: 3; } .container div:nth-child(4) { --n: 4; } .container div:nth-child(5) { --n: 5; } .container div:nth-child(6) { --n: 6; }
定義粒子從中心向外側的運動效果:
.container div span { animation: move 2s linear infinite; } @keyframes move { from { transform: translateX(0) scale(0); } 70% { transform: translateX(210%) scale(0.55); } to { transform: translateX(300%) scale(0); } }
再增長運動時讓粒子變色的效果,沿色相環取了 10 個顏色:
.container div span { animation: move 2s linear infinite, change-color 2s linear infinite; } @keyframes change-color { 0%, 100% { background-color: hsl(calc(0 / 100 * 360deg), 80%, 55%); } 10% { background-color: hsl(calc(10 / 100 * 360deg), 80%, 55%); } 20% { background-color: hsl(calc(20 / 100 * 360deg), 80%, 55%); } 30% { background-color: hsl(calc(30 / 100 * 360deg), 80%, 55%); } 40% { background-color: hsl(calc(40 / 100 * 360deg), 80%, 55%); } 50% { background-color: hsl(calc(50 / 100 * 360deg), 80%, 55%); } 60% { background-color: hsl(calc(60 / 100 * 360deg), 80%, 55%); } 70% { background-color: hsl(calc(70 / 100 * 360deg), 80%, 55%); } 80% { background-color: hsl(calc(80 / 100 * 360deg), 80%, 55%); } 90% { background-color: hsl(calc(90 / 100 * 360deg), 80%, 55%); } }
用變量設置動畫延時,這時能夠看到 6 個粒子陸續出現了。其中 --circles 表示圈數;--particles 表示粒子數,它等於每圈的粒子數與圈數的積:
.container { --circles: 2; --particles: calc(var(--particles-per-circle) * var(--circles)); } .container div span { animation-delay: calc(var(--n) / var(--particles) * -2s); }
接下來用 d3 來批量建立粒子。
引入 d3 庫:
<script src="https://d3js.org/d3.v5.min.js"></script>
用 d3 爲 css 的 --particles-per-circle 和 --circles 變量賦值:
const PARTICLES_PER_CIRCLE = 3; const CIRCLES = 2; d3.select('.container') .style('--particles-per-circle', PARTICLES_PER_CIRCLE) .style('--circles', CIRCLES);
用 d3 建立粒子 dom 元素:
const COUNT_OF_PARTICLES = PARTICLES_PER_CIRCLE * CIRCLES; d3.select('.container') .style('--particles-per-circle', PARTICLES_PER_CIRCLE) .style('--circles', CIRCLES) .selectAll('div') .data(d3.range(COUNT_OF_PARTICLES)) .enter() .append('div') .append('span');
用 d3 爲粒子元素的 --n 變量賦值:
d3.select('.container') .style('--particles-per-circle', PARTICLES_PER_CIRCLE) .style('--circles', CIRCLES) .selectAll('div') .data(d3.range(COUNT_OF_PARTICLES)) .enter() .append('div') .style('--n', (d) => d + 1) .append('span');
刪除掉 dom 中的粒子元素,以及用 css 聲明的變量。
最後,調整每圈的粒子數和圈數,造成旋臂效果:
const PARTICLES_PER_CIRCLE = 14; const CIRCLES = 4;
大功告成!