本篇文章給大家帶來的內容是關於如何使用CSS和D3實現小魚遊動的互動動畫(附代碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所協助。
效果預覽
原始碼下載
https://github.com/comehope/front-end-daily-challenges
代碼解讀
定義 dom,容器中包含的子項目分別代表魚的身體、眼睛、背鰭和尾巴:
<div class="fish"> <span class="body"></span> <span class="eye"></span> <span class="fin"></span> <span class="tail"></span></div>
設定頁面樣式為全屏且沒有捲軸:
body { margin: 0; width: 100vw; height: 100vh; background-color: #222; overflow: hidden;}
定義魚的容器尺寸,--r
是一個基本尺寸單位,後續所有尺寸都是基於它計算的:
.fish { position: absolute; --r: 15vw; width: calc(var(--r) + var(--r) / 3); height: calc(var(--r) * 2); left: 50%; top: 100px;}
畫出魚的身體,同時把魚的顏色聲明到父類中,因為下面還會用到這個顏色:
.fish { color: hsl(0, 50%, 50%);}.fish .body { position: absolute; border: var(--r) solid transparent; border-right-color: currentColor; border-left-style: none;}
畫出魚的眼睛:
.fish .eye { position: absolute; --r1: calc(var(--r) / 4); width: var(--r1); height: var(--r1); background-color: #111; border-radius: 50%; top: 35%; left: 30%;}
畫出魚的背鰭:
.fish .fin { position: absolute; --r2: calc(var(--r) / 2); border-bottom: var(--r2) solid; border-left: var(--r2) solid transparent; filter: brightness(2.5); left: calc(var(--r) - var(--r2));}
畫出魚的尾巴:
.fish .tail { position: absolute; --r3: calc(var(--r) / 3); border: var(--r3) solid transparent; border-right-color: currentColor; border-left-style: none; right: 0; top: calc(var(--r) - var(--r3));}
增加讓魚遊動的動畫效果,不是迴圈執行,而是只執行一次:
.fish { right: calc(var(--r) * -1); animation: run 3s linear forwards;}@keyframes run { to { right: 100%; }}
再增加魚遊動時搖擺的動畫效果:
.fish { animation: run 3s linear forwards, shake 0.3s linear infinite;}@keyframes shake { 50% { transform: rotateY(-30deg); } 100% { transform: rotateY(30deg); }}
接下來設定一些變數,以便建立不同樣子的魚:
魚的大小的變數 --size
,數值越大尺寸越大:
.fish { --size: 5; --r: calc(var(--size) * 1vw);}
魚的顏色變數 --color
,表示色相環的角度:
.fish { --color: 0; color: hsl(var(--color), 50%, 50%);}
魚從右側遊到左側的時間長度,時間長度越短遊得越快:
.fish { --duration: 3; animation: run calc(var(--duration) * 1s) linear forwards, shake 0.3s linear infinite;}
魚出現的高度,資料越大越靠近頁面下部:
.fish { --top: 100; top: calc(var(--top) * 1px);}
接下來用 d3 來批量處理 dom 元素和 css 變數。
引入 d3 庫:
<script src="https://d3js.org/d3.v5.min.js"></script>
刪除掉 html 中的 .fish
元素和 css 檔案中的變數聲明代碼。建立一個函數,用於產生一條魚。css 變數的值均為隨機產生,--size
的取值範圍是 5 ~ 8,--color
的取值範圍是 -60 ~ 15,--duration
的取值範圍是 3 ~ 6,--top
的取值範圍是 100 ~ 300:
function buildFish() { let fish = d3.select('body') .append('p') .attr('class', 'fish') .style('--size', d3.randomUniform(5, 8)()) .style('--color', d3.randomUniform(-60, 15)()) .style('--duration', d3.randomUniform(3, 6)()) .style('--top', d3.randomUniform(100, 300)()); fish.append('span').attr('class', 'body'); fish.append('span').attr('class', 'eye'); fish.append('span').attr('class', 'fin'); fish.append('span').attr('class', 'tail');}
綁定按一下滑鼠事件,當按下滑鼠時就產生一條魚:
function buildFish(e) { //略.... .style('--top', e.clientY);}window.addEventListener('click', buildFish);
並且讓魚的嘴部和點擊的位置在一條水平線上:
.fish { top: calc(var(--top) * 1px - var(--r));}
最後,在頁面載入時自動產生 3 條魚,以免頁面載入後一片空白:
function buildFish(e) { //略.... .style('--top', e ? e.clientY : d3.randomUniform(100, 300)());}d3.range(3).forEach(buildFish);
大功告成!