轮播图,作为前端学习的经典案例,涉及了各种知识点,包括动画函数,js基础知识以及逻辑思路等,一辈子只做一次。
下面总结实现轮播图的三种方法,从易到难,大家选择性学习。
轮播图
- 一、 Vue.js实现轮播图
- 二、js+css实现轮播图(移动端)
- index.html
- img
- css
- index.css
- js
- index.js
- 三、纯js实现轮播图(动画函数)
- index.html
- css
- index.css
- img
- js
- index.js
- animate.js
一、 Vue.js实现轮播图
源码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
#mask{
margin: 0px auto;
width: 690px; /*盒子宽度和高度跟图片一致 */
height: 380px;
}
.left,.right{
width: 50px;
height: 50px;
}
.left{
position: relative;
top: -250px;
}
.right{
position: relative;
top: -250px;
left: 300px;
float: left;
}
</style>
</head>
<body>
<div id="mask">
<!-- 鼠标经过时自动播放图片 -->
<img :src="imgArr[index]"v-on:mouseover="change" v-on:mouseout="stop">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app=new Vue({
el: '#mask',
data: {
imgArr:[
"./image/lx1.jpeg",
"./image/lx2.jpeg",
"./image/lx3.jpeg",
"./image/lx4.jpeg",
],
index:0
},
methods:{
next:function (){
this.index++;
if(this.index===4){
this.index=0
}
},
change:function(){
this.timer=setInterval(this.next,2000);
},
stop:function (){
clearInterval(this.timer)
}
},
})
</script>
</body>
</html>
二、js+css实现轮播图(移动端)
index.html
<!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>
<link rel="stylesheet" href="./css/index.css">
<script src="./js/index.js"></script>
</head>
<body>
<div class="focus">
<ul>
<li>
<a href="#"><img src="./img/lx1 (3).jpeg" alt=""></a>
</li>
<li>
<a href="#"><img src="./img/lx1 (1).jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="./img/lx1 (2).jpeg" alt=""></a>
</li>
<li>
<a href="#"><img src="./img/lx1 (3).jpeg" alt=""></a>
</li>
<li>
<a href="#"><img src="./img/lx1 (1).jpg" alt=""></a>
</li>
</ul>
<ol class="circle">
<li class="current"></li>
<li></li>
<li></li>
</ol>
</div>
</body>
</html>
img
css
index.css
*{
margin: 0%;
padding: 0%;
}
.focus {
margin: 0px auto;
position: relative;
width: 690px;
height: 350px;
background-color: #fff;
overflow: hidden;
}
.focus ul {
position: absolute;
top: 0;
left: 0;
width: 500%;
margin-left: -100%;
}
.focus ul li {
float: left;
width: 20%;
}
.circle {
position: absolute;
bottom: 10px;
right: 50px;
}
.circle li {
list-style: none;
float: left;
width: 8px;
height: 8px;
/* background-color: #fff; */
border: 2px solid rgba(255, 255, 255, 0.5);
margin: 0 3px;
border-radius: 50%;
/*鼠标经过显示小手*/
cursor: pointer;
transition: all .3s;
}
.focus ol li.current{
width: 15px;
background-color: #fff;
}
js
index.js
window.addEventListener('load',function(){
var focus=document.querySelector('.focus')
var ul=focus.children[0]
var ol=focus.children[1]
var focusWidth=focus.offsetWidth
var index=0
var timer=setInterval(function(){
index++
// 移动距离
var step=-index*focusWidth
ul.style.transition='all .3s'
ul.style.transform='translateX('+step+'px)'
},2000);
//判断过渡是否完成
ul.addEventListener('transitionend',function(){
//如果到达第三张图片,将无缝跳转到第一张
if(index>=ul.children.length-2){
index=0
ul.style.transition='none'
var step=-index*focusWidth
ul.style.transform='translateX('+step+'px)'
}
else if(index<0){
index=ul.children.length-3//跳转到第三张图片
ul.style.transition='none'
var step=-index*focusWidth
ul.style.transform='translateX('+step+'px)'
}
//小圆点跟随变化
ol.querySelector('.current').classList.remove('current')
ol.children[index].classList.add('current')
})
//手指拖动图片
// 初始位置
var startX=0
var moveX=0
var flag=false
ul.addEventListener('touchstart', function (e) {
// 获取鼠标位置
startX = e.targetTouches[0].pageX
clearInterval(timer)
})
ul.addEventListener('touchmove', function (e) {
moveX = e.targetTouches[0].pageX-startX
// 盒子位置=初始位置+盒子移动距离
var step=-index*focusWidth+moveX
ul.style.transition='none'
ul.style.transform='translateX('+step+'px)'
flag=true //触发移动事件,flag为true
})
//手指左右滑动切换图片
ul.addEventListener('touchend',function(){
if(flag){
if(Math.abs(moveX)>50){
//右滑上一张,当位于第一张图片是,index<0
if(moveX>0){
index--
}else{
index++ //左滑下一张
}
var step=-index*focusWidth
ul.style.transition='all .3s'
ul.style.transform='translateX('+step+'px)'
}else{
var step=-index*focusWidth
ul.style.transition='all .1s'
ul.style.transform='translateX('+step+'px)'
}
}
// 左右互动距离大于50,就切换上/或下一张图片
clearInterval(timer)
timer=setInterval(function(){
index++
// 移动距离
var step=-index*focusWidth
ul.style.transition='all .3s'
ul.style.transform='translateX('+step+'px)'
},2000);
})
})
三、纯js实现轮播图(动画函数)
index.html
<!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>
<link rel="stylesheet" href="./css/index.css">
<script src="./js/animate.js"></script><!-- 需要位于index.js之上 -->
<script src="./js/index.js"></script>
</head>
<body>
<div class="main">
<h1>轮播图</h1>
<div class="focus">
<a href="javascript:;" class="left"><</a>
<a href="javascript:;" class="right">">></a>
<ul>
<li>
<a href="#"><img src="./img/lx1 (1).jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="./img/lx1 (2).jpeg" alt=""></a>
</li>
<li>
<a href="#"><img src="./img/lx1 (3).jpeg" alt=""></a>
</li>
<li>
<a href="#"><img src="./img/lx1 (4).jpeg" alt=""></a>
</li>
</ul>
<ol class="circle">
</ol>
</div>
</div>
</body>
</html>
css
index.css
*{
margin: 0%;
padding: 0%;
}
.main{
width: 690px;
height: 350px;
margin: 0px auto;
}
h1{
text-align: center;
}
.focus {
position: relative;
width: 690px;
height: 350px;
background-color: purple;
overflow: hidden;
}
.left,.right{
display: none;
position: absolute;
top: 50%;
margin-top: -20px;
width: 24px;
height: 40px;
background: rgba(0, 0, 0, .3);
text-align: center;
line-height: 40px;
color: #fff;
font-family: 'icomoon';
font-size: 18px;
z-index: 2;
}
a{
text-decoration: none;
}
.right{
right: 0%;
}
.focus ul {
position: absolute;
top: 0;
left: 0;
width: 600%;
}
.focus ul li {
float: left;
}
.circle {
position: absolute;
bottom: 10px;
left: 50px;
}
.circle li {
list-style: none;
float: left;
width: 8px;
height: 8px;
/*background-color: #fff;*/
border: 2px solid rgba(255, 255, 255, 0.5);
margin: 0 3px;
border-radius: 50%;
/*鼠标经过显示小手*/
cursor: pointer;
}
.current{
background-color: #fff;
}
img
同上
js
index.js
window.addEventListener('load',function(){
var focus = document.querySelector('.focus')
var left=document.querySelector('.left')
var right=document.querySelector('.right')
// 显示切换栏
focus.addEventListener('mouseenter',function(){
left.style.display='block'
right.style.display='block'
})
// 隐藏切换栏
focus.addEventListener('mouseleave',function(){
left.style.display='none'
right.style.display='none'
})
// 动态创建小圆圈
var focusWidth=focus.offsetWidth
var ul=focus.querySelector('ul')
var ol = focus.querySelector('.circle')
for(var i=0;i<ul.children.length;i++){
var li=document.createElement('li')
li.setAttribute('index', i);
ol.appendChild(li)
li.addEventListener('click',function(){
for(var i=0;i<ol.children.length;i++){
ol.children[i].className=''
}
this.className='current'
// 当我们点击了某个小li 就拿到当前小li 的索引号
var index = this.getAttribute('index');
// 当我们点击了某个小li 就要把这个li 的索引号给 num
num = index;
// 当我们点击了某个小li 就要把这个li 的索引号给 circle
circle = index;
animate(ul, -index * focusWidth);
})
}
ol.children[0].className='current'
// 克隆第一张图片
var first=ul.children[0].cloneNode(true)
ul.appendChild(first)
//图片指针
var num=0
// 圆圈指针
var circle=0
// flag 节流阀
var flag=true
//右侧按钮
// console.log(foucusWidth);
right.addEventListener('click',function(){
if(flag){
flag=false
if(num==ul.children.length-1){
ul.style.left=0
num=0
}
num++
var step=-num*focusWidth
animate(ul,step,function(){
flag=true //执行了animate函数后才能切换下一张图片
})
circle++
if(circle==ol.children.length){
console.log(ol.children.length);
circle=0
}
circleChange();
}
})
//左侧按钮
left.addEventListener('click', function() {
if (flag) {
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = step + 'px';
}
num--;
var step=-num*focusWidth
animate(ul, step, function() {
flag = true;
});
// 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
circle--;
// 如果circle < 0 说明第一张图片,则小圆圈要改为第4个小圆圈(3)
// if (circle < 0) {
// circle = ol.children.length - 1;
// }
circle = circle < 0 ? ol.children.length - 1 : circle;
// 调用函数
circleChange();
}
});
function circleChange() {
// 先清除其余小圆圈的current类名
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
// 留下当前的小圆圈的current类名
ol.children[circle].className = 'current'
}
// 10. 自动播放轮播图
var timer = setInterval(function() {
//手动调用点击事件
right.click();
}, 2000);
})
animate.js
//动画函数封装,实现匀减速移动图片
function animate(obj, target, callback) {
// console.log(callback); callback = function() {} 调用的时候 callback()
// 先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function() {
// 步长值写到定时器的里面
// 把我们步长值改为整数 不要出现小数的问题
// var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
// 停止动画 本质是停止定时器
clearInterval(obj.timer);
// 回调函数写到定时器结束里面
// if (callback) {
// // 调用函数
// callback();
// }
callback && callback();
}
// 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}