<!-- 輪播圖div -->
<div class="banner">
<!-- 輪播圖内容 -->
<ul></ul>
<!-- 焦點按鈕 -->
<ol></ol>
<!-- 左右切換按鈕 -->
<div>
<a href="JavaScript:;" name="left"><</a>
<a href="JavaScript:;" name="right">></a>
</div>
</div>
* {
margin: 0;
padding: 0;
}
ul,
ol,
li {
list-style: none;
}
a,
a:hover,
a:active {
text-decoration: none;
}
img {
width: 100%;
height: 100%;
display: block;
}
.banner {
width: 600px;
height: 400px;
border: 5px solid #000;
position: relative;
margin: 50px auto;
overflow: hidden;
}
.banner>ul {
width: 500%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.banner>ul>li {
float: left;
width: 600px;
height: 400px;
}
.banner>ol {
height: 50px;
position: absolute;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
border-radius: 15px;
}
.banner>ol>li {
width: 20px;
height: 20px;
border-radius: 50%;
background: #fff;
margin: 0 15px;
cursor: pointer;
}
.banner>ol>li.active {
background: red;
}
.banner>div {
width: 100%;
height: 50px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: space-between;
align-items: center;
}
.banner>div>a {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
font-size: 40px;
color: #fff;
}
動态生成輪播圖頁面
目前我們自己定義一個數組 模拟一下
2, 根據數組動态生成頁面内容生成 ul>li ol>li
定義變量 存儲 ul>li字元串 ol>li字元串
循環周遊數組 每一個數組單元 對應一個 ul>li ol>li
第一個ol>li 有 class,active樣式
将 ul>li字元串 ol>li字元串寫入 ul ol 标簽對象
擷取 所有的 ul>li
克隆所有ul>li中的第一個li标簽
克隆所有ul>li中的最後一個li标簽
克隆的第一個ul>li标簽寫入到 ul标簽的最後
克隆的最後一個ul>li标簽寫入到 ul标簽的第一個
擷取 ul>li 寬度
重新設定ul标簽的寬度
(原始數組單元個數+2) * 一個li寬度 + 'px'
重新定位ul标簽
向左定位一個 li寬度
// 動态生成頁面函數
function setPage() {
// 定義變量儲存生成的字元串
let ulStr = '';
let olStr = '';
// 循環周遊數組
bannerArr.forEach(function (item, key) {
// ul标簽中的li标簽
ulStr += `<li><img src="./images/${item.name}"></li>`;
// ol标簽中的li标簽
// 第一個li有class,active
olStr += key === 0 ? `<li class="active" name="focus" num="${key}"></li>` :
`<li name="focus" num="${key}"></li>`;
})
// 循環結束将字元串寫入ul,ol标簽
oUl.innerHTML = ulStr;
oOl.innerHTML = olStr;
// 擷取所有的ul>li ol>li
// 給全局變量指派
oUlLis = oUl.querySelectorAll('li');
oOlLis = oOl.querySelectorAll('li');
// 克隆 ul>li 中 第一個和最後一個li
const cloneFirst = oUlLis[0].cloneNode(true);
const cloneLast = oUlLis[oUlLis.length - 1].cloneNode(true);
// 克隆的第一個寫入ul标簽最後
oUl.appendChild(cloneFirst);
// 克隆的最後一個寫入ul标簽起始
oUl.insertBefore(cloneLast, oUlLis[0]);
// 擷取li标簽的寬度
liWidth = oUlLis[0].offsetWidth;
// 重新設定ul标簽寬度
// (原始數組個數+2) * 一個li的寬度 拼接 px機關
oUl.style.width = (length + 2) * liWidth + 'px';
// 重新定位ul标簽
// 向左定位一個li标簽寬度
oUl.style.left = -liWidth + 'px';
}
自動輪播
通過 ul标簽 定位的改變 實作 顯示内容不同的效果
ul标簽 定位的改變 是 運動執行的效果
通過定義的運動函數實作
通過定時器 來 調用運動函數
實作 每間隔一段時間 ul做一次定位的改變
定時器的 時間間隔 必須要 大于 move() 運動函數的時間
// 自動輪播函數
function autoLoop() {
// 定義定時器
time = setInterval(function () {
// 變量累加1
index++;
console.log(index)
// 在運動之前 先切換 焦點按鈕 css樣式
setFocusStyle();
// 調用move運動函數,改變ul定位
// 每次定位的資料是 顯示li索引下标*一個li寬度
move(oUl, {left: -index * liWidth}, loopEnd);
}, 4000)
}
焦點樣式函數
清除所有ol>li标簽焦點樣式
給 顯示的 ul>li 對應的 ol>li 标簽添加焦點樣式
ul>li索引下标數值 - 1 是 ol>li索引下标數值
也就是 index存儲數值 -1 是 ol>li标簽的索引下标
特殊情況
當 index 存儲的索引下标是 最後一個li的索引下标時
index-1 沒有對應的 ol>li标簽
此時 應該是 所有 ol>li 中 索引下标是0的 第一個ol>li 标簽 添加樣式
當 index 存儲的索引下标是 第一個li的索引下标時
index-1 沒有對應的 ol>li标簽
此時 應該是 所有 ol>li 中 索引下标是 最後一個 ol>li标簽 添加樣式
最後一個ul>li 給 第一個 ol>li 添加樣式
第一個ul>li 給 最後一個 ol>li 添加樣式
// 焦點樣式切換
function setFocusStyle() {
// 給所有的 ol>li 清除 class,active
// 給索引下标和顯示li對應的ol>li 添加 class,active
// 索引下标 是 顯示li索引下标-1
oOlLis.forEach(function (item, key) {
// 清除 ol>li 标簽樣式
item.classList.remove('active');
// 如果 索引下标 等于 index-1 添加 樣式
if (key === index - 1) {
item.classList.add('active');
}
})
console.log(index)
// 特殊情況 如果是最後一個ul>li 給 第一個 ol>li 添加樣式
if (index === length + 1) {
oOlLis[0].classList.add('active');
// 特殊情況 如果是第一個ul>li 給 最後一個 ol>li 添加樣式
} else if (index === 0) {
oOlLis[oOlLis.length - 1].classList.add('active');
}
}
輪播圖運動結束函數
輪播圖切換結束時 觸發執行函數
判斷 index的數值
如果 index 存儲的是 最後一個li的索引下标
也就是 切換到 最後一個li , 也就是克隆的原始輪播圖的第一張
給 index 指派 1 同時立即切換輪播圖 到 所有ul>li的第二個标簽
如果 index 存儲的是 第一個li的索引下标
也就是 切換到 第一個li , 也就是克隆的原始輪播圖的最後一張
給 index 指派 倒數第二個ul>li的索引下标 同時立即切換輪播圖 到 所有 ul>li 的 倒數第二個标簽
// 輪播結束的回調函數
function loopEnd() {
// 判斷index的數值
// 如果 index的數值是 所有li的最後一個
// index 指派 1
// 運動結束 從最後一個li 瞬間定位到 第二個li
if (index === length + 1) {
index = 1;
oUl.style.left = -index * liWidth + 'px';
// index 是 0 瞬間定位到 倒數第二個li
} else if (index === 0) {
index = length;
oUl.style.left = -index * liWidth + 'px';
}
// 當所有的運動結束 ,已經可以正常切換下一張了
// 給 bool變量指派 true 可以再次觸發move()運動函數
bool = true;
}
滑鼠移入移出
滑鼠移入:
停止輪播圖運動
清除 自動輪播 定時器
// 滑鼠移入移出
function setMouse() {
// 滑鼠移入 父級div标簽 清除定時器
// 滑鼠移入 父級div标簽 清除一次定時器就可以了
oBanner.addEventListener('mouseenter', function () {
clearInterval(time);
console.log(111);
})
// 滑鼠移出 再次調用 自動輪播函數
oBanner.addEventListener('mouseleave', function () {
autoLoop();
})
}
點選效果
左右按鈕 焦點标簽 都是動态生成的
使用事件委托文法 添加點選效果
1, 點選 左按鈕
顯示 上一個 ul>li 标簽内容
變量index--
設定焦點标簽css樣式
根據 新的 index 定位 ul标簽
動态完成切換效果
2, 點選 右按鈕
顯示 下一個 ul>li 标簽内容
變量index++
設定焦點标簽css樣式
根據 新的 index 定位 ul标簽
動态完成切換效果
3, 點選 焦點按鈕
顯示 點選的 ol>li 對應的 ul>li
ol>li标簽索引下标+1 是 對應 ul>li索引下标
變量index 指派 ol>li索引下标+1
設定焦點标簽css樣式
根據 新的 index 定位 ul标簽
動态完成切換效果
// 點選效果
function setClick() {
// 給父級div添加點選事件
oBanner.addEventListener('click', function (e) {
// 通過 e.target 判斷點選标簽
// 如果 标簽名稱是 left 點選的是 左按鈕
if (e.target.getAttribute('name') === 'left') {
// 判斷bool變量
if (!bool) {
// 如果 bool 不是原始值true 執行return
// 終止之後程式的執行
return;
}
// 變量index--
index--;
// 調用焦點按鈕樣式切換函數
setFocusStyle();
// move函數要執行了,表示要開始切換下一張了,關閉開關,等運動完了再打開開關
bool = false
// 根據新的index數值 調用move()運動函數改變ul标簽的定位
move(oUl, {
left: -index * liWidth
}, loopEnd);
// 如果 标簽名稱是 right 點選的是 右按鈕
} else if (e.target.getAttribute('name') === 'right') {
// 判斷bool變量
if (!bool) {
// 如果 bool 是false,開關是關閉的,就不執行後面的代碼了
return;
}
// 變量index++
index++;
// 調用焦點按鈕樣式切換函數
setFocusStyle();
// move函數要執行了,表示要開始切換下一張了,關閉開關,等運動完了再打開開關
bool = false
// 根據新的index數值 調用move()運動函數改變ul标簽的定位
move(oUl, {left: -index * liWidth}, loopEnd);
// 如果 标簽名稱是 focus 點選的是 焦點按鈕
} else if (e.target.getAttribute('name') === 'focus') {
// 判斷bool變量
if (!bool) {
// 如果 bool 是false,開關是關閉的,就不執行後面的代碼了
return;
}
// 變量index 指派 點選ol>li标簽 索引下标+1
index = e.target.getAttribute('num') - 0 + 1;
// 調用焦點按鈕樣式切換函數
setFocusStyle();
// move函數要執行了,表示要開始切換下一張了,關閉開關,等運動完了再打開開關
bool = false
// 根據新的index數值 調用move()運動函數改變ul标簽的定位
move(oUl, {
left: -index * liWidth
}, loopEnd);
}
})
}
浏覽器背景運作
浏覽器最小化 或者 顯示運作其他程式
浏覽器不再是主要運作的程式 作業系統會切換到背景運作
再次 顯示浏覽器時 輪播圖執行會出現混亂
當浏覽器背景運作時 停止輪播圖的自動輪播
浏覽器顯示時 再次觸發輪播圖的運作
給 document 添加 visibilitychange 浏覽器顯示狀态 監聽事件
浏覽器顯示狀态改變時會觸發函數程式
document.visibilityState 浏覽器顯示狀态描述
hidden 隐藏 也就是 背景運作
清除 定時器 終止 輪播圖的自動執行
visible 顯示 也就是 正常運作浏覽器
再次調用 自動輪播函數
// 浏覽器背景運作效果
function setHide() {
document.addEventListener('visibilitychange', function () {
// 離開目前頁
if (document.visibilityState === 'hidden') {
// 清除定時器,終止輪播圖自動運作
clearInterval(time);
} else if (document.visibilityState === 'visible') {
// 再次調用自動輪播函數
autoLoop();
}
})
}
防止點選過快
本質是防止 上一個定時器沒有執行結束 就觸發下一個定時
也就是 防止同時有多個定時器觸發執行
設定一個變量 存儲原始值
判斷變量 如果存儲是原始值 變量指派其他數值 執行之後的程式
判斷變量 如果存儲不是原始值 執行return 終止之後的程式
輪播圖重點1:
定時器的嵌套
通過定時器A 每間隔一段時間 調用觸發定時器B
定時器A 的間隔時間 一定要 大于 定時器B的執行時間
如果 定時器A的時間間隔短 就會 同時 有 多個定時器B 在同時執行
就是同時操作 同一個對象 造成顯示混亂效果
輪播圖重點2:
通過 ul标簽定位的改變 執行效果是顯示不同的li标簽也就是顯示不同的圖檔
通過 顯示li标簽的索引下标 * li标簽的寬度 控制 ul标簽的定位
定義變量 index 存儲 索引下标數值
也就是 通過 控制 index 存儲的資料數值 控制 ul标簽的定位 控制顯示内容
改變顯示内容 一定要 先改變 index存儲的數值
再 通過 index存儲的數值 改變ul标簽的定位
全部code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
ul,
ol,
li {
list-style: none;
}
a,
a:hover,
a:active {
text-decoration: none;
}
img {
width: 100%;
height: 100%;
display: block;
}
.banner {
width: 600px;
height: 400px;
border: 5px solid #000;
position: relative;
margin: 50px auto;
/* overflow: hidden; */
}
.banner>ul {
width: 500%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
.banner>ul>li {
float: left;
width: 600px;
height: 400px;
}
.banner>ol {
height: 50px;
position: absolute;
bottom: 50px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
border-radius: 15px;
}
.banner>ol>li {
width: 20px;
height: 20px;
border-radius: 50%;
background: #fff;
margin: 0 15px;
cursor: pointer;
}
.banner>ol>li.active {
background: red;
}
.banner>div {
width: 100%;
height: 50px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
display: flex;
justify-content: space-between;
align-items: center;
}
.banner>div>a {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
font-size: 40px;
color: #fff;
}
</style>
</head>
<body>
<!-- 輪播圖div -->
<div class="banner">
<!-- 輪播圖内容 -->
<ul></ul>
<!-- 焦點按鈕 -->
<ol></ol>
<!-- 左右切換按鈕 -->
<div>
<a href="JavaScript:;" name="left"><</a>
<a href="JavaScript:;" name="right">></a>
</div>
</div>
<!-- 導入外部檔案加載move運動函數 -->
<script src="move.js"></script>
<script>
// 1, 輪播圖html,css
// 2, 動态生成輪播圖頁面内容
// 模拟生成一個數組
var bannerArr = [{
id: 1,
width: 500,
height: 333,
size: 29.7,
name: '1.jpg'
},
{
id: 2,
width: 500,
height: 333,
size: 19.3,
name: '2.jpg'
},
{
id: 3,
width: 500,
height: 333,
size: 17.1,
name: '3.jpg'
},
{
id: 4,
width: 500,
height: 333,
size: 20.3,
name: '4.jpg'
},
{
id: 5,
width: 600,
height: 400,
size: 320,
name: '5.jpg'
},
];
// 3, 擷取标簽對象
const oBanner = document.querySelector('.banner');
const oUl = oBanner.querySelector('ul');
const oOl = oBanner.querySelector('ol');
// 定義全局變量
let oUlLis;
let oOlLis;
let length = bannerArr.length;
let liWidth;
// 定義變量儲存顯示li标簽對應的索引下标
// 初始值是 1
let index = 1;
// 存儲定時器
let time;
// 定義一個變量 存儲原始值 防止 點選操作執行過快
// 開啟開關:運動結束,一張切換完畢,可以打開開關了,切換下一張
// 關閉開關:點選左右按鈕或者焦點後,開關關閉,等運動結束再開
// 初始值:如果是false,那一次都點不了,
let bool = true;
// 調用函數,動态渲染生成頁面
setPage();
// 調用自動輪播函數
autoLoop();
// 調用滑鼠移入移出函數
setMouse();
// 調用點選效果函數
setClick();
// 浏覽器背景運動函數
setHide();
// 動态生成頁面函數
function setPage() {
// 定義變量儲存生成的字元串
let ulStr = '';
let olStr = '';
// 循環周遊數組
bannerArr.forEach(function (item, key) {
// ul标簽中的li标簽
ulStr += `<li><img src="./images/${item.name}"></li>`;
// ol标簽中的li标簽
// 第一個li有class,active
olStr += key === 0 ? `<li class="active" name="focus" num="${key}"></li>` :
`<li name="focus" num="${key}"></li>`;
})
// 循環結束将字元串寫入ul,ol标簽
oUl.innerHTML = ulStr;
oOl.innerHTML = olStr;
// 擷取所有的ul>li ol>li
// 給全局變量指派
oUlLis = oUl.querySelectorAll('li');
oOlLis = oOl.querySelectorAll('li');
// 克隆 ul>li 中 第一個和最後一個li
const cloneFirst = oUlLis[0].cloneNode(true);
const cloneLast = oUlLis[oUlLis.length - 1].cloneNode(true);
// 克隆的第一個寫入ul标簽最後
oUl.appendChild(cloneFirst);
// 克隆的最後一個寫入ul标簽起始
oUl.insertBefore(cloneLast, oUlLis[0]);
// 擷取li标簽的寬度
liWidth = oUlLis[0].offsetWidth;
// 重新設定ul标簽寬度
// (原始數組個數+2) * 一個li的寬度 拼接 px機關
oUl.style.width = (length + 2) * liWidth + 'px';
// 重新定位ul标簽
// 向左定位一個li标簽寬度
oUl.style.left = -liWidth + 'px';
}
// 自動輪播函數
function autoLoop() {
// 定義定時器
time = setInterval(function () {
// 變量累加1
index++;
console.log(index)
// 在運動之前 先切換 焦點按鈕 css樣式
setFocusStyle();
// 調用move運動函數,改變ul定位
// 每次定位的資料是 顯示li索引下标*一個li寬度
move(oUl, {
left: -index * liWidth
}, loopEnd);
}, 4000)
}
// 輪播結束的回調函數
function loopEnd() {
// 判斷index的數值
// 如果 index的數值是 所有li的最後一個
// index 指派 1
// 運動結束 從最後一個li 瞬間定位到 第二個li
if (index === length + 1) {
index = 1;
oUl.style.left = -index * liWidth + 'px';
// index 是 0 瞬間定位到 倒數第二個li
} else if (index === 0) {
index = length;
oUl.style.left = -index * liWidth + 'px';
}
// 當所有的運動結束 ,已經可以正常切換下一張了
// 給 bool變量指派 true 可以再次觸發move()運動函數
bool = true;
}
// 焦點樣式切換
function setFocusStyle() {
// 給所有的 ol>li 清除 class,active
// 給索引下标和顯示li對應的ol>li 添加 class,active
// 索引下标 是 顯示li索引下标-1
oOlLis.forEach(function (item, key) {
// 清除 ol>li 标簽樣式
item.classList.remove('active');
// 如果 索引下标 等于 index-1 添加 樣式
if (key === index - 1) {
item.classList.add('active');
}
})
console.log(index)
// 特殊情況 如果是最後一個ul>li 給 第一個 ol>li 添加樣式
if (index === length + 1) {
oOlLis[0].classList.add('active');
// 特殊情況 如果是第一個ul>li 給 最後一個 ol>li 添加樣式
} else if (index === 0) {
oOlLis[oOlLis.length - 1].classList.add('active');
}
}
// 滑鼠移入移出
function setMouse() {
// 滑鼠移入 父級div标簽 清除定時器
// 滑鼠移入 父級div标簽 清除一次定時器就可以了
oBanner.addEventListener('mouseenter', function () {
clearInterval(time);
console.log(111);
})
// 滑鼠移出 再次調用 自動輪播函數
oBanner.addEventListener('mouseleave', function () {
autoLoop();
})
}
// 點選效果
function setClick() {
// 給父級div添加點選事件
oBanner.addEventListener('click', function (e) {
// 通過 e.target 判斷點選标簽
// 如果 标簽名稱是 left 點選的是 左按鈕
if (e.target.getAttribute('name') === 'left') {
// 判斷bool變量
if (!bool) {
// 如果 bool 不是原始值true 執行return
// 終止之後程式的執行
return;
}
// 變量index--
index--;
// 調用焦點按鈕樣式切換函數
setFocusStyle();
// move函數要執行了,表示要開始切換下一張了,關閉開關,等運動完了再打開開關
bool = false
// 根據新的index數值 調用move()運動函數改變ul标簽的定位
move(oUl, {
left: -index * liWidth
}, loopEnd);
// 如果 标簽名稱是 right 點選的是 右按鈕
} else if (e.target.getAttribute('name') === 'right') {
// 判斷bool變量
if (!bool) {
// 如果 bool 是false,開關是關閉的,就不執行後面的代碼了
return;
}
// 變量index++
index++;
// 調用焦點按鈕樣式切換函數
setFocusStyle();
// move函數要執行了,表示要開始切換下一張了,關閉開關,等運動完了再打開開關
bool = false
// 根據新的index數值 調用move()運動函數改變ul标簽的定位
move(oUl, {left: -index * liWidth}, loopEnd);
// 如果 标簽名稱是 focus 點選的是 焦點按鈕
} else if (e.target.getAttribute('name') === 'focus') {
// 判斷bool變量
if (!bool) {
// 如果 bool 是false,開關是關閉的,就不執行後面的代碼了
return;
}
// 變量index 指派 點選ol>li标簽 索引下标+1
index = e.target.getAttribute('num') - 0 + 1;
// 調用焦點按鈕樣式切換函數
setFocusStyle();
// move函數要執行了,表示要開始切換下一張了,關閉開關,等運動完了再打開開關
bool = false
// 根據新的index數值 調用move()運動函數改變ul标簽的定位
move(oUl, {
left: -index * liWidth
}, loopEnd);
}
})
}
// 浏覽器背景運作效果
function setHide() {
document.addEventListener('visibilitychange', function () {
// 離開目前頁
if (document.visibilityState === 'hidden') {
// 清除定時器,終止輪播圖自動運作
clearInterval(time);
} else if (document.visibilityState === 'visible') {
// 再次調用自動輪播函數
autoLoop();
}
})
}
</script>
</body>
</html>