天天看點

仿網易輪播圖(html+css+javascript)

本篇部落格還是有點難度的,前前後後加起來花了一天時間才算搞明白。涉及的技術棧包括定時器、動畫原理、排他思想、json解析、浏覽器相容性問題、根據圖檔動态顯示張數等。關鍵點是點選上一張和下一張以及特定張時的邏輯實作。

html代碼

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>網易輪播圖</title>
		<link rel="stylesheet" type="text/css" href="css/base.css" target="_blank" rel="external nofollow" />
		<script type="text/javascript" src="js/animate.js" ></script>
		<script type="text/javascript" src="js/base.js" ></script>
	</head>
	<body> 
		<div class="w-slider" id="js_slider">
			<div class="slider">
				<div class="slider-main" id="slider_main_block">
					<div class="slider-main-img"><a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ><img src="images/1.jpg" alt="" /></a></div>
					<div class="slider-main-img"><a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ><img src="images/2.jpg" alt="" /></a></div>
					<div class="slider-main-img"><a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ><img src="images/3.jpg" alt="" /></a></div>
					<div class="slider-main-img"><a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ><img src="images/4.jpg" alt="" /></a></div>
					<div class="slider-main-img"><a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ><img src="images/5.jpg" alt="" /></a></div>
					<div class="slider-main-img"><a href="#" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" ><img src="images/6.jpg" alt="" /></a></div>
				</div>
			</div>
			<div class="slider-ctrl" id="slider_ctrl">
				<span class="slider-ctrl-prev"></span>
				<span class="slider-ctrl-next"></span>
			</div>
		</div>
	</body>
</html>
           

base.css代碼

*{
	margin: 0;
	padding: 0;
}
img{
	/*去除圖檔地下的空隙*/
	vertical-align: top;
}
.w-slider{
	width: 310px;
	height: 265px;
	margin: 100px auto;
	position: relative;
	overflow: hidden;
}
.slider{
	width: 310px;
	height: 220px;
}
.slider-main{
	width: 620px;
	height: 220px;
}
.slider-main-img{
	position: absolute;
	top: 0;
	left: 0;
	
}
.slider-ctrl{
	text-align: center;
	padding-top: 5px;
}
.slider-ctrl-con{
	width: 24px;
	height: 20px;
	background:url(../images/icon.png) no-repeat -24px -782px;
	display: inline-block;
	margin: 0 5px;
	cursor: pointer;
	/*首行縮進*/
	text-indent: -20em;
	overflow: hidden;
	
}
.current{
	background-position:-24px -762px ;
}
.slider-ctrl-prev,
.slider-ctrl-next{
	position: absolute;
	top: 50%;
	margin-top: -35px;
	width: 20px;
	height: 35px;
	background: url(../images/icon.png) no-repeat 6px top;
	opacity: 0.8;
	cursor: pointer;
}
.slider-ctrl-prev{
	left: 0;
}
.slider-ctrl-next{
	right: 0;
	background-position: -14px -44px;
}
           

animate.js

/**
 * Created by ydj on 2018/08/08.
 */
// 多個屬性運動架構  添加回調函數
function animate(obj,json,fn) {  // 給誰    json
    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        var flag = true;  // 用來判斷是否停止定時器   一定寫到周遊的外面
        for(var attr in json){   // attr  屬性     json[attr]  值
            //開始周遊 json
            // 計算步長    用 target 位置 減去目前的位置  除以 10
            // console.log(attr);
            var current = 0;
            if(attr == "opacity")
            {
                current = Math.round(parseInt(getStyle(obj,attr)*100)) || 0;
                console.log(current);
            }
            else
            {
                current = parseInt(getStyle(obj,attr)); // 數值
            }
            // console.log(current);
            // 目标位置就是  屬性值
            var step = ( json[attr] - current) / 10;  // 步長  用目标位置 - 現在的位置 / 10
            step = step > 0 ? Math.ceil(step) : Math.floor(step);
            //判斷透明度
            if(attr == "opacity")  // 判斷使用者有沒有輸入 opacity
            {
                if("opacity" in obj.style)  // 判斷 我們浏覽器是否支援opacity
                {
                    // obj.style.opacity
                    obj.style.opacity = (current + step) /100;
                }
                else
                {  // obj.style.filter = alpha(opacity = 30)
                    obj.style.filter = "alpha(opacity = "+(current + step)* 10+")";

                }
            }
            else if(attr == "zIndex")
            {
                obj.style.zIndex = json[attr];
            }
            else
            {
                obj.style[attr] = current  + step + "px" ;
            }

            if(current != json[attr])  // 隻要其中一個不滿足條件 就不應該停止定時器  這句一定周遊裡面
            {
                flag =  false;
            }
        }
        if(flag)  // 用于判斷定時器的條件
        {
            clearInterval(obj.timer);
            //alert("ok了");
            if(fn)   // 很簡單   當定時器停止了。 動畫就結束了  如果有回調,就應該執行回調
            {
                fn(); // 函數名 +  ()  調用函數  執行函數
            }
        }
    },10)
}
function getStyle(obj,attr) {  //  誰的      那個屬性
    if(obj.currentStyle)  // ie 等
    {
        return obj.currentStyle[attr];  // 傳回傳遞過來的某個屬性
    }
    else
    {
        return window.getComputedStyle(obj,null)[attr];  // w3c 浏覽器
    }
}
           

