效果演示
实现了一个全屏滑动轮播图的效果,包括一个背景图片的模糊效果和多张图片的轮播。用户可以通过点击左右箭头或者点击下方的小圆点来切换图片。同时,这段代码还实现了响应式布局,在屏幕宽度小于1620px时,左右箭头的位置会发生变化。
Code
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>仿网易云音乐轮播图</title>
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="./27-仿网易云音乐轮播图.css">
</head>
<body>
<div class="swipe" id="swipe">
<div class="bg" id="swipe_bg"></div>
<section>
<div class="img-box" id="swipe_img_box">
<a href="#" class="link" id="swipe_link">
<img src="./images/1.jpg" alt="" class="img" id="swipe_img">
</a>
</div>
<div class="select" id="swipe_select">
</div>
<div class="btn left" id="swipe_btn_left">
<i class="fa fa-angle-left" aria-hidden="true"></i>
</div>
<div class="btn right" id="swipe_btn_right">
<i class="fa fa-angle-right" aria-hidden="true"></i>
</div>
</section>
</div>
</body>
<script src="./27-仿网易云音乐轮播图.js"></script>
</html>
CSS
* {
margin: 0;
padding: 0;
}
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #333;
}
.swipe {
position: relative;
width: 100%;
overflow: hidden;
}
.swipe .bg {
position: absolute;
width: 500%;
height: 100%;
z-index: 1;
background-image: url("../images/cloud_music/1.jpg");
background-size: 6000px;
background-position: center center;
filter: blur(140px);
}
.swipe section {
position: relative;
z-index: 2;
width: 100%;
max-width: 1500px;
height: 600px;
margin: 0 auto;
}
.swipe .img-box {
width: 100%;
height: 100%;
}
.swipe .img-box .img {
width: 100%;
height: 100%;
object-fit: cover;
}
.swipe .select {
position: absolute;
width: 100%;
height: 30px;
line-height: 30px;
bottom: 20px;
text-align: center;
}
.swipe .select .item {
display: inline-block;
width: 10px;
height: 10px;
background-color: #fff;
border-radius: 50%;
margin: 0 10px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
}
.swipe .select .item:hover {
background-color: #ff4400;
}
.swipe .select .item.checked {
background-color: #ff4400;
}
.swipe .btn {
width: 40px;
height: 100px;
color: #fff;
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 50px;
background-color: rgba(0, 0, 0, 0.05);
display: flex;
justify-content: center;
align-items: center;
z-index: 3;
cursor: pointer;
transition: 0.3s;
}
.swipe .btn.left {
left: -60px;
}
.swipe .btn.right {
right: -60px;
}
.swipe .btn:hover {
background-color: rgba(0, 0, 0, 0.2);
}
@media screen and (max-width: 1620px) {
.swipe .btn.left {
left: 20px;
}
.swipe .btn.right {
right: 20px;
}
}
JavaScript
let current_index = -1;
let swipe_timer = null;
let links = [
{'image': './images/1.jpg', 'target': '#1'},
{'image': './images/2.jpg', 'target': '#2'},
{'image': './images/3.jpg', 'target': '#3'},
{'image': './images/4.jpg', 'target': '#4'},
{'image': './images/5.jpg', 'target': '#5'},
{'image': './images/6.jpg', 'target': '#6'}
];
let swipe = document.getElementById('swipe');
let swipe_bg = document.getElementById('swipe_bg');
let swipe_img_box = document.getElementById('swipe_img_box');
let swipe_link = document.getElementById('swipe_link');
let swipe_img = document.getElementById('swipe_img');
let swipe_select = document.getElementById('swipe_select');
let swipe_btn_left = document.getElementById('swipe_btn_left');
let swipe_btn_right = document.getElementById('swipe_btn_right');
let select = (index) => {
stop();
index = Number(index);
if (index >= links.length) {
return;
}
if (current_index == index) {
return;
}
if (current_index > -1) {
swipe_select.children[current_index].classList.remove('checked');
}
current_index = index;
let current_link = links[current_index];
swipe_bg.style.backgroundImage = 'url(' + current_link.image + ')';
swipe_img.setAttribute('src', current_link.image);
swipe_link.setAttribute('href', current_link.target);
swipe_select.children[current_index].classList.add('checked');
};
let autoSelect = (index) => {
index = Number(index);
if (index >= links.length) {
return;
}
if (current_index == index) {
return;
}
swipe_select.children[current_index].classList.remove('checked');
current_index = index;
let current_link = links[current_index];
swipe_img.style.transition = 'opacity 0.5s ease-in 0s';
swipe_img.style.opacity = 0.2;
setTimeout(() => {
swipe_bg.style.backgroundImage = 'url(' + current_link.image + ')';
swipe_img.setAttribute('src', current_link.image);
swipe_link.setAttribute('href', current_link.target);
swipe_img.style.transition = 'opacity 0.7s ease-out 0s';
swipe_img.style.opacity = 1;
if (!document.querySelector('.swipe .checked')) {
swipe_select.children[current_index].style.transition = 'background-color 0.5s';
swipe_select.children[current_index].classList.add('checked');
}
}, 500);
};
let play = () => {
swipe_timer = setInterval(() => {
let index = current_index + 1;
if (index >= links.length) {
index = 0;
}
autoSelect(index);
}, 3000);
};
let stop = () => {
if (swipe_timer) {
clearInterval(swipe_timer);
swipe_timer = null;
}
};
let init = () => {
for (let i = 0; i < links.length; i++) {
let item = document.createElement('a');
item.setAttribute('class', 'item');
item.setAttribute('href', '#');
item.setAttribute('data-index', i);
swipe_select.appendChild(item);
}
select(0);
bind();
play();
};
let bind = () => {
swipe_btn_left.addEventListener('click', () => {
let index = current_index - 1;
if (index < 0) {
index = links.length - 1;
}
select(index);
});
swipe_btn_right.addEventListener('click', () => {
let index = current_index + 1;
if (index >= links.length) {
index = 0;
}
select(index);
});
for (const key in swipe_select.children) {
if (swipe_select.children.hasOwnProperty(key)) {
const element = swipe_select.children[key];
element.addEventListener('click', (e) => {
e.preventDefault();
select(e.target.dataset.index);
});
}
}
swipe.addEventListener('mouseover', (e) => {
if (e.relatedTarget && swipe.compareDocumentPosition(e.relatedTarget) == 10) {
stop();
}
});
swipe.addEventListener('mouseout', (e) => {
if (e.relatedTarget && swipe.compareDocumentPosition(e.relatedTarget) == 10) {
play();
}
});
swipe.addEventListener('mousemove', (e) => {
stop();
});
};
window.addEventListener('load', () => {
init();
})
实现思路拆分
* {
margin: 0;
padding: 0;
}
这段代码是设置所有元素的外边距和内边距为0,这是为了避免不同浏览器的默认样式对页面造成影响。
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #333;
}
这段代码设置了body元素的高度为100vh,即占据整个视口的高度。同时,使用flex布局使得body元素的子元素在水平和垂直方向上都居中对齐。背景颜色为#333。
.swipe {
position: relative;
width: 100%;
overflow: hidden;
}
这段代码定义了一个名为swipe的类,设置其为相对定位,宽度为100%,并且隐藏超出部分。
.swipe .bg {
position: absolute;
width: 500%;
height: 100%;
z-index: 1;
background-image: url("../images/cloud_music/1.jpg");
background-size: 6000px;
background-position: center center;
filter: blur(140px);
}
这段代码定义了一个名为bg的类,设置其为绝对定位,宽度为500%,高度为100%,并且设置z-index为1,使其在其他元素之下。同时,设置背景图片、背景大小、背景位置和模糊效果。
.swipe section {
position: relative;
z-index: 2;
width: 100%;
max-width: 1500px;
height: 600px;
margin: 0 auto;
}
这段代码定义了一个名为section的类,设置其为相对定位,z-index为2,宽度为100%,最大宽度为1500px,高度为600px,并且水平居中对齐。
.swipe .img-box {
width: 100%;
height: 100%;
}
这段代码定义了一个名为img-box的类,设置其宽度和高度均为100%。
.swipe .img-box .img {
width: 100%;
height: 100%;
object-fit: cover;
}
这段代码定义了一个名为img的类,设置其宽度和高度均为100%,并且使用object-fit属性使得图片按比例缩放并且填充整个容器。
.swipe .select {
position: absolute;
width: 100%;
height: 30px;
line-height: 30px;
bottom: 20px;
text-align: center;
}
这段代码定义了一个名为select的类,设置其为绝对定位,宽度为100%,高度为30px,行高为30px,底部距离为20px,并且文本居中对齐。
.swipe .select .item {
display: inline-block;
width: 10px;
height: 10px;
background-color: #fff;
border-radius: 50%;
margin: 0 10px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
}
这段代码定义了一个名为item的类,设置其为内联块元素,宽度和高度均为10px,背景颜色为白色,边框半径为50%,左右间距为10px,阴影效果为0 2px 5px rgba(0, 0, 0, 0.4)。
.swipe .select .item:hover {
background-color: #ff4400;
}
这段代码设置鼠标悬停在item元素上时的背景颜色为#ff4400。
.swipe .select .item.checked {
background-color: #ff4400;
}
这段代码设置选中的item元素的背景颜色为#ff4400。
.swipe .btn {
width: 40px;
height: 100px;
color: #fff;
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 50px;
background-color: rgba(0, 0, 0, 0.05);
display: flex;
justify-content: center;
align-items: center;
z-index: 3;
cursor: pointer;
transition: 0.3s;
}
这段代码定义了一个名为btn的类,设置其宽度为40px,高度为100px,颜色为白色,绝对定位,顶部距离为50%,使用transform属性使其在垂直方向上居中对齐,字体大小为50px,背景颜色为rgba(0, 0, 0, 0.05),使用flex布局使得内容水平和垂直方向上都居中对齐,z-index为3,鼠标样式为手型,过渡效果为0.3秒。
.swipe .btn.left {
left: -60px;
}
.swipe .btn.right {
right: -60px;
}
这段代码设置左箭头的位置为左侧-60px,右箭头的位置为右侧-60px。
.swipe .btn:hover {
background-color: rgba(0, 0, 0, 0.2);
}
这段代码设置鼠标悬停在btn元素上时的背景颜色为rgba(0, 0, 0, 0.2)。
@media screen and (max-width: 1620px) {
.swipe .btn.left {
left: 20px;
}
.swipe .btn.right {
right: 20px;
}
}
这段代码使用@media查询,当屏幕宽度小于等于1620px时,将左箭头的位置设置为左侧20px,右箭头的位置设置为右侧20px。这是为了适应不同屏幕尺寸的设备。
let current_index = -1;
let swipe_timer = null;
let links = [
{ 'image': './images/1.jpg', 'target': '#1' },
{ 'image': './images/2.jpg', 'target': '#2' },
{ 'image': './images/3.jpg', 'target': '#3' },
{ 'image': './images/4.jpg', 'target': '#4' },
{ 'image': './images/5.jpg', 'target': '#5' },
{ 'image': './images/6.jpg', 'target': '#6' }
];
这段代码定义了三个变量,current_index表示当前选中的图片的索引,swipe_timer表示轮播定时器,links是一个数组,包含了每张图片的路径和链接目标。
let swipe = document.getElementById('swipe');
let swipe_bg = document.getElementById('swipe_bg');
let swipe_img_box = document.getElementById('swipe_img_box');
let swipe_link = document.getElementById('swipe_link');
let swipe_img = document.getElementById('swipe_img');
let swipe_select = document.getElementById('swipe_select');
let swipe_btn_left = document.getElementById('swipe_btn_left');
let swipe_btn_right = document.getElementById('swipe_btn_right');
这段代码获取了页面中的各个元素,包括轮播图容器、背景图片、图片容器、链接、图片、小圆点、左箭头和右箭头。
let select = (index) => {
stop();
index = Number(index);
if (index >= links.length) {
return;
}
if (current_index == index) {
return;
}
if (current_index > -1) {
swipe_select.children[current_index].classList.remove('checked');
}
current_index = index;
let current_link = links[current_index];
swipe_bg.style.backgroundImage = 'url(' + current_link.image + ')';
swipe_img.setAttribute('src', current_link.image);
swipe_link.setAttribute('href', current_link.target);
swipe_select.children[current_index].classList.add('checked');
};
这段代码定义了一个名为select的函数,用于切换图片。首先调用stop函数停止轮播,然后将传入的参数转换为数字类型,并且判断是否超出数组范围或者是否已经选中了该图片。如果当前已经选中了一张图片,则将其小圆点的样式去除。然后更新current_index的值,获取当前图片的路径和链接目标,并且更新背景图片、图片和链接的属性。最后将当前小圆点的样式添加上。
let autoSelect = (index) => {
index = Number(index);
if (index >= links.length) {
return;
}
if (current_index == index) {
return;
}
swipe_select.children[current_index].classList.remove('checked');
current_index = index;
let current_link = links[current_index];
swipe_img.style.transition = 'opacity 0.5s ease-in 0s';
swipe_img.style.opacity = 0.2;
setTimeout(() => {
swipe_bg.style.backgroundImage = 'url(' + current_link.image + ')';
swipe_img.setAttribute('src', current_link.image);
swipe_link.setAttribute('href', current_link.target);
swipe_img.style.transition = 'opacity 0.7s ease-out 0s';
swipe_img.style.opacity = 1;
if (!document.querySelector('.swipe .checked')) {
swipe_select.children[current_index].style.transition = 'background-color 0.5s';
swipe_select.children[current_index].classList.add('checked');
}
}, 500);
};
这段代码定义了一个名为autoSelect的函数,用于自动切换图片。首先将传入的参数转换为数字类型,并且判断是否超出数组范围或者是否已经选中了该图片。然后将当前小圆点的样式去除,更新current_index的值,获取当前图片的路径和链接目标。接着设置图片的过渡效果和透明度,等待0.5秒后更新背景图片、图片和链接的属性,并且设置图片的过渡效果和透明度。最后判断是否存在选中的小圆点,如果不存在则添加当前小圆点的样式。
let play = () => {
swipe_timer = setInterval(() => {
let index = current_index + 1;
if (index >= links.length) {
index = 0;
}
autoSelect(index);
}, 3000);
};
这段代码定义了一个名为play的函数,用于启动轮播。使用setInterval函数每隔3秒调用一次autoSelect函数,传入的参数为当前选中图片的索引加1,如果超出数组范围则从头开始。
let stop = () => {
if (swipe_timer) {
clearInterval(swipe_timer);
swipe_timer = null;
}
};
这段代码定义了一个名为stop的函数,用于停止轮播。如果swipe_timer存在,则清除定时器并且将其赋值为null。
let init = () => {
for (let i = 0; i < links.length; i++) {
let item = document.createElement('a');
item.setAttribute('class', 'item');
item.setAttribute('href', '#');
item.setAttribute('data-index', i);
swipe_select.appendChild(item);
}
select(0);
bind();
play();
};
这段代码定义了一个名为init的函数,用于初始化轮播图。首先使用for循环创建小圆点元素,并且设置其class、href和data-index属性。然后调用select函数选中第一张图片,调用bind函数绑定事件,最后调用play函数启动轮播。
let bind = () => {
swipe_btn_left.addEventListener('click', () => {
let index = current_index - 1;
if (index < 0) {
index = links.length - 1;
}
select(index);
});
swipe_btn_right.addEventListener('click', () => {
let index = current_index + 1;
if (index >= links.length) {
index = 0;
}
select(index);
});
for (const key in swipe_select.children) {
if (swipe_select.children.hasOwnProperty(key)) {
const element = swipe_select.children[key];
element.addEventListener('click', (e) => {
e.preventDefault();
select(e.target.dataset.index);
});
}
}
swipe.addEventListener('mouseover', (e) => {
if (e.relatedTarget && swipe.compareDocumentPosition(e.relatedTarget) == 10) {
stop();
}
});
swipe.addEventListener('mouseout', (e) => {
if (e.relatedTarget && swipe.compareDocumentPosition(e.relatedTarget) == 10) {
play();
}
});
swipe.addEventListener('mousemove', (e) => {
stop();
});
};
这段代码定义了一个名为bind的函数,用于绑定事件。首先为左箭头和右箭头添加点击事件,分别调用select函数切换图片。然后使用for循环为每个小圆点添加点击事件,调用select函数切换图片。接着为轮播图容器添加鼠标移入事件,调用stop函数停止轮播。为轮播图容器添加鼠标移出事件,调用play函数启动轮播。最后为轮播图容器添加鼠标移动事件,调用stop函数停止轮播。
window.addEventListener('load', () => {
init();
})
这段代码为页面加载完成后调用init函数,初始化轮播图。