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

 

 
結果
相關文章
相關標籤/搜索