CSS動效集錦,視覺魔法的碰撞與融合(三)


本文講述的原理和相關demo
  • 扇形DIV的使用——實現雷達掃描圖
  • DIV環形布局—實現loading圈
  • 動畫的向量合成—實現拋物線動畫
  • 無限滾動動畫—實現跑馬燈效果
  • perspective和transform的運用——實現卡片翻轉
 
話不多說,請看。
 

扇形DIV的使用——實現雷達掃描圖

在一些殺毒或文件掃描類的軟件上,我們可能會看到一些雷達掃描的UI樣式,例如下圖所示
 
如果我們要通過CSS該如何去實現話,我們的想法一般是先畫個扇形,然后給它加上漸變。
實現漸變的方式很簡單,但我們該如何實現一個扇形呢?
 
我們可以通過一些技巧實現這一點,請看:
沒錯,我們可以通過skew函數,將黃色的div傾斜,然后溢出部分通過overflow:hidden遮住就可以了。
  • 銳角扇形:deg<0,向右邊傾斜,即可得到銳角扇形
  • 鈍角扇形:deg>0, 向左邊傾斜,即可得到鈍角扇形
 
代碼如下
// CSS代碼
@keyframes rotateAnimate {
  from {
    transform: rotate(0deg) skew(-30deg)
  }
 
  to {
    transform: rotate(360deg) skew(-30deg)
  }
}
 
.fan-wrapper {
  overflow: hidden;
  position: relative;
  margin: 100px;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: red;
}
 
.fan {
  position: absolute;
  right: 0;
  animation: rotateAnimate 2s linear infinite;
  /* 這一行很重要,設置左下角為旋轉點 */
  transform-origin: 0% 100%;
  width: 100px;
  height: 100px;
  background: blue;
}
 // HTML代碼    
 <div class="fan-wrapper">
  <div class="fan"></div>
</div>
 
實現效果如下圖所示
(因為篇幅有限,漸變就不加了2333)
 

DIV環形布局—實現loading圈

 
loading加載條是常見的一種UI組件,如下圖所示
而要實現它,就需要考慮怎么把一堆小圓等距地布局在一個“大圓”的邊框上,也就是DIV的環形布局的問題。
當然我們可以通過暴力測量解決,但很麻煩且不優雅,而且如果小圓的數量變化的話要重新測一遍。
我的解決辦法如下:
 
第一步:根據圓的數量計算相鄰圓和圓心形成的夾角
例如假設我們需要排列8個圓,那么夾角為360度 / 8 = 45度。圖示如下,每個數字代表以該位置為圓心放一個小圓
 
第二步:以外部DIV左下角為原點,批量計算小圓圓心的橫縱坐標
批量算出所有圓的相對坐標,我們以編號8的圓為例,假設半徑R和X軸的逆時針夾角為θ,則有以下等式
(cos/sin可能有正負,而等式同樣成立)
第三步,外部div相對定位,內部小圓絕對定位,並且將步驟二中計算的X/Y作為小圓的bottom和left去設置
這一步也是批量完成,下圖以編號8的圓為例
 
代碼
CSS/HTML代碼如下:
我們在一個父div內部放8個子div。父div相對定位,而子div絕對定位
// CSS代碼
.circles {
  position: relative;
  margin: 50px;
  width: 200px;
  height: 200px;
}
 
.circle {
  position: absolute;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: black;
}
 // HTML
<div class="circles">
  <div class="circle circle1"></div>
  <div class="circle circle2"></div>
  <div class="circle circle3"></div>
  <div class="circle circle4"></div>
  <div class="circle circle5"></div>
  <div class="circle circle6"></div>
  <div class="circle circle7"></div>
  <div class="circle circle8"></div>
</div>

 

 
JS代碼如下
第一步:編寫calcXYs方法: 以外部DIV左下角為原點,批量計算小圓圓心的橫縱坐標
/**
 * R:大圓半徑,2*R = 外部正方形的邊長
 * r:在大圓邊上等距排列的小圓的半徑
 * counts: 圓的數量
 * 返回值:
 *  [
 *    [x1,y1],
 *    [x2,y2],
 *    ...
 *  ]
 */
function calcXYs(R, r, counts) {
  // 當前度數
  let deg = 0;
  // 單位度數,兩小圓和圓心的夾角
  const pDeg = 360 / counts;
  // 存放返回結果
  const arr = [];
  for (let i = 0; i < counts; i++) {
    // 度數以單位度數遞增
    deg = pDeg * i;
    // Math.sin接收的參數以 π 為單位,需要根據360度 = 2π進行轉化
    const proportion = Math.PI / 180;
    // 以外部DIV左下角為原點,計算小圓圓心的橫縱坐標
    let Y = R + R * Math.sin(proportion * deg);
    let X = R + R * Math.cos(proportion * deg);
    // 存放結果
    arr.push([X, Y, deg]);
  }
  return arr;
}
 
第二步:編寫resizeCircles方法: 根據上一步的結果:調整絕對定位的小圓的位置
/**
 * R,r,counts:含義同上
 * selector: 獲取所有小圓的標志符
 * 作用:根據上一步的坐標計算結果,調整絕對定位的小圓的位置
 */
