javascript-輪播圖

學(xué)習(xí)了許多的javascript知識(shí),我們今天來(lái)做一個(gè)應(yīng)用—輪播圖。許多網(wǎng)站上都有輪播圖,像淘寶,京東等電商網(wǎng)站的首頁(yè),輪播圖總是不可獲取的頁(yè)面組成元素。往往大家都是上網(wǎng)找插件(最出名的可能是swiper)。假如自己動(dòng)手讓你用原生js寫(xiě)一個(gè)呢?
下面我們開(kāi)始今天的主題,一個(gè)可自動(dòng)輪播+點(diǎn)擊輪播+無(wú)縫滾動(dòng)的原生輪播圖。
上代碼:
css部分

  // 樣式重置
* {
        margin: 0;
        padding: 0;
        list-style: none;
    }
// 主要樣式
// 大盒子
  .box{
      width: 560px;
      height: 300px;
      position: relative;
      overflow: hidden;
      border: 1px solid #f00;
      margin: 30px auto;
      box-shadow: 1px 1px 10px 5px blue;
    }
// 包裹圖片的盒子,這樣做是為了無(wú)縫滾動(dòng)服務(wù)
    .wrap{
      position: relative;
      width: 5000px;
      height: 300px;
      top: 0;
      left: 0px;
    }
// 圖片盒子
    .wrap ul{
      position: absolute;
      top: 0;
      left: 0;
    }
    .wrap ul li{
      float: left;
    }
// 控制圓點(diǎn)盒子
    .control{
      position: absolute;
      bottom: 5px;
      right: 0;
    }
// 控制圓點(diǎn)設(shè)置
    .control li{
      margin-right: 5px;
      width: 20px;
      height: 20px;
      line-height: 20px;
      font-weight: bold;
      text-align: center;
      background: #fff;
      cursor: pointer;
      border-radius: 50%;
      float: left;
    }
// 選中狀態(tài)
    .control li.active{
      background: red;
      color: #fff;
    }
// 按鈕盒子
    .btn{
      position: absolute;
      width: 100%;
      top: 50%;
      margin-top: -25px;
    }
// 按鈕樣式
    .btn a{
      width: 50px;
      height: 50px;
      line-height: 45px;
      text-decoration-line: none;
      color: aliceblue;
      font-size: 36px;
      background: rgba(0, 0, 0, .5);
      text-align: center;
      border-radius: 50%;
      opacity: .5;
      display: none;
    }
    .btn .prev{
      float: left;
    }
    .btn .next{
      float: right;
    }
// 滑入選中狀態(tài)
    .btn .prev:hover,
    .btn .next:hover {
        filter: alpha(opacity=100);
        opacity: 1;
    }

css部分需要注意的是我們要做無(wú)縫滾動(dòng)的效果所以我們的大盒子 wrap 要寬度足夠才能讓每一張圖片排成一排,因?yàn)槲覀兪冀K動(dòng)的只是包裹圖片的 ul。

接下來(lái)是html:

  <div class="box" id="wrap">
    <div class="wrap" >
      <ul id="imgBox"></ul>
    </div>
    <ul class="control" id="control"></ul>
    <div class="btn">
      <a href="javascript:;" class="prev">&lt;</a>
      <a href="javascript:;" class="next">&gt;</a>
    </div>
  </div>

布局這方面沒(méi)啥說(shuō)的,因?yàn)槭莿?dòng)態(tài)生成圖片和控制圓點(diǎn),所以沒(méi)有直接寫(xiě) li。

下面主要的來(lái)了

