話很少說,先展現效果圖。因爲錄製工具,稍顯卡頓,實際是流暢的。能夠看到實現了無縫輪播,鼠標懸停,點擊左右上下按鈕切換Banner的功能,如圖1所示。javascript
圖1 原生無縫banner效果展現css
以我這個輪播圖爲例,總共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圖,無論多少張,還須要在頭部以前多加一張尾部的圖,尾部以後多加一張頭部的圖,這兩張是重複的,這樣整個流程看起來就是無縫的。html
圖2 部分html代碼java
而後再貼上代碼。ide
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>
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;}
css裏須要注意的幾個地方是width和height要與圖片的長度和寬度相對應。banner至關於容器,只顯示一張的長度,而bannerList的width是N張banner圖加頭尾各兩張,總共是N+2張圖片的長度,如圖3所示。ui
圖3 部分css代碼this
js:url
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; }
js須要注意的animate函數中的-544和-1632,如圖4所示,一個是一張圖片的長度,一個是到三張圖片的長度。此函數傳入的參數544也是banner圖的長度。其中的(time / inteval)須要能被整除,不然最終回調go函數執行結束的時候,頁面會顯示差好幾px纔會把下一張圖覆蓋。
圖4 js部分代碼
如今網上有不少Banner輪播圖這類已經封裝好的插件,好比PC端ElementUI(餓了麼團隊開源的)的走馬燈效果,或是Mobile端MintUI(一樣是餓了麼團隊開源的)的Swipe以及Mand Mobile(滴滴團隊開源的)的Swiper。功能也很豐富,效果也很炫酷。可是不少功能是已經寫死了的,雖然也夠用了,可是不免會遇到些刁鑽的需求,這些固定的功能不能很好的知足這些需求,這樣,就很須要本身手寫一個。