寫在前面的話:
有這樣一個需求,在大屏中要實現幾個球用橢圓形狀的布局進行展示,展示的同時還要沿着橢圓軌道進行運動。經過 百度結合自身的思考之后給出了以下demo。
正文:
首先我們先寫結構
<html> <head> <meta charset="utf-8"> <title></title> </head> <body> <div class="area">
<div class="ball ball1"></div> <div class="ball ball2"></div> <div class="ball ball3"></div> <div class="ball ball4"></div> <div class="ball ball5"></div> <div class="ball ball6"></div> </div> </body> </html>
類名為area的div為存放球類的容器,類名為ball的div為球
接着定義樣式
<style> .area{ width: 1200px; height: 800px; background: green; } .area>.ball{ width: 60px; height: 60px; position: absolute; border-radius: 60px; background-image: linear-gradient(to top,blue,lightblue); box-shadow: 0px 0px 20px #0000ff5c; } </style>
目前得到的效果如下:
接着我們要將這六個球進行橢圓的排列並使其動起來:
分析過程:
橢圓軌跡的運動可以分解為左右反復運動和上下反復運動的疊加而形成的復合運動。知道了這一點之后我們就可以嘗試使得一個球進行該運動
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <style> .area{ width: 1200px; height: 800px; background: green; } .area>.ball{ width: 60px; height: 60px; position: absolute; border-radius: 60px; background-image: linear-gradient(to top,blue,lightblue); box-shadow: 0px 0px 20px #0000ff5c; } .area>.ball1{ animation: anmiteX 12s linear 0s infinite alternate, anmiteY 12s linear 0s infinite alternate; } /* 動畫 */ /* 在X軸上的移動 */ @keyframes anmiteX{ from{ left: 100px; } to{ left: 1000px; } } /* 在軸上Y的移動 */ @keyframes anmiteY{ from{ top: 100px; } to{ top: 600px; } }</style> <div class="area"> <div class="ball ball1"></div> </div> </body> </html>
以上的代碼我們得到的是如下的動畫,從左上角到右下叫的疊加動畫,是不是之前的分析出錯了呢,並沒有只是我們漏分析了運動的時間差,當x軸開始運動的時候,Y軸的開始位置要在中間了,也可以理解為在開始運動的時候Y軸先運動了一半,那么假設整個完成一個橢圓的運動時間未24秒,也就是x軸來回運動疊加上Y軸來回運動的時間是24秒。那么運動一趟的時間未24/2=12秒,Y軸的運動時間是biX軸的領先一半那么時間未12/2=6秒;現在對XY軸的運動疊加上時間差
.area>.ball1{ animation: anmiteX 12s linear -6s infinite alternate,/* 疊加上6秒時間差 */ anmiteY 12s linear 0s infinite alternate; }
已經是一個橢圓的運行軌跡了。接下來就是進行六個球的同時運動。
分析:六個球進行橢圓運動的軌跡沒有變化,只是起始的時間不同,那么假設運行一圈的時間未24 秒 那么六個橢圓的時間差位24/6=4秒,也就是說每個球的其實位置間隔4秒那么CSS代碼表現如下
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <style> .area{ width: 1200px; height: 800px; background: green; } .area>.ball{ width: 60px; height: 60px; position: absolute; border-radius: 60px; background-image: linear-gradient(to top,blue,lightblue); box-shadow: 0px 0px 20px #0000ff5c; } /* 6個球 總共運行一圈的時間為24秒 每個球的間隔時間為 4秒*/ .area>.ball1{ animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -6s infinite alternate, anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) 0s infinite alternate, scale 24s cubic-bezier(0.6,0.3,0.3,0.6) 0s infinite alternate; } .area>.ball2{ animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -10s infinite alternate, anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -4s infinite alternate, scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -4s infinite alternate; } .area>.ball3{ animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -14s infinite alternate, anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -8s infinite alternate, scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -8s infinite alternate; } .area>.ball4{ animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -18s infinite alternate, anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -12s infinite alternate, scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -12s infinite alternate; } .area>.ball5{ animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -22s infinite alternate, anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -16s infinite alternate, scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -16s infinite alternate; } .area>.ball6{ animation: anmiteX 12s cubic-bezier(0.6,0.3,0.3,0.6) -26s infinite alternate, anmiteY 12s cubic-bezier(0.6,0.3,0.3,0.6) -20s infinite alternate, scale 24s cubic-bezier(0.6,0.3,0.3,0.6) -20s infinite alternate; } /* 動畫 */ /* 在X軸上的移動 */ @keyframes anmiteX{ from{ left: 100px; } to{ left: 1000px; } } /* 在軸上Y的移動 */ @keyframes anmiteY{ from{ top: 100px; } to{ top: 600px; } } /* 對球進行放大和縮小在視覺上進行遠近的模擬 */ @keyframes scale{ 0%{ transform: scale(0.7,0.7); } 50%{ transform: scale(1.2,1.2); } 100%{ transform: scale(0.7,0.7); } } </style> <div class="area"> <div class="ball ball1"></div> <div class="ball ball2"></div> <div class="ball ball3"></div> <div class="ball ball4"></div> <div class="ball ball5"></div> <div class="ball ball6"></div> </div> </body> </html>
以上是完整的代碼 並添加了放大縮小的動畫使得運動更加立體,運動軌跡使用塞爾曲線cubic-bezier()來定義,以下就是具體的運行結果了
進階:
很多時候球的個數是不定的,而且需要進行懸浮小球暫停運動的操作,那么這樣的需求就要使用到javascript來進行動態生成了
<script type="text/javascript"> // nameArr 球的名稱,runtime 運行一圈的時間.warmballArr 爆滿的球素組 function addBall(num,runtime){ let _parentbox=document.getElementsByClassName('area')[0]; let _innerHtml=""; for (let i = 0; i <num; i++) { let _xtime=parseFloat(runtime/4); let _ytime=parseFloat(runtime/num); let _style=` animation: anmiteX `+(runtime/2)+`s cubic-bezier(0.36, 0, 0.64, 1) -`+(_xtime+(i*_ytime))+`s infinite alternate, anmiteY `+(runtime/2)+`s cubic-bezier(0.36, 0, 0.64, 1) -`+(i*_ytime)+`s infinite alternate, scale `+runtime+`s cubic-bezier(0.36, 0, 0.64, 1) -`+(i*_ytime)+`s infinite alternate; `; _innerHtml+=` <div class=" ball`+(i+1)+` ball " Style="`+_style+`"> </div>` } _parentbox.innerHTML=_innerHtml; } // 添加懸浮暫停事件 function ballring(){ var items = document.getElementsByClassName("ball"); for (var i = 0; i < items.length; i++) { items[i].addEventListener('click', function () { // console.log(this) }) } for (var i = 0; i < items.length; i++) { items[i].addEventListener('mouseover', function () { for (j = 0; j < items.length; j++) { items[j].style.animationPlayState = "paused";; } }) items[i].addEventListener('mouseout', function () { for (j = 0; j < items.length; j++) { items[j].style.animationPlayState = "running";; } }) } } addBall(8,32); ballring(); </script>
知識鏈接:
碼字不易,如果覺得不錯給個贊咯!