function resizeCircles(selector, R, r, counts) {
  // 獲取所有小圓NodeList的選擇器
  let list = document.querySelectorAll(selector);
  //調用calcXYs方法
  const XYs = calcXYs(R, r, counts);
  // 遍歷每個小圓的XY坐標
  for (let i = 0; i < list.length; i++) {
    const [X, Y] = XYs[i];
    const e = list[i];
    // 修改小圓距離外部DIV底部和左邊的距離
    e.style.left = X + "px";
    e.style.bottom = Y + "px";
  }
}
 
最后我們只需要調用resizeCircles方法就可以啦
resizeCircles(".circle", 60, 20, 8);

 

實現效果如下
 
讓loading圖標動起來
好,現在布局完成了,那我們該怎么去讓這個loading圖標“動起來”呢?
  1. 給每個圓設置animation實現明暗變化,例如可以設置黑色的背景色然后動態變化opacity
  2. animation屬性可以設置delay實現動畫延遲播放,我們依次給圓設置等距的delay,例如1s,2s,3s...
  3. 給animation屬性設置alternate,表示往復播放,設置infinite,表示無限循環播放
 
@keyframes k {
  from {
    opacity: 1;
  }
 
  to {
    opacity: 0;
  }
}
.circle1 {
  animation: k 1s ease 0s alternate infinite;
}
 
.circle2 {
  animation: k 1s ease 0.2s alternate infinite;
}
 
.circle3 {
  animation: k 1s ease 0.4s alternate infinite;
}
// circle4 ~ circle8同理,delay以0.2s遞增

 

 
Demo
 

動畫的向量合成—實現拋物線動畫

 
在餓了么,或者淘寶天貓之類的購物外賣相關的APP里,我們可能會看到類似於下面這種的拋物線的動畫。
 
如果要實現這種平拋效果,需要一點基礎的高中物理知識。
平拋運動由水平方向的兩種運動合成而得到
  • 水平方向: 勻速直線運動
  • 垂直方向:初速度為0的勻加速直線運動
如下所示
 
如果我們通過圖像捕捉的方式就可理解的更清楚了,從下面的圖可以看到:
水平方向的速度是不變的,而垂直方向的速度是不斷加快的
好,下面終於可以講下CSS的實現思路了
CSS實現原理
  1. 設置兩個div:外層div和內層div
  2. 外層div設置橫向勻速運動的動畫
  3. 內層div設置縱向的勻加速直線運動的動畫,加速過程可以用cubic-bezier設置
 
cubic-bezier又叫做貝塞爾曲線,它可接收四個參數,來規定動畫的速度變化過程,使用方法如下
transition-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1);
 
我們可以通過下面這個官方網站去設置速度變化曲線,然后獲取生成的四個參數
 
具體代碼如下:
 // HTML
<div id="outer">
  <div id="inner"></div>
</div>
<button id='btn'>拋物線效果</button>
// CSS #outer
{ transition: all 1.5s linear; } #inner { width: 30px; height: 30px; border-radius: 50%; background: red; transition: all 1.5s cubic-bezier(.54, .11, .95, .68); } .outer-active { transform: translateX(300px); } .inner-active { transform: translateY(300px) scale(0.3); }

 

JS
document.getElementById("btn").onclick = function() {
  document.getElementById("outer").classList.add("outer-active");
  document.getElementById("inner").classList.add("inner-active");
};
 
效果如下
 
 
 

無限滾動動畫—實現跑馬燈效果

當文本過長時候,我們可能需要做成跑馬燈效果,然后無限滾動播放。
 
因為marquee這個HTML元素被廢棄了,所以一般情況下我們需要手動通過動畫去實現跑馬燈
實現圖示如下,注意開始位置和結束位置是不可見的
 
// HTML
<div class="marquee">
  <p>ABCDEFGHIJKLMN</p>
</div>
// CSS
@keyframes marquee {
  from {
    transform: translateX(-200px)
  }
 
  to {
    transform: translateX(200px)
  }
}
 
.marquee {
  overflow: hidden;
  margin: 100px;
  width: 200px;
}
 
.marquee p {
  animation: marquee 3s linear infinite;
}
 
結果
 
 

perspective和transform的運用——實現卡片翻轉

卡片翻轉三要素
  • transform: rotateY(x deg) 翻轉卡片
  • backface-visibility:hidden 翻轉后隱藏背面,重要!必須要加
  • perspective:增加透視和立體效果
 
// HTML
<div id="img-wrapper">
  <img src='./timg.jpg' id='img1' class="img disable-img1" />
  <img src='./timg2.jpg' id='img2' class="img" />
</div>
 
// CSS
#img-wrapper {
  perspective: 1200px;
  position: relative;
  height: 479px;
}
 
#img1,
#img2 {
  position: absolute;
  transition: all 1s linear;
  backface-visibility: hidden;
}
 
#img1 {
  transform: rotateY(-180deg);
}
 
#img-wrapper:hover #img1 {
  transform: rotateY(-360deg);
}
 
#img-wrapper:hover #img2 {
  transform: rotateY(-180deg);
}

 

 
結果
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM