一、需求描述
標題“多尺寸圖片左右切換功能”,概括的不知道是否恰當,具體是需求如下。
- 一次點擊按鈕,向左或向右移動一個圖片。
- 切換到盡頭時不顯示按鈕
- 頁面有三個尺寸
可以一睹為快,看一下最終效果。
二、切圖代碼
1、代碼
html代碼如下:

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> <link rel="stylesheet" href="http://static9.pplive.cn/pub/flagment/v_20150114110035/header.min.css" /> <!--頁面初始化CSS和頁面公用頭部的css--> <link rel="stylesheet" href="css/vipgrowth.css"> <!--新增樣式的css,名稱可根據具體需求修改--> <script type="text/javascript" src="http://static9.pplive.cn/vip/201508/center/v_20150901140940/js/jquery-1.9.1.min.js"></script> <script> window.onresize = function() { var winWidth = document.body.clientWidth; if (winWidth <= 1230) { body.className = "grid-1010"; } else if (winWidth <= 1410) { body.className = "grid-1230"; } else if (winWidth > 1410) { body.className = "grid-1410"; } else { alert("do not know!"); } } </script> </head> <body id="body"> <script> //初始化狀態顯示樣式判斷,放在body后面 var winWidth = document.body.clientWidth; if (winWidth <= 1230) { body.className = "grid-1010"; } else if (winWidth <= 1410) { body.className = "grid-1230"; } else if (winWidth > 1410) { body.className = "grid-1410"; } else { alert("do not know!"); } </script> <div class="vg-body"> <!--任務成長值 開始--> <div class="vg_title"> <p>任務成長值</p> </div> <div class="vg_task"> <div class="arrowbtn-left"></div> <div class="arrowbtn-right"></div> <div class="vg_tasklist"> <ul class="cf" id="switchPic"> <li> <img src="images/task_year.png"> <div class="rightinfo"> <h3>開通年費會員</h3> <p>獎勵成長值<span>200</span>點</p> <a href="javascript:;">已完成></a> </div> <div class="task_hover"> <p class="task_desc">一次性開通年費會員(12個月及以上)</p> <p class="task_limittimes">月限<span>1</span>次</p> <a href="javascript:;" class="done">已完成</a> </div> </li> <li> <img src="images/task_lianxubaoyue.png"> <div class="rightinfo"> <h3>開通連續包月</h3> <p>獎勵成長值<span>10</span>點</p> <a href="javascript:;">去完成></a> </div> <div class="task_hover"> <p class="task_desc">一次性開通年費會員(12個月及以上)</p> <p class="task_limittimes">月限<span>1</span>次</p> <a href="javascript:;">去完成></a> </div> </li> <li> <img src="images/task_year.png"> <div class="rightinfo"> <h3>升級成為SVIP</h3> <p>獎勵成長值<span>10</span>點</p> <a href="javascript:;">去完成></a> </div> <div class="task_hover"> <p class="task_desc">一次性開通年費會員(12個月及以上)</p> <p class="task_limittimes">月限<span>1</span>次</p> <a href="javascript:;">去完成></a> </div> </li> <li> <img src="images/task_year.png"> <div class="rightinfo"> <h3>關注微信公眾號</h3> <p>獎勵成長值<span>10</span>點</p> <a href="javascript:;">去完成></a> </div> <div class="task_hover"> <p class="task_desc">一次性開通年費會員(12個月及以上)</p> <p class="task_limittimes">月限<span>1</span>次</p> <a href="javascript:;">去完成></a> </div> </li> <li> <img src="images/task_year.png"> <div class="rightinfo"> <h3>任務555555555</h3> <p>獎勵成長值<span>10</span>點</p> <a href="javascript:;">去完成></a> </div> <div class="task_hover"> <p class="task_desc">一次性開通年費會員(12個月及以上)</p> <p class="task_limittimes">月限<span>1</span>次</p> <a href="javascript:;">去完成></a> </div> </li> <li> <img src="images/task_year.png"> <div class="rightinfo"> <h3>任務666666666</h3> <p>獎勵成長值<span>10</span>點</p> <a href="javascript:;">去完成></a> </div> <div class="task_hover"> <p class="task_desc">一次性開通年費會員(12個月及以上)</p> <p class="task_limittimes">月限<span>1</span>次</p> <a href="javascript:;">去完成></a> </div> </li> <li> <img src="images/task_year.png"> <div class="rightinfo"> <h3>任務7777777</h3> <p>獎勵成長值<span>10</span>點</p> <a href="javascript:;">去完成></a> </div> <div class="task_hover"> <p class="task_desc">一次性開通年費會員(12個月及以上)</p> <p class="task_limittimes">月限<span>1</span>次</p> <a href="javascript:;">去完成></a> </div> </li> </ul> </div> </div> <!--任務成長值 結束--> </div> </body> <script> //task growth var switchPic = (function() { /* now:當前第幾個li linum:總共幾個li shownum:要展示幾個li w_li:li的寬度 marginR_li:li的右邊距 */ var now = 1; var linum, shownum, offset, w_li, marginR_li, pre, next, wrap; function init(o) { pre = o.preBtn; next = o.nextBtn; wrap = o.wrap; bindBtn(); } function btnShow() { getInfo(); if (linum <= shownum) { //如果li總個數小於要展示的個數,pre和next都不顯示 pre.hide(); next.hide(); } else if (now == 1) { //初始化,只顯示next pre.hide(); next.show(); } else if (now == linum - shownum + 1) { //到最后一組,只顯示pre pre.show(); next.hide(); } else { //中間pre,next都顯示。 pre.show(); next.show(); } } function getInfo() { linum = $("#switchPic").find("li").size(); if ($("#body").hasClass("grid-1010")) { shownum = 3; w_li = wrap.find("li").outerWidth(); //算上了border的寬度 marginR_li = parseInt(wrap.find("li").css("marginRight")); offset = w_li + marginR_li; } else if ($("#body").hasClass("grid-1230")) { shownum = 4; w_li = wrap.find("li").outerWidth(); //算上了border的寬度 marginR_li = parseInt(wrap.find("li").css("marginRight")); offset = w_li + marginR_li; } else if ($("#body").hasClass("grid-1410")) { shownum = 4; w_li = wrap.find("li").outerWidth(); //算上了border的寬度 marginR_li = parseInt(wrap.find("li").css("marginRight")); offset = w_li + marginR_li; } } function bindBtn() { btnShow(); next.on("click", function() { now++; btnShow(); wrap.stop(true).animate({ "margin-left": -(now - 1) * offset }); }); pre.on("click", function() { now--; btnShow(); wrap.stop(true).animate({ "margin-left": -(now - 1) * offset }); }); $(window).resize(function() { now = 1; btnShow(); wrap.animate({ "margin-left": 0 }); }); } return { init: init } })(); switchPic.init({ preBtn: $(".arrowbtn-left"), nextBtn: $(".arrowbtn-right"), wrap: $("#switchPic") }); </script> </html>
css代碼如下:

