<!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>Slider</title>
</head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.img-container {
margin: 20px auto;
display: flex;
align-items: center;
overflow: hidden;
position: relative;
justify-content: center;
}
img {
position: absolute;
transition: all 0.3s ease-in-out;
height: 100%;
}
</style>
<body>
<div class="img-container">
<img
class="previous"
src="./img/中岛美雪.png"
alt=""
srcset=""
h="362"
w="578"
/>
<img
h="1200"
w="1920"
class="current"
src="./img/华盛顿北瀑布国家公园.jpg"
alt=""
srcset=""
/>
<img h="640" w="640" class="next" src="./img/星空.jpg" alt="" srcset="" />
</div>
<button class="prev">Previous</button>
<button class="nex">Next</button>
</body>
<script>
/*
思路:这里设置三个图片,分别是上一张,当前,下一张(previous,current,next),它们均为绝对定位,父容器为相对定位。
current是当前实际显示的图片,默认left和right都为0,previous默认right为100%,next的left为100%。我们通过
设置current的left和right来实现图片的切换,当我们选择上一张时,current的left渐变为100%,而previous的left
渐变为0。next的right直接变为100%。当我们选择下一张是只需反过来即可,此时需要注意当动画结束后需要对于previous
,current,next的left和right进行重置(元素的类名先变而后选择器重置),以便下一次动画。
*/
const container = document.querySelector('.img-container');
let previous = document.querySelector('.previous');
let next = document.querySelector('.next');
let current = document.querySelector('.current');
let prevBtn = document.querySelector('.prev');
let nextBtn = document.querySelector('.nex');
/*如果current高度大于600则使用600作为容器高度否则则采用图片的高度
这里为了保证图片不会失真,我们将实际高度比上图片的高度获取实际缩放比,将其与图片原始宽度相乘得到最佳实际宽度
*/
let height = getHeight(current) > 600 ? 600 : getHeight(current);
let width = (height / getHeight(current)) * getWidth(current);
let autoTimer;
//默认将容器的宽度和高度设置为current的宽度和高度
container.style.height = `${height}px`;
container.style.width = `${width}px`;
//设置默认值
previous.style.right = `100%`;
next.style.left = `100%`;
//创建自动轮播的效果,默认时间时三秒一换,这里使用一个函数将其包含以便调用
const auto = function () {
//设置实际的轮播定时器
autoTimer = setInterval(() => {
current.style.right = `0%`;
const timer = setInterval(() => {
if (getLeftValue(next) <= 0) {
clearInterval(timer);
let height = getHeight(next) > 600 ? 600 : getHeight(next);
let width = (height / getHeight(next)) * getWidth(next);
container.style.height = `${height}px`;
container.style.width = `${width}px`;
previous.classList.remove('previous');
previous.classList.add('next');
current.classList.remove('current');
current.classList.add('previous');
next.classList.remove('next');
next.classList.add('current');
previous = document.querySelector('.previous');
next = document.querySelector('.next');
current = document.querySelector('.current');
previous.removeAttribute('style');
next.removeAttribute('style');
previous.style.right = `100%`;
next.style.left = `100%`;
return;
}
next.style.left = `${getLeftValue(next) - 10}%`;
current.style.right = `${getRightValue(current) + 10}%`;
}, 10);
}, 3000);
};
//页面加载后默认直接调用自动轮播函数
auto();
prevBtn.addEventListener('click', () => {
//点击上一张和下一张时清除自动轮播的定时器
clearInterval(autoTimer);
//我们必须先设置一个默认值否则会导致显示的异常,因为默认它是没有设置left和right的
current.style.left = `0%`;
const timer = setInterval(() => {
//当current的left等于0时停止动画,这里的动画设置的默认时长为10*10ms
if (getLeftValue(current) === 100) {
clearInterval(timer);
//将容器设置为上一张的宽度和高度,因为这里是上一张,因此此时上一张即为当前实际显示的图片
let height = getHeight(previous) > 600 ? 600 : getHeight(previous);
let width = (height / getHeight(previous)) * getWidth(previous);
container.style.height = `${height}px`;
container.style.width = `${width}px`;
//重置类名
previous.classList.remove('previous');
previous.classList.add('current');
current.classList.remove('current');
current.classList.add('next');
next.classList.remove('next');
next.classList.add('previous');
//重置选择器
previous = document.querySelector('.previous');
next = document.querySelector('.next');
current = document.querySelector('.current');
//去除冗余的样式
previous.removeAttribute('style');
next.removeAttribute('style');
previous.style.right = `100%`;
next.style.left = `100%`;
auto();
return;
}
//动画效果
previous.style.right = `${getRightValue(previous) - 10}%`;
current.style.left = `${getLeftValue(current) + 10}%`;
}, 10);
});
nextBtn.addEventListener('click', () => {
clearInterval(autoTimer);
current.style.right = `0%`;
const timer = setInterval(() => {
if (getLeftValue(next) <= 0) {
clearInterval(timer);
let height = getHeight(next) > 600 ? 600 : getHeight(next);
let width = (height / getHeight(next)) * getWidth(next);
container.style.height = `${height}px`;
container.style.width = `${width}px`;
previous.classList.remove('previous');
previous.classList.add('next');
current.classList.remove('current');
current.classList.add('previous');
next.classList.remove('next');
next.classList.add('current');
previous = document.querySelector('.previous');
next = document.querySelector('.next');
current = document.querySelector('.current');
previous.removeAttribute('style');
next.removeAttribute('style');
previous.style.right = `100%`;
next.style.left = `100%`;
auto();
return;
}
next.style.left = `${getLeftValue(next) - 10}%`;
current.style.right = `${getRightValue(current) + 10}%`;
}, 10);
});
//鼠标移入移出时清除和设置自动轮播的定时器
container.addEventListener('mouseenter', () => {
clearInterval(autoTimer);
//鼠标移移出时重启自动轮播,注意为了避免同一次移出造成mouseleave的重复调用,每次调用mouseleave时先清除定时器
current.addEventListener('mouseleave', () => {
clearInterval(autoTimer);
auto();
});
});
function getWidth(img) {
return parseInt(img.getAttribute('w'));
}
function getHeight(img) {
return parseInt(img.getAttribute('h'));
}
function getLeftValue(ele) {
if (ele.style.left === '') return 0;
return parseInt(ele.style.left.replace('%', ''));
}
function getRightValue(ele) {
if (ele.style.right === '') return 0;
return parseInt(ele.style.right.replace('%', ''));
}
</script>
</html>
因篇幅问题不能全部显示,请点此查看更多更全内容