前面我們通過《css佈局簡史與決勝未來的第四代css佈局技術》瞭解了css佈局發展史和未來,下面,我們通過《使用flex進行網易雲音樂界面構建和佈局解析》瞭解一下,如何在實際項目中使用flex進行佈局,相信大家也體會到了它的便捷之處。今天我們就深入項目的細節,說說每一個切圖人員繞不過去的坎兒,也是jser必須要面對的一個常規任務--《網易雲音樂高複用的響應式輪播圖的實現》
輪播圖相對於大家的工作,就和你首次去女朋友家的準備工作一樣,重要而且繞不過去。遺憾的是,大部分人寫輪播圖都跟第一次見家長一樣,沒什麼經驗。
很多人想自己寫一套輪播圖,然後以後工作中不斷的完善,最後形成自己的插件庫,遺憾的是有這個想法的大部分人,到了行動的時候才發現,想要實現它,比兌現“結婚就買套房”的諾言都難。最後只好迫於項目壓力和自身技能水平,變成了插件的搬運工。
可是插件搬運工有三個問題,首先這個東西對一個人的技術成長沒什麼用,其次也是重點,插件並不能完全符合項目需求,自己又沒有能力進行二次開發,遇上詭異bug也只能聽天由命,繼續踏上尋找更合適的插件的慢慢征途。最後,有些插件很重,很臃腫,但你只需要的是最基礎的輪播功能而已。你會爲了吃上一碟醋,專門包頓餃子嗎?我想不會。那你爲什麼僅僅爲了使用一個輪播圖會而項目裏面使用幾百k甚至上M的插件?
很多人可能會說因爲不會寫,好,今天我們就來實現一個,你會發現原來js的世界如此的簡單和美好,有找插件的功夫,你都能開發出8個插件了。
往上看,大家都認的啥叫輪播圖,仔細看下你第一步要做的至少說我拖着一個東西得能動,哪怕是一個紅色方塊唄。這裏就得說下拖拽,拖拽改變的無非就是left和top值(外星人才改right和bottom,我們地球人一般都用left和top,別問我爲什麼),先讓他在一個方向上動起來。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#div1 {
width: 100px;
height: 100px;
position: absolute;
left: 50px;
top: 50px;
background: red;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function () {
var oDiv = document.getElementById('div1');
var disX = 0;
oDiv.addEventListener("touchstart", function (e) {
var startPoint = e.changedTouches[0].pageX;
var startLeft = oDiv.offsetLeft;
disX = startPoint - startLeft;
});
oDiv.addEventListener("touchmove", doMove,false);
function doMove(e) {
var currPoint = e.changedTouches[0].pageX;
var newLeft = currPoint - disX;
oDiv.style.left = newLeft +'px';
}
function doUp(e) {
var currPoint = e.changedTouches[0].pageX;
var newLeft = currPoint - disX;
oDiv.style.left = newLeft +'px';
oDiv.removeEventListener("touchmove", doUp,false);
oDiv.removeEventListener("touchend", doUp,false);
}
oDiv.addEventListener("touchend", doUp,false);
}, false);
</script>
</head>
<body>
<div id="div1"></div>
</body>
</html>
仔細看,無非就是用了移動端事件而已,分分鐘就能理解,問題是很多同學會說,老師,我不理解這裏,這是啥,
var currPoint = e.changedTouches[0].pageX;
var newLeft = currPoint - disX;
oDiv.style.left = newLeft +'px';
這個又是啥?
var currPoint = e.changedTouches[0].pageX;
var newLeft = currPoint - disX;
oDiv.style.left = newLeft +'px';
oDiv.addEventListener("touchmove", doUp,false);
oDiv.addEventListener("touchend", doUp,false);
其實這些就是核心內容,簡單的說就是一張圖,非常簡單的圖,你一看就能懂!
其實就是算藍線的距離只要藍線正確,位置就錯不了,真要是理解不了也沒事,你就把他當成公式記住一點毛病也沒有。有了這些基礎知識就好辦了,搭個架子,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.swiper-container {
width: 320px;
height: 130px;
position: relative;
margin: 20px auto;
overflow: hidden;
}
.swiper-container .swiper-wrapper {
width: 2240px;
height: 130px;
position: absolute;
left: 0px;
}
.swiper-container .swiper-wrapper img {
width: 320px;
height: 130px;
float: left;
display: block;
}
.swiper-container ul {
width: 35px;
height: 4px;
position: absolute;
bottom: 10px;
left: 50%;
margin-left: -15px;
}
.swiper-container ul li {
width: 4px;
height: 4px;
border-radius: 2px;
border: 0.25px solid #fff;
margin-left: 2.5px;
background: #666;
float: left;
cursor: pointer;
}
.swiper-container ul .active {
background: #fff;
}
.swiper-container ul li:hover {
background: #fff;
}
</style>
</head>
<body>
<div class="swiper-container">
<div class="swiper-wrapper">
<img src="images/4.jpg">
<img src="images/0.jpg">
<img src="images/1.jpg">
<img src="images/2.jpg">
<img src="images/3.jpg">
<img src="images/4.jpg">
<img src="images/0.jpg">
</div>
<ul>
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
var oSWiperContainer = document.querySelector(".swiper-container");
var oSWiperWrapper = document.querySelector(".swiper-container .swiper-wrapper");
var aImg = document.querySelectorAll(".swiper-container .swiper-wrapper img")
var aLi = document.querySelectorAll(".swiper-container ul li");
oSWiperContainer.addEventListener("touchstart", function (e) {
var disX = 0;
var startPoint = e.changedTouches[0].pageX;
var startLeft = oSWiperWrapper.getBoundingClientRect().left;
disX = startPoint - startLeft;
oSWiperContainer.addEventListener("touchmove", doMove, false);
oSWiperContainer.addEventListener("touchend", doUp, false);
function doMove(e) {
var currPoint = e.changedTouches[0].pageX;
var newLeft = currPoint - disX;
oSWiperWrapper.style.left = newLeft + 'px';
}
function doUp(e) {
oSWiperContainer.removeEventListener("touchmove", doUp, false);
oSWiperContainer.removeEventListener("touchend", doUp, false);
}
}, false);
}, false);
</script>
</body>
</html>
至少現在一拖拽走起來了,這裏簡單吧,連縱向都不用考慮,輪播比拖拽還簡單,只考慮水平方向,
問題是鬆手了以後,輪播圖的,每一項沒去正確的位置,啥叫正確的位置,其實每次改變的left的值將好是一個輪播圖的寬度,上圖。
!你先別管別的,看紅框就是手機屏幕寬度,每次其實就是移動一個格子。那我只要定一個iNow值記錄移動幾個格子,只要iNow正確就一切OK了唄,說幹就幹。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.swiper-container {
width: 320px;
height: 130px;
position: relative;
margin: 20px auto;
overflow: hidden;
}
.swiper-container .swiper-wrapper {
width: 2240px;
height: 130px;
position: absolute;
left: 0px;
transition: .3s all ease;
}
.swiper-container .swiper-wrapper img {
width: 320px;
height: 130px;
float: left;
display: block;
}
.swiper-container ul {
width: 35px;
height: 4px;
position: absolute;
bottom: 10px;
left: 50%;
margin-left: -15px;
}
.swiper-container ul li {
width: 4px;
height: 4px;
border-radius: 2px;
border: 0.25px solid #fff;
margin-left: 2.5px;
background: #666;
float: left;
cursor: pointer;
}
.swiper-container ul .active {
background: #fff;
}
.swiper-container ul li:hover {
background: #fff;
}
</style>
</head>
<body>
<div class="swiper-container">
<div class="swiper-wrapper">
<img src="images/1.jpg">
<img src="images/2.jpg">
<img src="images/3.jpg">
<img src="images/4.jpg">
</div>
<ul>
<li class="active"></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
var oSWiperContainer = document.querySelector(".swiper-container");
var oSWiperWrapper = document.querySelector(".swiper-container .swiper-wrapper");
var aImg = document.querySelectorAll(".swiper-container .swiper-wrapper img")
var aLi = document.querySelectorAll(".swiper-container ul li");
var iNow = 0;
var oW = aImg[0].offsetWidth;
oSWiperContainer.addEventListener("touchstart", function (e) {
var disX = 0;
var startPoint = e.changedTouches[0].pageX;
var startLeft = oSWiperWrapper.getBoundingClientRect().left;
disX = startPoint - startLeft;
oSWiperContainer.addEventListener("touchmove", doMove, false);
oSWiperContainer.addEventListener("touchend", doUp, false);
function doMove(e) {
var currPoint = e.changedTouches[0].pageX;
var newLeft = currPoint - disX;
oSWiperWrapper.style.left = newLeft+'px';
}
function doUp(e) {
var endPoint = e.changedTouches[0].pageX;
if(endPoint-startPoint>50){
iNow--;
if(iNow==-1){
iNow = 0;
}
oSWiperWrapper.style.left = -iNow*oW+'px';
}
if(endPoint-startPoint<-50){
iNow++;
if(iNow==aImg.length){
iNow = aImg.length -1;
}
oSWiperWrapper.style.left = -iNow*oW+'px';
}
oSWiperContainer.removeEventListener("touchmove", doMove, false);
oSWiperContainer.removeEventListener("touchend", doUp, false);
}
}, false);
}, false);
</script>
</body>
</html>
強調一點,getBoundingClientRect(),這裏我爲什麼沒用offsetLeft呢?因爲實際項目裏面不可能輪播圖的外層什麼都不套,或者說萬一有margin、padding,輪播圖的距離就不對了,使用offsetLeft是不具有項目的實用性的,做演示還行,實際項目那麼寫就廢了。
最後我說一個無限輪播圖,其實就是算數字的,!)所謂無限輪播的原理,就是當iNow 等於最右邊的0的時候,拉回到紅框位置,左側是當iNow 等於 最左邊的4的時候,iNow等於6.
很多人有了源代碼就忽略了基礎的學習,直接拿過去用了,那跟直接找插件沒區別,所以這個就當一個小練習吧。
四個練習:
1.實現多屏幕相應適配
2.實現無線輪播
3.實現如果滑動距離不超過50px就不播下一張
4.實現定時器自動輪播!
這裏我把上面四個練習解決方法的左側代碼放出來作爲提示,大家儘量學會實現。
注意學習是一個過程,不是一個結果,得到最終的源碼不重要,學會自己實現這個才重要,畢竟網上有太多的資源和插件代碼,如果那個有用,那麼每一個人的工資都應該非常高才對。那爲什麼很多人的技術水平並不高,工資也不理想呢,是因爲大家只努力去得到結果,而忽視了技術的實現過程。端盤子和吃菜誰都會,但是飯店卻只會給廚師高工資就是這個道理。我們要做的是廚師,不是端盤子的服務員或者食客(此處僅爲了說明過程的重要性,無其他意思)。
就說這麼多吧,最後一句。牛頓說過,我有一個蘋果我吃了你瞅着我就比你幸福,錯了牛頓說他沒說過這句話,他說的是,我有一個思想,你也有一個,咱倆一交換,就又生一個思想(牛頓好像大意如此,大家理解就OK)。
所以大家有問題可以留言,根據大家的留言我會提供更有針對性的課程。