@charset "utf-8"; html,body{ background-color: #f6f5f5; } .vg-body{ width: 1390px; margin:0 auto; } /*任務成長值*/ .vg_title{ font-size: 24px; line-height: 24px; padding:20px 0; color:#464646; } .vg_task{ background-color: #fff; position: relative; } .vg_task .arrowbtn-left,.vg_task .arrowbtn-right{ position: absolute; top:70px; width: 16px; height: 20px; cursor: pointer; } .vg_task .arrowbtn-left{ left: 40px; background:url(../images/arrow-left.png) no-repeat;; } .vg_task .arrowbtn-right{ right: 40px; background:url(../images/arrow-right.png) no-repeat;; } .vg_tasklist{ width: 1200px; overflow: hidden; margin:0 auto; } .vg_tasklist ul{width: 999%;} .vg_tasklist li{ width: 258px; height: 130px; float: left; border:1px solid #c8c8c8; margin:15px 53px 15px 0; position: relative; } .vg_tasklist li .task_hover{ position: absolute; left: -1px; top: -1px; width: 212px; padding:20px 25px 20px 23px; height: 90px; border-bottom: 2px solid #e65a5a; overflow: hidden; background-color: #f0f0f0; display: none; } .vg_tasklist li:hover .task_hover{ display: block; } .task_hover .task_desc{ font-size: 16px; line-height: 20px; color:#646464; } .task_hover .task_limittimes{ font-size: 14px; color: #787878; float: left; padding-top: 12px; } .vg_tasklist li img{ float: left; margin: 22px 8px 20px 20px; } .vg_tasklist li .rightinfo{ width: 136px; float: left; text-align: center; } .rightinfo h3{ font-size: 16px; color: #646464; padding-top: 15px; } .rightinfo p{ font-size: 14px; line-height: 26px; color: #787878; } .rightinfo a,.task_hover a{ display: block; text-align: center; width: 96px; height: 30px; line-height: 30px; border:2px solid #e65a5a; border-radius: 5px; font-size: 16px; font-weight: 700; color: #e65a5a; } .task_hover a.done,.task_hover a.done:hover{ background-color: #b4b4b4; color: #fff; border-color: #b4b4b4; cursor: default; } .rightinfo a{ margin: 12px auto 0; } .task_hover a{ float: right; margin-top: 18px; margin-right: -4px; } .task_hover a:hover{ text-decoration: none; background-color: #e65a5a; color: #fff; } /*grid-1230*/ .grid-1230 .vg-body{ width: 1210px; } .grid-1230 .vg_tasklist{ width: 1090px; } .grid-1230 .vg_tasklist li{ margin-right: 16px; } .grid-1230 .vg_task .arrowbtn-left{ left: 33px; } .grid-1230 .vg_task .arrowbtn-right{ right: 33px; } .grid-1230 .vg_growth_table { padding:24px 30px; } /*grid-1010*/ .grid-1010 .vg-body{ width: 990px; } .grid-1010 .vg_tasklist{ width: 850px; } .grid-1010 .vg_tasklist li{ margin-right: 35px; } .grid-1010 .vg_task .arrowbtn-left{ left: 30px; } .grid-1010 .vg_task .arrowbtn-right{ right: 30px; } .grid-1010 .vg_growth_table { padding:24px; }
2、切圖分析
根據切好的圖,向右切換的時候,margin需要向左移動的距離為(li的width+2*border+margin-right)。
width+2*border在jquery中可用用outerWidth()獲取。
margin-right的值在jquery中用css("marginRight")獲取。
二、js交互部分
1、思路
總共就一個響應事件,就是點擊按鈕,以next按鈕為例。點按鈕發生了哪些事件。點擊按鈕—》ul產生位移—》更新按鈕狀態。或者點擊按鈕—》更新按鈕狀態—》ul產生位移。順序可以改變
第一步:分析ul產生位移的過程。
抽象2個變量
now:表示當前頁面第一個展示位展示的是第幾個li,默認為1,向右切換now++,向左切換now--。
offset:表示i的width+2*border+margin-right。
這樣點擊按鈕時的響應就變成了設置margin-left為-(now-1)*offset。
因為頁面有三個尺寸,所以點擊按鈕時ul產生位移時需要根據尺寸計算出offset的值。
第二步,分析更新按鈕狀態的過程。
分析一下這句話“切換到盡頭時不顯示按鈕”,頁面默認只顯示向右的按鈕,切換到到最左邊只顯示向左的按鈕,中間過程兩個按鈕都要顯示。
抽象出幾個變量:
linum:總共有幾個li,一次切換一個。
shownum:頁面需要展示幾個li。
now:當前頁面第一個展示位展示的是第幾個li,默認為1,向右切換now++,向左切換now--。
分析幾種情況:
- 如果li的總數小於要展示的數,即linum<shownum,pre和next按鈕都不顯示。
- 初始化,判斷now為1,只顯示next按鈕。
- 展示到最后shownum個li的時候,即判斷now==linum-shownum+1時,只顯示next按鈕。
- 否則pre和next按鈕都顯示。
因為頁面有三個尺寸,所以點擊按鈕更新按鈕狀態時需要根據尺寸計算出shownum的值。
第三步:提取方法
把第一步和第二步中涉及通過尺寸獲取信息的部分封裝成一個函數。getInfo。
第二步更新按鈕狀態的封裝成一個函數。btnShow。
第一步中給按鈕綁定事件的過程封裝成一個函數。bindBtn。
同時要注意,頁面縮放的時候,需要重置一些狀態。
2、代碼實現
<script> //task growth var switchPic = (function() { /* now:當前第幾個li linum:總共幾個li shownum:要展示幾個li w_li:li的寬度 marginR_li:li的右邊距 */ var now = 1; var linum, shownum, offset, w_li, marginR_li, pre, next, wrap; function init(o) { pre = o.preBtn; next = o.nextBtn; wrap = o.wrap; bindBtn(); } function btnShow() { getInfo(); if (linum <= shownum) { //如果li總個數小於要展示的個數,pre和next都不顯示 pre.hide(); next.hide(); } else if (now == 1) { //初始化,只顯示next pre.hide(); next.show(); } else if (now == linum - shownum + 1) { //到最后一組,只顯示pre pre.show(); next.hide(); } else { //中間pre,next都顯示。 pre.show(); next.show(); } } function getInfo() { linum = $("#switchPic").find("li").size(); if ($("#body").hasClass("grid-1010")) { shownum = 3; w_li = wrap.find("li").outerWidth(); //算上了border的寬度 marginR_li = parseInt(wrap.find("li").css("marginRight")); offset = w_li + marginR_li; } else if ($("#body").hasClass("grid-1230")) { shownum = 4; w_li = wrap.find("li").outerWidth(); //算上了border的寬度 marginR_li = parseInt(wrap.find("li").css("marginRight")); offset = w_li + marginR_li; } else if ($("#body").hasClass("grid-1410")) { shownum = 4; w_li = wrap.find("li").outerWidth(); //算上了border的寬度 marginR_li = parseInt(wrap.find("li").css("marginRight")); offset = w_li + marginR_li; } } function bindBtn() { btnShow(); next.on("click", function() { now++; btnShow(); wrap.stop(true).animate({"margin-left": -(now - 1) * offset}); }); pre.on("click", function() { now--; btnShow(); wrap.stop(true).animate({"margin-left": -(now - 1) * offset}); }); $(window).resize(function() { now = 1; btnShow(); wrap.animate({"margin-left": 0}); }); } return {init: init} })(); switchPic.init({ preBtn: $(".arrowbtn-left"), nextBtn: $(".arrowbtn-right"), wrap: $("#switchPic") }); </script>
三、一個小tip
在寫動畫的時候,用了
wrap.stop(true).animate()
把當前元素涉及的所有動畫都停止了,讓后再觸發。否則當頁面快速resize,快速點擊按鈕多次,會產生“動畫積累”,觸發了下一個動畫,之前的動畫還沒完,就會有一個延遲,影響用戶體驗。
stop()參數說明:
$(selector).stop(stopAll,goToEnd)
- stopAll,可選,規定是否停止被選元素的所有加入隊列的動畫。
- goToEnd,可選,規定是否允許完成當前的動畫。該參數只能在設置了stopAll參數時使用。
具體用法:
- stop(true)等價於stop(true,false): 停止被選元素的所有加入隊列的動畫。
- stop(true,true):停止被選元素的所有加入隊列的動畫,但允許完成當前動畫。
- stop()等價於stop(false,false):停止被選元素當前的動畫,但允許完成以后隊列的所有動畫。
- stop(false,true):立即結束當前的動畫到最終效果,然后完成以后隊列的所有動畫。
在此提供一個小 demo,可以幫助理解stop()各個參數。

<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <title>stop的用法案例</title> <style type="text/css"> #animater { width: 150px; background: activeborder; border: 1px solid black; /*為了移動,需設置此屬性*/ position: relative; } </style> <script src="http://code.jquery.com/jquery-3.1.0.js" integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" crossorigin="anonymous"></script> <script type="text/javascript"> $(function() { $("#start").click(function() { $("#box").animate({ height: 300 }, "slow"); $("#box").animate({ width: 300 }, "slow"); $("#box").animate({ height: 100 }, "slow"); $("#box").animate({ width: 100 }, "slow"); }); // 點擊不同的button執行不同的操作 $('#button1').click(function() { //默認參數是false,不管寫一個false還是兩個false還是沒寫false效果一樣 $('#box').stop(); }); $('#button2').click(function() { //第二個參數默認false $('#box').stop(true); }); $('#button3').click(function() { $('#box').stop(false, true); }); $('#button4').click(function() { $('#box').stop(true, true); }); }) </script> </head> <body> <p> <input type='button' value='開始測試' id='start'> </p> <div id="button"> <input type="button" id="button1" value="stop()" /> <input type="button" id="button2" value="stop(true)" /> <input type="button" id="button3" value="stop(false,true)" /> <input type="button" id="button4" value="stop(true,true)" /> </div> <div id="box" style="background:#98bf21;height:100px;width:100px;position:relative">stop運動參數測試</div> </body> </html>
本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章內容也不定時更新,為避免誤導讀者,方便追根溯源,請諸位轉載注明出處:http://www.cnblogs.com/starof/p/5443445.html有問題歡迎與我討論,共同進步。