引言
element-ui组件库中,有一个Carousel走马灯组件,也就是我们平时说的轮播图,为了搞清它的实现原理,接下来我们使用原生js实现一个轮播图效果。
1.基础轮播图实现过程
1.1 基础样式配置
分析实现轮播的基本要素,固定容器,图片,切换circle, 以及当前的活跃样式.active
, 最终得到以下基础样式:
代码部分:
<div class="containter">
<div class="imageBox">
<img class="imageItem" src="./image/ftai-bg.png" alt="">
<img class="imageItem" src="./image/ftai-home2.png" alt="" >
<img class="imageItem" src="./image/bg.png" alt="">
<img class="imageItem" src="./image/ftai-home.png" alt="">
</div>
<div class="circleBox">
<span class="circleItem active" ></span>
<span class="circleItem"></span>
<span class="circleItem"></span>
<span class="circleItem"></span>
</div>
</div>
.containter {
position: relative;
width: 600px;
height: 400px;
overflow: hidden;
}
.imageBox {
width: 600px;
display: flex;
transition: all .5s;
}
.imageItem {
width: 600px;
height: 400px;
flex-shrink: 0; /* 防止图片缩小 */
}
.circleBox {
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: 30px;
width: 200px;
height: 40px;
/* outline: 1px solid #ccc; */
display: flex;
justify-content: space-around;
align-items: center;
}
.circleItem {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;;
border: 2px solid #EA7C13;
z-index: 10;
}
.circleItem:hover {
cursor: pointer;
}
.active {
background-color: #EA7C13;
}
1.2 js逻辑
思路:通过当前图片的索引实现图片容器不同位置的切换。容器位置切换方式有很多种,此处我们使用tranlateX(xx)
来实现。
示意:
// 获取图片容器
const imageBoxDom = document.querySelector('.imageBox')
// 获取所有circle的dom类数组
const circleItemArr = document.querySelectorAll('.circleItem')
// circle点击事件
circleItemArr.forEach((item, index) => {
item.addEventListener('click',() => {
// 图片容器偏移到当前图片位置
imageBoxDom.style.transform = `translateX(-${index}00%)`
// 改变当前活跃状态的circle
let activeDom = document.querySelector('.active')
activeDom.classList.remove('active')
item.classList.add('active')
})
})
1.3 实现效果
至此,一个简单的轮播图就实现了
2.卡片化轮播图实现过程
此外,elementUI还提供了一种卡片化的轮播图,这种轮播图的样式采用了堆叠式的设计,只需要稍作调整就可以实现这种效果
2.1 基础样式配置
<body>
<div class="box">
<img class="imageItem" src="./image/ftai-bg.png" alt="PIC">
<img class="imageItem" src="./image/ftai-home2.png" alt="PIC">
<img class="imageItem" src="./image/bg.png" alt="PIC">
<img class="imageItem" src="./image/ftai-home.png" alt="PIC">
<img class="imageItem" src="./image/ftai-bg.png" alt="PIC">
<div class="btns">
<span class="prebtn btn"><</span>
<span class="nextbtn btn">></span>
</div>
</div>
</body>
body {
display: flex;
justify-content: center;
background-color: #534F50;
padding-top: 200px;
}
.box {
width: 1200px;
height: 300px;
margin: 50px auto;
position: relative;
display: flex;
}
.imageItem {
position: absolute;
left: 200px;
width: 800px;
height: 400px;
transition: all .3s linear;
flex-shrink: 0; /* 防止图片缩小 */
}
.box:hover .btn {
opacity: 1;
}
.prebtn {
left: 0px;
}
.back {
left: 600px;
}
.active {
left: 300px;
transform: scale(1.5);
z-index: 10;
}
.btn {
width: 60px;
height: 60px;
display: block;
position: absolute;
background-color: rgba(0, 0, 0, .5);
font-size: 50px;
font-family: "微软雅黑";
color: rgba(255, 255, 255, .5);
line-height: 55px;
text-align: center;
cursor: pointer;
z-index: 100;
opacity: 0;
transition: opacity .3s linear;
}
.btns .btn:first-child {
top: 200px
}
.btns .btn:last-child {
top: 200px;
right: 0px;
}
2.1 js实现逻辑
const prebtn = document.querySelector('.prebtn')
const nextbtn = document.querySelector('.nextbtn')
const imgArr = document.querySelectorAll('.imageItem')
const imgLength = imgArr.length
const scaleNum = 0.9 // 缩放倍数
const offsetNum = 200 // 偏移基础量
let currentIndex = 0
layout()
prebtn.addEventListener('click', () => {
preFn()
})
nextbtn.addEventListener('click', () => {
nextFn()
})
function preFn() {
console.log(27, 'aa');
if(currentIndex === 0) {
return
}
currentIndex --
layout()
}
function nextFn() {
if(currentIndex === imgArr.length - 1) {
return
}
currentIndex ++
layout()
}
function layout() {
imgArr.forEach((item,index) => {
let transNum = (index - currentIndex) * offsetNum // 水平位置偏移量
const scale = scaleNum ** Math.abs(index - currentIndex) // 缩放量
const sign = Math.sign(index - currentIndex) // math函数,此处获取正负数(用于判断图片索引与当前索引的位置关系)
const rotateNum = index === currentIndex ? 0 : -45 * sign // 旋转晾
if(index !== currentIndex) {
transNum = transNum + 100 * sign
}
// 根据当前的索引定义不同位置图片的样式
item.style.transform = `translateX(${transNum}px) scale(${scale}) rotateY(${rotateNum}deg)`
item.style.zIndex = imgLength - Math.abs(index - currentIndex)
item.style.opacity = 0.8 ** Math.abs(index - currentIndex)
})
}