話不多說,先展示效果圖。由於錄製工具,稍顯卡頓,實際是流暢的。可以看到實現了無縫輪播,滑鼠懸停,點擊左右上下按鈕切換Banner的功能,如圖1所示。 圖1 原生無縫banner效果展示 以我這個輪播圖為例,總共3張圖的Banner輪播圖,實際上是由5張圖組成,如圖2所示。一張圖片長544px,所以s ...
話不多說,先展示效果圖。由於錄製工具,稍顯卡頓,實際是流暢的。可以看到實現了無縫輪播,滑鼠懸停,點擊左右上下按鈕切換Banner的功能,如圖1所示。
圖1 原生無縫banner效果展示
以我這個輪播圖為例,總共3張圖的Banner輪播圖,實際上是由5張圖組成,如圖2所示。一張圖片長544px,所以style用了絕對定位,將其定位在圖片banner_1上。當位置為4的圖片banner_3,繼續往下輪播的時候,就會被js定位到位置為1的圖片banner_3的位置,而位置為5的圖片banner_1只是提供了一種偽裝的效果,相當於副本,讓用戶看起來是無縫切換的。同理,位置為1的banner_3也是為了點擊向上一張的時候提供的副本,實際會被定位到位置為5的banner_3的位置。所以,這邊的輪播圖需要裡面不僅需要所有用到的banner圖,不管多少張,還需要在頭部之前多加一張尾部的圖,尾部之後多加一張頭部的圖,這兩張是重覆的,這樣整個流程看起來就是無縫的。
圖2 部分html代碼
然後再貼上代碼。
html:

<div id="banner"> <div id="bannerList" style="left: -544px;"> <img src="./images/banner_3.jpg"/> <img src="./images/banner_1.jpg"/> <img src="./images/banner_2.jpg"/> <img src="./images/banner_3.jpg"/> <img src="./images/banner_1.jpg"/> </div> <div id="bannerButtons"> <span index="1" class="on"></span> <span index="2"></span> <span index="3"></span> </div> <!-- 使a標簽不跳轉但仍然執行其功能,使用href="#"也可起到同樣效果 --> <a href="javascript:;" id="prev" class="arrow"></a> <a href="javascript:;" id="next" class="arrow"></a> </div>View Code
css:

#banner {width: 544px; height: 414px;margin-top: 9px;margin-left: 9px; float: left;position: relative;overflow: hidden;} #bannerList {width: 2720px;height: 414px;position: absolute;z-index: 1;} #bannerList img {width: 544px;float: left;} #bannerButtons {width: 70px;height: 12px;bottom: 20px;left: 240px;position: absolute;z-index: 2;display: table-cell;} #bannerButtons span {width: 10px;height: 10px;float: left;margin-right: 5px;cursor: pointer;border: 1px solid #fff;border-radius: 50%;background: #333;} #bannerButtons .on {background:#1fa4f0;width: 12px;height: 12px;border-radius: 50%;} .arrow {width: 40px;height: 40px;top: 180px;display: none;font-size: 36px;font-weight: bold;line-height: 39px;position: absolute;z-index: 2;cursor: pointer;text-align: center;color: #fff;background-color: RGBA(0,0,0,.3);} .arrow:hover {background-color: RGBA(0,0,0,.7);} #banner:hover .arrow {display: block;} #prev {left: 20px;background: url(../images/ui-slider-arrow.png) no-repeat;border-radius: 5px;} #next {right: 20px;background: url(../images/ui-slider-arrow.png) no-repeat -40px;border-radius: 5px;}View Code
css里需要註意的幾個地方是width和height要與圖片的長度和寬度相對應。banner相當於容器,只顯示一張的長度,而bannerList的width是N張banner圖加頭尾各兩張,總共是N+2張圖片的長度,如圖3所示。
圖3 部分css代碼
js:

window.onload = function () { var prev = document.getElementById("prev"); var next = document.getElementById("next"); var list = document.getElementById("bannerList"); var buttons = document.getElementById("bannerButtons").getElementsByTagName("span"); var banner = document.getElementById("banner"); var index = 1; var timer; var animated = false; function shownButton() { for (var i = 0; i < buttons.length; i++) { if (buttons[i].className == 'on') { buttons[i].className = ''; /* prev和next每click一次,就會清除一次前一個class為on的span元素,*/ break; } // 或者直接遍歷清除 buttons[i].className=""; } buttons[index - 1].className = "on";//Banner滾動的時候下邊焦點跟隨 } function animate(offset) { var time = 272; var inteval = 16; //(time/inteval)要為整數,能被整除,否則因為影響到list.style.left的位移量。這裡的值也可以寫死。 var speed = offset / (time / inteval); animated = true; var newLeft = parseInt(list.style.left) + offset; function go() { if ((speed > 0 && parseInt(list.style.left) < newLeft) || (speed < 0 && parseInt(list.style.left) > newLeft)) { list.style.left = parseInt(list.style.left) + speed + 'px'; setTimeout(go, inteval);//回調函數,一張圖輪播到另一張圖的中間過程。每執行一次go函數,都會位移一點,直到整個圖被下個圖替換就會退出此函數。 } else { animated = false; // list.style.left=newLeft+"px"; if (newLeft > -544) { list.style.left = -1632 + "px"; }; if (newLeft < -1632) { list.style.left = -544 + "px"; }; } } go(); }; prev.onclick = function () { if (!animated) { if (index == 1) { index = 3; } else { index -= 1; } shownButton(); animate(544); } }; next.onclick = function () { if (!animated) { if (index == 3) { index = 1; } else { index += 1; } shownButton(); animate(-544); } }; for (var i = 0; i < buttons.length; i++) { buttons[i].onclick = function () { //無關緊要,判斷目前banner圖是否是用戶正要選擇的 if (this.className == "on") { return; } var myIndex = parseInt(this.getAttribute("index")); var offset = -544* (myIndex - index); if (!animated) { animate(offset); } index = myIndex; shownButton(); } } function play() { timer = setInterval(function () { next.onclick(); }, 2000);//banner停止滾動,展示banner的時間 } function stop() { clearInterval(timer); } play(); banner.onmouseover = stop;//滑鼠在banner停留時停止滾動 banner.onmouseout = play; }View Code
js需要註意的animate函數中的-544和-1632,如圖4所示,一個是一張圖片的長度,一個是到三張圖片的長度。此函數傳入的參數544也是banner圖的長度。其中的(time / inteval)需要能被整除,否則最終回調go函數執行結束的時候,頁面會顯示差好幾px才會把下一張圖覆蓋。
圖4 js部分代碼
現在網上有很多Banner輪播圖這類已經封裝好的插件,比如PC端ElementUI(餓了麽團隊開源的)的走馬燈效果,或是Mobile端MintUI(同樣是餓了麽團隊開源的)的Swipe以及Mand Mobile(滴滴團隊開源的)的Swiper。功能也很豐富,效果也很炫酷。但是很多功能是已經寫死了的,雖然也夠用了,但是難免會遇到些刁鑽的需求,這些固定的功能不能很好的滿足這些需求,這樣,就很需要自己手寫一個。