js部分:

 // 元素獲取
    var wrap = document.getElementById("wrap")
    var imgBox = document.getElementById("imgBox");
    var control = document.getElementById("control");
    var prev = document.getElementsByTagName("a")[0];
    var next = document.getElementsByTagName("a")[1];
    var imgWidth = 560;
    var target = 0;
    var imgIndex = 0;
    var timer = null;
    var autoTimer = null;

    // ------------------------start--------------------
    var imgs = [
      'img/0.jpg',
      'img/1.jpg',
      'img/2.jpg',
      'img/3.jpg',
      'img/4.jpg'
    ]
    var lis = []; // 圖片列表數(shù)組
    var ctrs = [];// 控制點(diǎn)數(shù)組
    // 動(dòng)態(tài)創(chuàng)建圖片列表
    for (let index = 0; index < imgs.length; index++) {
      lis.push('<li><img src="'+imgs[index]+'" /></li>')
      ctrs.push('<li>'+(index-1+2)+'</li>')
    }
    // 加入到頁(yè)面中
    imgBox.innerHTML = lis.join("");
    // 復(fù)制節(jié)點(diǎn)
    imgBox.appendChild(imgBox.children[0].cloneNode(true));

    control.innerHTML = ctrs.join("");
    control.children[0].setAttribute("class","active");
    //---------------------------------------------------
    //按鈕顯示隱藏
    wrap.onmouseover = function () {
        prev.style.display = "block";
        next.style.display = "block";
        clearInterval(autoTimer);// 清除自動(dòng)輪播
    }
    wrap.onmouseout = function () {
        prev.style.display = "none";
        next.style.display = "none";
        autoPlay();// 開(kāi)啟自動(dòng)輪播
    }
    // 控制點(diǎn)循環(huán)綁定事件
    var ctrlis = control.getElementsByTagName("li");
    for (let i = 0; i < ctrlis.length; i++) {
      ctrlis[i].index = i;// 記錄元素
      ctrlis[i].onmouseover = function(){
        // clearInterval(timer);
        imgIndex = this.index;
        animate(imgIndex);
      }
      
    }
    // 上一頁(yè)
    prev.onclick = function(){
      clearInterval(timer);// 清除運(yùn)動(dòng)定時(shí)器
      imgIndex--;
      if (imgIndex == -1) {
        imgBox.style.left = -imgWidth*(imgBox.children.length-1) + "px";
        imgIndex = imgBox.children.length-2;
      }
      animate(imgIndex);

    }
    // 下一頁(yè)
    next.onclick = function(){
      clearInterval(timer);
      imgIndex++;
      if (imgIndex == imgBox.children.length) {
        imgBox.style.left = 0;
        imgIndex = 1;
      }
      animate(imgIndex);
    }
    // 運(yùn)動(dòng)封裝
    function animate(index){
      clearInterval(timer);
      // 控制點(diǎn)樣式修改
      for(let i = 0; i < ctrlis.length; i++){
        ctrlis[i].className = "";
      }
      ctrlis[index%ctrlis.length].className="active"
      //開(kāi)啟定時(shí)器
      timer = setInterval(function(){
        target = -index*imgWidth; // 目標(biāo)距離
        var step = 210/30;// 運(yùn)動(dòng)次數(shù) 這個(gè)可以設(shè)置參數(shù)傳入,像index一樣,后面再加一位參數(shù),這里就寫(xiě)死了
        let speed = (target - imgBox.offsetLeft)/step // 每次步長(zhǎng)是由目標(biāo)距離減去當(dāng)前距離
        speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); // 取整方便計(jì)算
        if (target == imgBox.offsetLeft) {
          clearInterval(timer);// 到達(dá)終點(diǎn),我們要停止運(yùn)動(dòng)
        }else{
          imgBox.style.left = imgBox.offsetLeft + speed + "px";// 這是left值
        }
      },30);
    }
    // 自動(dòng)輪播
    function autoPlay() {
      autoTimer = setInterval(function(){
        // 這個(gè)邏輯和下一頁(yè)點(diǎn)擊的邏輯相同
        imgIndex++;
        if (imgIndex == imgBox.children.length) {
          imgBox.style.left = 0;
          imgIndex = 1;
        }
        animate(imgIndex);
      },2000)
    }
    autoPlay() // 開(kāi)始自動(dòng)輪播

這塊的js都是基礎(chǔ)知識(shí)的組裝,所以js基礎(chǔ)還是很重要的。
我們來(lái)講一下重點(diǎn):

  1. 標(biāo)簽的創(chuàng)建與添加,還有克隆, 用到了字符串拼接的方法,innerHtML、 appendChild()、cloneNode()。標(biāo)簽用字符串創(chuàng)建出來(lái)放進(jìn)數(shù)組,然后join(),是一個(gè)很使用的方法,以后會(huì)經(jīng)常用到的。
  2. 事件循環(huán)綁定中ctrlis[i].index = i 這一行是重點(diǎn),它使你能夠順利找到你對(duì)誰(shuí)綁定事件。
  3. 運(yùn)動(dòng)封裝中我們首先要找到目標(biāo)點(diǎn),然后減去當(dāng)前l(fā)eft值再除以運(yùn)動(dòng)次數(shù)來(lái)算出運(yùn)動(dòng)距離。這個(gè)是運(yùn)動(dòng)起來(lái)的關(guān)鍵。
  4. ctrlis[index%ctrlis.length].className="active" 這一行代碼是最不要忽視的,它是動(dòng)態(tài)改變小圓點(diǎn)的樣式,因?yàn)槲覀冏隽藷o(wú)縫滾動(dòng),但是小圓點(diǎn)還是只有我們能看到的圖片的個(gè)數(shù),重復(fù)的不算,所以要進(jìn)行取余數(shù)判斷,才不會(huì)報(bào)錯(cuò)。

好了,大概就是這么多內(nèi)容,有什么不足之處還希望大家見(jiàn)諒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,058評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,360評(píng)論 4 61
  • 原理 圖片輪播原理:將一系列大小相等的圖片平鋪,利用css布局只顯示一張圖片,其他圖片隱藏,通過(guò)計(jì)算偏移量利用定時(shí)...
    黎貝卡beka閱讀 2,322評(píng)論 1 2
  • Bitmap內(nèi)存優(yōu)化:Bitmap是內(nèi)存消耗大戶,絕大多數(shù)的OOM崩潰都是在操作Bitmap時(shí)產(chǎn)生的,下面來(lái)看看如...
    一航j(luò)ason閱讀 499評(píng)論 0 0
  • 德華,是和我一起長(zhǎng)大的發(fā)小,為人老實(shí)憨厚,不善言辭,但和我卻是無(wú)話不談。 高考名落孫山后,他和親戚去了南方打工。剛...
    奇樂(lè)融閱讀 380評(píng)論 0 0

友情鏈接更多精彩內(nèi)容