基于Vue3的Web端自定义轮播图动画效果(完整版保姆级教程,附源码)
大家好~ 我是前端uio,本文主要使用vue3制作web端自定义轮播图动画效果(完整版保姆级教程,附源码) 有什么疑问都欢迎私聊或者在评论区留言。如果需要开发web网页或者微信小程序都可以找我私聊,我会尽可能回答我了解的内容。
一、功能说明
1.最终效果
自定义轮播图
2.图片切换
i)先使用Dom操作获取图片信息
let currentImg = document.querySelector('.img');
ii)改变图片的src属性
① 因为有多张图片,考虑代码的简洁性,先设置imgArr数组放置所有的轮播图片
const imgArr = [
'http://localhost:8081/img/test.2140f46e.jpeg',
'http://localhost:8081/img/test1.b5a3016e.jpeg',
'http://localhost:8081/img/test2.060c4789.jpeg'
]
请注意:若使用网络图片,则没有影响;若使用的是本地图片,这里的图片不能使用相对路径,需要使用源路径。可先将所需图片放置在页面中,如下图所示,可以在浏览器中,通过点击键盘上的F12,可以通过筛选器找到图片所在的元素后,鼠标悬浮在该元素,即可查看源图片路径。
② 通过动态修改imgIndex的值,可实现图片的切换
currentImg.src= imgArr[imgIndex.value]
iii)图片切换的动画效果
① 以淡入动画为例,在js中,进行图片切换时,使用Dom操作先将图片的透明度,也就是opacity设置为0,再进行0.5s的延时,延时结束后,将图片的opacity设置为1,即可实现简单的淡入动画效果。
3.控制图片切换的左右箭头图标
i)左右箭头
① 图标
本文使用的是element plus 提供的icon图标 ,可根据需要进行替换
<el-icon><ArrowLeftBold /></el-icon>
<el-icon><ArrowRightBold /></el-icon>
② 绑定事件(以左边的箭头为例)
通过v-on,也就是@来绑定点击事件,并传入自定义参数(用于判断是点击了左还是右箭头),在事件函数中修改imgIndex的值,即可完成左右切换图片
<el-icon size="40" class="left-btn" @click="next(-1)"><ArrowLeftBold /></el-icon>
③ 样式(以左箭头为例)
父元素使用相对定位,左箭头icon使用绝对定位后,通过设置cursor,实现鼠标悬浮时的小手效果,设置top为50%(在绝对定位时),可实现垂直方向的居中
.left-btn {
position: absolute;
cursor: pointer;
top: 50%;
left: 30px;
width: auto;
}
④动画效果
效果:若鼠标悬浮在轮播图区域内,左右箭头显示;若鼠标未悬浮在轮播图区域内,左右箭头隐藏。
步骤(以less为例):先设置左右箭头的宽度为0,即可实现初始化时左右箭头隐藏,当鼠标悬浮在轮播图区域内,触发hover伪类选择器,所以在伪类选择器中设置前面提到的③中的样式,即可实现动画效果。
.banner {
position: relative;
width: 100%;
.left-btn, .right-btn {
width: 0;
}
&:hover {
.left-btn {
position: absolute;
cursor: pointer;
top: 50%;
left: 30px;
width: auto;
}
}
}
4. 标题过渡动画
i)标题内容组件
① 使用Vue的<transition>组件,可点击跳转到官网进行查看,本文主要讲解用法以及注意事项,这里不再赘述。
② 注意:<transition>组件只能放置一个 Vue 组件或 HTML 元素,所以只能在里面放置一个<div>标签,将其他内容放置在<div>标签内,或者使用多个<transition>组件分别进行过渡动画效果的控制。
ii)从左渐入到中间的过渡动画
① 过渡动画的样式
在组件中传入name效果名,在style中,使用对应的css样式,具体实现过程与介绍,可查看基于css的过渡效果。本文在进入动画前使用margin-right,实现从左边进入动画,在动画进入前以及动画结束后设置opacity(透明度)为0的动画效果,实现淡入淡出动画。最后在transition设置动画时长。
.scale-enter-active{
transition: all 1s ease-in-out;
}
.scale-leave-active {
transition: all 1s linear;
}
.scale-enter-from{
margin-right: 300px;
opacity: 0;
}
.scale-leave-to {
opacity: 0;
}
iii)标题内容切换
① 使用v-for进行遍历,创建多个<transition>组件,通过绑定不同的key来区分不同的<transition>组件,从而实现标题内容的切换。
② 由于可能进行频繁的切换,所以使用v-show控制内容的切换。
③ v-if 会把元素进行删除,v-show 只是进行隐藏,该元素仍然保留,所以进行频繁的切换的话,使用v-show 效率会更高一点,若不频繁切换显示与隐藏,使用v-if 也可以,具体使用哪一种需要看具体的实现方式以及效果。
<div v-for="(title,titleIndex) in titles" :key="titleIndex" class="content">
<transition name="scale">
<div v-show="imgIndex===titleIndex" >
<span>{{title}}</span>
</div>
</transition>
</div>
5. 轮播图底下的指示圆圈
i)放置圆圈
根据图片数组的长度进行循环遍历,添加并动态绑定相应的选中样式即可实现指示圆圈动画效果。
<div class="dot-content">
<div v-for="(item,index) in imgArr.length" :key="item" :class="index===imgIndex?'active':'dot-box'">
</div>
</div>
ii)样式
当前图片css样式为active,未被选中图片的样式dot-box。
.dot-content {
display: flex;
position: absolute;
bottom: 20px;
justify-content: space-around;
align-items: center;
width: 100px;
height: 30px;
.dot-box {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #fff;
}
.active {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: red;
}
}
iii)动态样式绑定
使用 v-bind 进行动态样式绑定,本质上是一个三元表达式,当问号前面内容判断为true是,使用冒号前的样式;当问号前面内容判断为false时,使用冒号后的样式。
:class="index===imgIndex?'active':'dot-box'"
6.注意事项
i)边界条件
左右切换图片时,第一张图片的左切换,与最后一张图片的右切换需要进行判断处理,本文采用循环轮播的方式进行处理,可根据需要进行调整。
if(imgIndex.value >= imgArr.length ) {
imgIndex.value=0
}
if(imgIndex.value <0 ) {
imgIndex.value=imgArr.length-1
}
二、主要代码
完整版代码请看下方第三部分《拓展与练习》的第2小点
/**
* @name { 轮播图 }
* @info { 自定义轮播图以及动画 }
* @author { 前端uio 2024-5-20 }
*
* @click funtion => 处理对应的点击事件
* @transition 组件 => 实现过渡动画
* @el-icon 组件 => 切换图片的左右箭头图标
*/
<template>
<div>
<div class="banner">
<img src="../../assets/image/test/test.jpeg" class="img">
<div v-for="(title,titleIndex) in titles" :key="titleIndex" class="content">
<transition name="scale">
<div v-show="imgIndex===titleIndex" >
<span>{{title}}</span>
</div>
</transition>
</div>
<div class="dot-content">
<div v-for="(item,index) in imgArr.length" :key="index" :class="index===imgIndex?'active':'dot-box'">
</div>
</div>
<el-icon size="40" class="left-btn" @click="next(-1)"><ArrowLeftBold /></el-icon>
<el-icon size="40" class="right-btn" @click="next(1)"><ArrowRightBold /></el-icon>
</div>
</div>
</template>
<script setup>
import {ref} from 'vue'
const imgIndex = ref(0)
const imgArr = [
'http://localhost:8081/img/test.2140f46e.jpeg',
'http://localhost:8081/img/test1.b5a3016e.jpeg',
'http://localhost:8081/img/test2.060c4789.jpeg'
]
const titles = [
'胡桃🍑🍑🍑🍑🍑🍑','启动⚪⚪⚪⚪⚪⚪','撒花❀❀❀❀❀❀'
]
const next = (e) => {
let currentImg = document.querySelector('.img');
e>0? imgIndex.value+=1 : imgIndex.value-=1
if(imgIndex.value >= imgArr.length ) {
imgIndex.value=0
}
if(imgIndex.value <0 ) {
imgIndex.value=imgArr.length-1
}
currentImg.style.opacity = '0'
setTimeout(() => {
currentImg.src= imgArr[imgIndex.value]
currentImg.style.opacity = '1';
},500)
}
</script>
<style scoped lang="less">
.banner {
position: relative;
display: flex;
justify-content: center;
width: 100%;
.left-btn, .right-btn {
width: 0;
}
&:hover {
.left-btn {
position: absolute;
cursor: pointer;
top: 50%;
left: 30px;
width: auto;
}
.right-btn {
position: absolute;
cursor: pointer;
top: 50%;
right: 30px;
width: auto;
}
}
.img {
display: none;
&:first-child {
display: block;
height: 60vh;
opacity: 1;
transition: opacity 0.5s ease;
}
}
.scale-enter-active{
transition: all 1s ease-in-out;
}
.scale-leave-active {
transition: all 1s linear;
}
.scale-enter-from{
margin-right: 300px;
opacity: 0;
}
.scale-leave-to {
opacity: 0;
}
.content {
position: absolute;
top: 50%;
font-size: 40px;
color: #fff;
}
.dot-content {
display: flex;
position: absolute;
bottom: 20px;
justify-content: space-around;
align-items: center;
width: 100px;
height: 30px;
.dot-box {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #fff;
}
.active {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: red;
}
}
}
</style>
三、拓展与练习
1.点击轮播图下方的指示圆圈进行图片的切换
i)绑定点击事件
当点击相应的指示圆圈时,触发selectImg事件,传入当前指示圆圈绑定的key,来确定当前点击的元素。
<div class="dot-content">
<div v-for="(item,index) in imgArr.length" :key="index" :class="index===imgIndex?'active':'dot-box'" @click="selectImg(index)">
</div>
</div>
ii) 鼠标悬浮样式
添加了鼠标悬浮时的小手指示样式
.dot-content {
display: flex;
position: absolute;
bottom: 20px;
justify-content: space-around;
align-items: center;
width: 100px;
height: 30px;
.dot-box {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #fff;
cursor: pointer;
}
.active {
cursor: pointer;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: red;
}
}
2.项目源码(完整版)
/**
* @name { 轮播图(完整源码) }
* @info { 自定义轮播图以及动画 }
* @author { 前端uio 2024-5-20 }
*
* @click funtion => 处理对应的点击事件
* @transition 组件 => 实现过渡动画
* @el-icon 组件 => 切换图片的左右箭头图标
*/
<template>
<div>
<div class="banner">
<img src="../../assets/image/test/test.jpeg" class="img">
<div v-for="(title,titleIndex) in titles" :key="titleIndex" class="content">
<transition name="scale">
<div v-show="imgIndex===titleIndex" >
<span>{{title}}</span>
</div>
</transition>
</div>
<div class="dot-content">
<div v-for="(item,index) in imgArr.length" :key="index" :class="index===imgIndex?'active':'dot-box'" @click="selectImg(index)">
</div>
</div>
<el-icon size="40" class="left-btn" @click="next(-1)"><ArrowLeftBold /></el-icon>
<el-icon size="40" class="right-btn" @click="next(1)"><ArrowRightBold /></el-icon>
</div>
</div>
</template>
<script setup>
import {ref} from 'vue'
const imgIndex = ref(0)
const imgArr = [
'http://localhost:8081/img/test.2140f46e.jpeg',
'http://localhost:8081/img/test1.b5a3016e.jpeg',
'http://localhost:8081/img/test2.060c4789.jpeg'
]
const titles = [
'胡桃🍑🍑🍑🍑🍑🍑','启动⚪⚪⚪⚪⚪⚪','撒花❀❀❀❀❀❀'
]
const selectImg =(e) => {
let currentImg = document.querySelector('.img')
currentImg.style.opacity = '0'
setTimeout(() => {
currentImg.src= imgArr[e]
imgIndex.value = e
currentImg.style.opacity = '1';
},500)
}
const next = (e) => {
e>0? imgIndex.value+=1 : imgIndex.value-=1
if(imgIndex.value >= imgArr.length ) {
imgIndex.value=0
}
if(imgIndex.value <0 ) {
imgIndex.value=imgArr.length-1
}
selectImg(imgIndex.value)
}
</script>
<style scoped lang="less">
.banner {
position: relative;
display: flex;
justify-content: center;
width: 100%;
.left-btn, .right-btn {
width: 0;
}
&:hover {
.left-btn {
position: absolute;
cursor: pointer;
top: 50%;
left: 30px;
width: auto;
}
.right-btn {
position: absolute;
cursor: pointer;
top: 50%;
right: 30px;
width: auto;
}
}
.img {
display: none;
&:first-child {
display: block;
height: 60vh;
opacity: 1;
transition: opacity 0.5s ease;
}
}
.scale-enter-active{
transition: all 1s ease-in-out;
}
.scale-leave-active {
transition: all 1s linear;
}
.scale-enter-from{
margin-right: 300px;
opacity: 0;
}
.scale-leave-to {
opacity: 0;
}
.content {
position: absolute;
top: 50%;
font-size: 40px;
color: #fff;
}
.dot-content {
display: flex;
position: absolute;
bottom: 20px;
justify-content: space-around;
align-items: center;
width: 100px;
height: 30px;
.dot-box {
width: 20px;
height: 20px;
border-radius: 50%;
background-color: #fff;
cursor: pointer;
}
.active {
cursor: pointer;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: red;
}
}
}
</style>
四、总结与思考
1.能不能不使用Dom操作完成轮播图效果(使用滚动条)
2.当前轮播图下方的指示圆圈禁止点击(禁止点击的样式)
更多推荐
所有评论(0)