1. 程式人生 > >原生JS輪播-各種效果的極簡實現

原生JS輪播-各種效果的極簡實現

star element length for sha 部分 wid 方式 高度

寒假持續摸魚中~此為老早以前博客的重寫,當時還是分開寫的,這裏匯總重寫,正好復習一遍~

春招我來了!
所有有意思的,一股腦先扔進收藏,然後再也不看哈哈,真是糟糕。
今日事,今日畢,說起來容易。
當時竟然不是用markdown寫的!
當時使用var還需要解決必報的問題!而如今使用ES6的let,自帶領域的感覺就是不一樣!

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    * {
      margin: 0;
      padding: 0;
    }
    ul, li {
      list-style: none;
    }
    body {
      background-color: #000;
    }
    .wrap {
      position: relative;
      border: 8px solid #fff;
      margin: 100px auto;
      width: 400px;
      height: 250px;
      overflow: hidden;
    }
    .pic-group {
      position: absolute;
      top: -250px;
    }
    .pic-group li img {
      display: block;
      width: 100%;
      height: 100%;
    }
  </style>
</head>
<body>
  <div class="wrap">
    <ul class="pic-group">
      <li><img src="./pic1.jpg" alt=""></li>
      <li><img src="./pic2.jpg" alt=""></li>
      <li><img src="./pic3.jpg" alt=""></li>
      <li><img src="./pic4.jpg" alt=""></li>
      <li><img src="./pic5.jpg" alt=""></li>
    </ul>
    <ol class="num-group">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ol>
  </div>
</body>
</html>

一.輪播是什麽?

輪播其實就是一個定時變換的廣告(卡片?圖片?)。
在HTML結構上他們其實是ul裏面的li。數據層面來說的話,他們就是list的一條數據。

那麽,這其中的變換其實也可以有很多種~你可能會知道現在的 vue-swiper這麽絢麗的輪播效果

  • 緩沖效果 --- 透明度變化(意味著一開始所有的item剛開始都是疊在一起的)
  • 滑動效果 --- position top位置的變化(意味著所有的item單/豎/橫向排列)

二.變化和上述的代碼分析 --- 改變 top 則切換圖片。

如上面的代碼,只搭了個結構,我們看到wrap層被設為了 1.position:relative2.overflow:hidden

,本質上是為了子層的pic-group服務的,我們設子層pic-group3.position:absolute,這樣的話 3 就可以根據 1和2 來達到 => 改變top位置(top位置為圖片高度的 n 倍哦!)

為了極簡!!!!!我這裏只設置了 .pic-group li img 的寬高。一般情況下其實每個外層元素都會寫一個具體的高寬的。

  • 為什麽我給.pic-group li img 設置 display:block ?

    實際上呢,img 它是行內元素。行內元素有默認的 4px 邊距。去除的辦法有 font-size:0等諸多方法,這裏我追求代碼極簡。所以一句話,變成塊級元素吧少年。

  • 為什麽我只給.pic-group li img 設置了 寬高?

    依舊為了極簡~實際上應該根據要求都設置一下寬高的。這裏的結果就是
    a.內層 img 寬高繼承了最外的 400 250
    =>
    b.繼而作為 li 的子層撐開了 li
    =>
    c.li 再繼續撐開 .pic-group
    =>
    d.因為.pic-group的高度被老大的overflow:hidden限制了,最後就變成了一張圖片。
    原來的樣子應該是好幾層圖片~

技術分享圖片

三.變化的契機 --- 誰來改變 top?

我們給我們的輪播案例加上數字,通過點擊數字來按下改變世界的開關!
首先這是我們給數字添加的樣式

.num-group {
      position: absolute;
      bottom: 0;
      right: 0;
      height: 20px;
    }
    .num-group li {
      float: left;
      width: 20px;
      height: 20px;
      line-height: 20px;
      font-size: 10px;
      margin-right: 10px;
      background-color: #089e8a;
      color: #eee;
      text-align: center;
      border-radius: 10px;
      cursor: pointer;
      opacity: 0.8;
    }
    .num-group li:hover {
      box-shadow: 0 0 18px #000;
    }
    .num-group li.current {
      opacity: 1;
      color: #089a8a;
      background-color: #000;
    }

這裏就不多解釋了,上面是是樣式的部分。
下面是JS的部分

// 首先,獲取我們要改變的元素
const oImage = document.getElementsByClassName("pic-group")[0];
// 其次,獲取改變世界的鑰匙
const oNumber = document.getElementsByClassName("num-group")[0];
const numList = oNumber.getElementsByTagName("li");
// 接下來,便是世界改變的邏輯
for (let i = 0; i < numList.length; i++) {
  // 關鍵:我們要把我們的 索引index 傳進 onclick/onmouseover 裏面
  numList[i].onclick = () => {
    // numList[i].className = "current";
    clearNumState();
    numList[i].className = "current";
    const topValue = - i * 250;
    oImage.style.top = topValue + "px";
  }
}
// 每次新點擊 num,先置空所有list的current的類,此後再添加當前索引
const clearNumState = () => {
  for (const item of numList) {
    item.className = "";
  }
}
通過上面的代碼我們已經可以實現點擊數字按鈕進行對圖片的切換了.

改變世界的最終還是 JS,而不是CSS,我們用JS給數字們添加上事件。
技術分享圖片
技術分享圖片

4.用戶體驗為王! -- 緩沖的輪播

點擊不能立馬切換圖片系列

時代在進步,刀耕火種的JS --- 談談重寫之前用var,重寫之後用let的變化

不用糾結閉包的問題了!!!!
哦草!
我他媽竟然忘了!

秀一秀古老的onclick

  for (var i = 0; i < oList.length; i++) {
    oList[i].onclick = function () {
      console.log(i);
    }
  }

這樣寫的後果是,無論怎麽寫,最後的i的結果都會是oList.length
閉包(匿名函數)要使用外部作用於中變量的結果,這也是由於匿名函數本身無法傳遞參數,
故無法維護自己的作用域。
當函數調用外部變量就構成一個閉包,裏面的變量會受到別的地方的影響。不可抗力!所以解決的方式是:構建一個只有匿名函數本身才可以訪問的閉包,保存只供本身使用的變量。

  • 古老的解決方案一.使用過去的 function 式函數,將 當前的 i 賦值給 index

      for (var i = 0; i < oList.length; i++) {
    oList[i].index = i;
    oList[i].onclick = function () {
      console.log(this.index);
    }
      }
  • 古老的解決方案二.使用匿名函數的方式隔離外部的i => 匿名函數:這就是我的領域,魔法-畫地為牢!!!

      for (var i = 0; i < oList.length; i++) {
    (function (i) {
      oList[i].onclick = () => {
        console.log(i);
      }
    })(i);
      }
  • 然而我是現代人,能坐車我幹嘛要走路???So !

      for (let i = 0; i < oList.length; i++) {
    oList[i].onclick = () => {
      console.log(i);
    }
      }

    正所謂四兩撥千斤!什麽?你說沒差別? var -> let
    歸根結底還是作用域的問題,let 是自帶領域的。

最終代碼如下

github地址

原生JS輪播-各種效果的極簡實現