base.js

window.onload = function() {
	// 1.擷取元素
	function $(id) {
		return document.getElementById(id);
	}
	// 2.擷取最大的盒子
	var js_slider = $("js_slider");
	// 3.擷取圖檔組的父類
	var slider_main_block = $("slider_main_block");
	// 4.擷取圖檔組
	var imgs = slider_main_block.children;
	// 5.擷取控制span的父盒子
	var slider_ctrl = $("slider_ctrl");
	// 6.動态生成小span
	for (var i = 0, len = imgs.length; i < len; i++) {
		// 7.建立元素
		var span = document.createElement("span");
		// 8.為生成的span添加類名,并且倒叙指派 疊加現象
		span.className = "slider-ctrl-con";
		span.innerHTML = len - i;
		// 9.将生成的span插入到盒子中
		slider_ctrl.insertBefore(span, slider_ctrl.children[1]);
	}
	// 10 為插入的第一個span設定樣式
	var spans = slider_ctrl.children;
	spans[1].setAttribute("class", "slider-ctrl-con current");
	// 11.獲得後面動畫走的距離
	var scrollWidth = js_slider.clientWidth;
	// 12.開始時隻有第一張圖檔留下,其餘的走到顯示框的右邊
	for (var i = 1; i < imgs.length; i++) {
		imgs[i].style.left = scrollWidth + "px";
	}
	// 16.控制圖檔的張數
	var Now = 0;
	// 13.開始周遊spans 圖檔+左右的輪播共計8個
	for (var k in spans) {
		spans[k].onclick = function() {
			// 14.判斷目前的span是不是prev
			if (this.className == "slider-ctrl-prev") {
				//alert("左側按鈕");
				// 15.開始動畫了 第一個參數 誰要動   第二參數 怎麼動  第三個參數 回調函數(可省落)
				animate(imgs[Now], {
					left: scrollWidth
				});
				// 17.上一張圖檔要快速的走到顯示框的左側,然後慢慢的走到舞台中
				--Now < 0 ? Now = imgs.length - 1 : Now;
				imgs[Now].style.left = -scrollWidth + "px";
				animate(imgs[Now], {
					left: 0
				});
				setSquare();
			}
			// 18.判斷目前的按鈕時next
			else if(this.className=="slider-ctrl-next"){
				// 19.目前的圖檔先慢慢的走到舞台的左邊,下一張快速走到舞台的右側,然後慢慢的走到舞台中
//				animate(imgs[Now],{left:-scrollWidth});
//				++Now > imgs.length -1 ?Now =0:Now;
//				imgs[Now].style.left = scrollWidth + "px";
//				animate(imgs[Now],{left:0});
//				setSquare();
				autoPlay();
			}else{
				// 20.點選圖檔下方的序列 1-2-3-4-5-6 對應圖檔序号是 0-1-2-3-4-5
				var that = this.innerHTML -1;
				if(that >Now){
					// 21.處理邏輯和next按鈕類似 目前的慢慢的走到舞台的左側,下一張快速走到右側
					animate(imgs[Now],{left:-scrollWidth});
					imgs[that].style.left = scrollWidth + "px";
					//animate(imgs[that],{left:0});
				}else if(that < Now){
					// 22 .處理邏輯和prev類似,目前的慢慢走到舞台的右側,下一張快速走到舞台的左側
					animate(imgs[Now],{left:scrollWidth});
					imgs[that].style.left = -scrollWidth + "px";
					//animate(imgs[that],{left:0});
				}
				//else{
					Now = that;
					animate(imgs[Now],{left:0});
					
				//}
				setSquare();
			}

		}
	}
	// 設定走動的顯示序列
	function setSquare(){
		// 去掉頭部的prev 和尾部的next 兩個小span
		for(var i = 1,len = spans.length-1;i<len;i++){
			spans[i].className = "slider-ctrl-con";
		}
		// 這裡一定要+1 是下一張
		spans[Now+1].className = "slider-ctrl-con current";
	}
	// 設定定時器開始
	var timer = null;
	timer = setInterval(autoPlay,2000);
	// 23 仔細想想其實定時器的運動和設定next這個小span的功能是一樣一樣的
	function autoPlay(){
		// 19.目前的圖檔先慢慢的走到舞台的左邊,下一張快速走到舞台的右側,然後慢慢的走到舞台中
		animate(imgs[Now],{left:-scrollWidth});
		++Now > imgs.length -1 ?Now =0:Now;
		imgs[Now].style.left = scrollWidth + "px";
		animate(imgs[Now],{left:0});
		setSquare();
	}
	// 24.滑鼠經過清除定時器
	js_slider.onmouseover = function(){
		clearInterval(timer);
	}
	// 25.滑鼠移開是設定定時器
	js_slider.onmouseout = function(){
		// 先清除定時器
		clearInterval(timer);
		// 開啟定時器
		timer = setInterval(autoPlay,2000);
	}
}
           

繼續閱讀