聲明:以下方法是剛入門前端實驗產品,高手繞道。
最近做自己網站的時候遇到輪播圖問題。網絡上無數個教程都描述瞭如何做出一個輪播圖,或者如何用jq做出一個自適應輪播圖。對於還沒有時間去了解jq的dba來說,實在沒有精力去了解jq(主要是js還不熟),但是自己琢磨了下好像可以用純js+css3實現自適應輪播。
鑑於是我無聊給我自己做的網站,所以在寫前端的時候沒有考慮太多支持各種老版本瀏覽器,所以兼容性問題不在討論範圍內。
正文:
輪播圖設計思路:
需求要點:
1、自動播放
2、左右按鈕控制變換
3、分頁下標
4、如果做全屏輪播圖,需要考慮屏幕寬度問題
實現思路:
1、需要一個一級容器存放所有數據,做鼠標移動暫停自動播放需要調用
2、需要多個二級容器存放內容,思路有兩種:
第一種各圖片層疊,用position 父模塊relative + 子模塊absolute屬性,
第二種僅在父級使用position relative屬性或者flex等模式,使其圖片水平橫向擴展
層疊需要從層級z-index屬性或者透明疊層等方向下手,能發展淡入淡出效果
橫向需要從圖片偏移像素下手,採用left屬性較多,比較容易實現橫向移動過度效果。
全屏輪播方式建議水平擴展而不是層疊,水平擴展如果是全屏輪播圖需要處理不同屏幕大小之間寬度問題,相對容易實現
局部輪播按需求可採用層疊等方式
3、分頁下標和二級容器放在同層級並且浮動到輪播圖父容器上
4、需要兩個按鈕放到最上層
offsetwidth 獲取left屬性所需要的自適應屏幕寬度
模塊樣式設計:
本次使用flex橫向擴展模式
1、確定一級box寬高
2、確定二級容器數據,做移動輪播寬度設定需要很長很長的寬度;
3、圖片容器寬度和需要展示寬度一致
4、浮動,用flex,移動採用 left
5、確定按鈕位置
6、確定下標位置和樣式顏色
7、自動輪播和鼠標暫停
注意細節:
1、自適應全屏的選擇,使用flex還是div等
2、js邊緣處理
3、分頁下表的移動和點擊操作
4、自動播放,原理是定時模擬點擊
如下圖我做的實驗截圖:
通過僞類可以讓按鈕在鼠標不在的情況下隱藏。
19年9.29,重構了代碼,解決了改變窗口大小造成的圖片位移,最後一張到第一張之間的過渡橫拉問題,加入響應式css,自適應各種屏幕,還有唯一一個問題待優化:在改變窗口大小口第一次滑動產生的快速位移,解決思路是寬度監聽端口中增加像素值判斷來優化,後續再嘗試;
css部分代碼如下:
/* 輪播圖 */
.img{
width: 100%;
height: 100%;
}
.lb_box{
width: 100%;
height: 25vw;
}
.lb_imgbox{
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.lb_imgleft{
width: 100%;
height: 100%;
position: relative;
left: 0;
transition:left 0.3s linear;
}
.lb_img{
width: 600%;
height: 100%;
display: flex;
}
.lb_li{
list-style: none;
display: block;
width: 100%;
height: 100%;
margin: 0;
}
.lb_point{
position: absolute;
bottom: 0;
width: 100%;
z-index: 1;
}
.li_ol{
display: flex;
justify-content:center;
}
.lb_olli{
list-style: none;
border: 0.2vw solid snow;
border-radius: 50%;
margin-left: 1%;
margin-right: 1%;
padding: 0.5%;
}
.lb_olli_color{
background-color: red;
}
@media screen and (max-width:599px){
.lb_btn{
display: none;
}
.lb_box{
height: 40vw;
}
}
.lb_btn{
position: absolute;
top: 30%;
height: 40%;
background: transparent;
background-color: rgba(0 , 0, 0, .5);
border: none;
width: 3vw;
z-index: 1;
}
.lb_btnl{
left: 0;
}
.lb_btnr{
right: 0;
}
/* !輪播圖 */
html代碼如下:
<!-- 輪播圖 -->
<section-lunbo style="width: 100%">
<div id="lb_id" class="lb_box">
<div class="lb_imgbox">
<div class="lb_imgleft">
<div class="lb_img">
<li class="lb_li"><a href=""><img class="img" src="picture/lunbo/4.jpg" alt=""></a></li>
<li class="lb_li"><a href=""><img class="img" src="picture/lunbo/1.jpg" alt=""></a></li>
<li class="lb_li"><a href=""><img class="img" src="picture/lunbo/2.jpg" alt=""></a></li>
<li class="lb_li"><a href=""><img class="img" src="picture/lunbo/3.jpg" alt=""></a></li>
<li class="lb_li"><a href=""><img class="img" src="picture/lunbo/4.jpg" alt=""></a></li>
<li class="lb_li"><a href=""><img class="img" src="picture/lunbo/1.jpg" alt=""></a></li>
</div>
</div>
<div class="lb_point">
<ol id = 'test' class="li_ol">
<li class="lb_olli"></li>
<li class="lb_olli"></li>
<li class="lb_olli"></li>
<li class="lb_olli"></li>
</ol>
</div>
<button id="lb_lbtn" class="lb_btn lb_btnl">left</button>
<button id="lb_rbtn" class="lb_btn lb_btnr">right</button>
</div>
</div>
</section-lunbo>
js代碼如下:
// 輪播圖js
window.onload = function(){
var lb_box = this.document.getElementsByClassName("lb_imgleft")[0];
//初始化默認寬度
var lb_boxwidth = this.document.body.clientWidth;
var lb_imglist = this.document.getElementsByClassName("lb_li").length;
var lbtn = this.document.getElementsByClassName("lb_btnl")[0];
var rbtn = this.document.getElementsByClassName("lb_btnr")[0];
var lb_pointlist = this.document.getElementsByClassName("lb_olli");
var num = 0;
var newwidth = 0;
//監聽屏幕寬度響應輪播圖寬度li大小縮放產生的偏移量
window.onresize = function(){
var leftsize = document.body.clientWidth;
if(leftsize!=lb_boxwidth && num >0){
lb_box.style.transition ="none";
lb_box.style.left = -leftsize +"px";
}
}
//點擊事件
rbtn.onclick = function(){
num ++;
//獲取自適應屏幕改變後寬度
newwidth = document.body.clientWidth;
if(num>lb_imglist-1){
num = 2;
}
left(newwidth);
//到最後一張的時候,快速切換到第一張,需要加延時等到倒數第二張切換到最後
//一張的動作結束才執行,否則立即執行會有左滑效果,延時時間等於動畫時間
if(num == lb_imglist-1){
setTimeout(function del(){
//清除切換樣式,無感知最後一張到第一張
lb_box.style.transition ="none";
lb_box.style.left = -newwidth +"px";
},300);
}
}
lbtn.onclick = function(){
num--;
newwidth = document.body.clientWidth;;
if(num<0){
num = lb_imglist-1;
}
left(newwidth);
if(num == 1){
setTimeout(function del(){
lb_box.style.transition ="none";
lb_box.style.left = -newwidth*(lb_imglist-1) +"px";
num = lb_imglist-1;
},300);
}
}
//下標被點擊:獲取點擊位置,切換到點擊頁面
for(var i=0;i<lb_pointlist.length;i++){
//設定下標索引
lb_pointlist[i].setAttribute("p_index",i);
lb_pointlist[i].onclick =function(){
num = this.getAttribute("p_index");
newwidth = document.body.clientWidth;;
left(newwidth);
}
}
//自動輪播,模擬點擊
var timer = setInterval(function(){
rbtn.onclick();
}, 4000);
//鼠標移入暫停,移入鼠標清除自動定時器
var lb_box_f = document.getElementsByClassName("lb_box")[0];
lb_box_f.onmouseenter = function(){
clearInterval(timer);
}
//移除鼠標繼續定時器
lb_box_f.onmouseleave = function(){
timer = setInterval(function(){
rbtn.onclick();
}, 4000);
}
function left(newwidth){
lb_box.style.transition ="left 0.3s linear";
//如果屏幕寬度改變,偏移量按照改變後的寬度設定
if(0<newwidth && newwidth!=lb_boxwidth){
lb_box.style.left = -newwidth*num +"px";
}
else
{
lb_box.style.left = -lb_boxwidth*num +"px";
}
//小圓點
for(var i=0;i<lb_pointlist.length;i++){
lb_pointlist[i].style.backgroundColor = "transparent";
if(num<4){
lb_pointlist[num].style.backgroundColor = "snow";
}
else{
lb_pointlist[num-4].style.backgroundColor = "snow";
}
}
}
}
心得:
1、flex盒子做浮動時,需要定義position屬性,flex默認時static的塊屬性,對於static而言left屬性是沒有效果的,所以需要定義成position以便能使用left操作進行左右移動變換
2、自適應全屏,left所需移動的寬度需要獲取當前屏幕的寬度具體像素,因爲flex定義的百分比寬度不能直接用於left,所以需要用clientwidth獲取當前屏幕的寬度數值
3、由於用的flex盒子,ul寬度是根據百分比定義的,不需要預估屏幕像素大小,同時也不需要去寫一個js監聽屏幕大小來自適應,flex自己能做到自適應,在不同屏幕上自動按比例改變圖像,相對來說少了監聽要簡單些。
4、定時器原理是定時模仿點擊函數即可,當初糾結了好久怎麼實現
5、解決最後一張到第一張之間的過度,出了首尾添加多一張圖片以外,需要讓倒數第二張切換到最後一張的動作做完,所以重置最後一張等於第一張圖片位置時需要加延時函數,否則立即執行會產生倒數第二張立即切換到第一張的左滑效果。延時時間等於動畫時間即可消除左滑效果。
6、高度跟隨寬度,寬度和高度比可以通過padding-botton或者vw來確定,看個人喜好。