一、前言
看别人做的效果不错,自己也搞一个试试
二、代码
<template>
<div class="w-ful h-full flex justify-center items-center flex-col border border-red-300" ref="lunboref">
<div class="flex-1 w-full overflow-hidden">
<div class="h-full transition-all duration-500" :style="[yidongjuli,allwidth]" >
<div v-for="(item,index) in imagelist" :key="index+'a'" class="h-full float-left"
:style="{width:`${kuandu}px`}">
<img :src="item" alt="" class="h-full w-full object-contain">
</div>
</div>
</div>
<div class="h-10 w-full flex justify-center items-center bg-gray-600">
<div v-for="(item,index) in imagelist" :key="index"
class=" py-1 flex h-full justify-center items-center flex-nowrap relative"
:style="{width:`${1/imagelist.length*100}%`}">
<img :src="item" alt="" class="w-full h-full object-contain">
<div class="absolute inset-0 bg-gray-600 hover:bg-opacity-0 cursor-pointer"
:class="[activeindex===index?'bg-opacity-0':'bg-opacity-50',]" @click="dianji(index)"></div>
</div>
</div>
</div>
</template>
<script setup>
import img1 from "./tupian/01.jpg"
import img2 from "./tupian/02.jpg"
import img3 from "./tupian/03.jpg"
import img4 from "./tupian/04.jpg"
import {defineComponent, ref, onMounted, computed} from "vue";
import {useStore} from "vuex"
import {useRouter, useRoute} from "vue-router"
const store = useStore()
const router = useRouter()
const route = useRoute()
const lunboref = ref(null)
const activeindex = ref(0)
const yidongjuli = computed(()=>{
return {transform:`translateX(-${activeindex.value * kuandu.value}px)`}
})
const allwidth = computed(()=>{
return {width:`${imagelist.value.length * kuandu.value}px`}
})
const kuandu = ref(0)
const imagelist = ref([img1, img2, img3, img4])
const dianji = (index) => {
activeindex.value = index
console.log(activeindex.value)
}
onMounted(() => {
// 获取元素宽度
kuandu.value = lunboref.value.clientWidth
console.log(kuandu.value, "宽度")
})
</script>
<style scoped>
</style>
没有自动播放功能,等有时间吧
三、功能完善版的来了
2021年9月17日 17:15:55
<template>
<div class="w-full h-full border" ref="lunboref" @mouseover="zanting(false)" @mouseleave="zanting(true)">
<div class="h-4/5 w-full overflow-hidden">
<ul style="width:99999px;height: 100%;" :style="{transform:`translateX(-${yidongjuli}px)`}"
class="transition-all duration-500">
<li :style="{width:`${kuandu}px`}" class="h-full flex justify-center items-center float-left relative"
v-for="(item,index) in imglist" :key="index+'a'">
<img :src="item" alt="轮播图" class="w-full h-full object-contain">
<div :style="{width:`${kuandu/10}px`}" @click="qiehuan(-1)" v-show="activeindex>0 || prop.xunhuan"
class="group absolute top-0 bottom-0 left-0 flex justify-center items-center bg-opacity-0 hover:bg-opacity-40 bg-gray-400 cursor-pointer active:bg-gray-500 active:text-blue-300">
<span class="text-white text-opacity-0 group-hover:text-opacity-100 iconfont icon-zuojiantou2"></span>
</div>
<div :style="{width:`${kuandu/10}px`}" @click="qiehuan(1)"
v-show="activeindex<imglist.length-1 || prop.xunhuan"
class="group absolute top-0 bottom-0 right-0 w-6 flex justify-center items-center bg-opacity-0 hover:bg-opacity-40 bg-gray-400 cursor-pointer active:bg-gray-500 active:text-blue-300">
<span class="text-white text-opacity-0 group-hover:text-opacity-100 iconfont icon-youjiantou2"></span>
</div>
</li>
</ul>
</div>
<div class="h-1/5 w-full overflow-hidden">
<ul style="width:99999px;height: 100%;" :style="{transform:`translateX(${pianyix}px)`}" class="transition-all">
<li class="flex justify-center items-center h-full float-left relative" :style="{width:`${kuandu/4}px`}"
v-for="(item,index) in imglist" :key="index" @mousedown="mouseputdown2">
<img :src="item" alt="缩略图" class="w-full h-full object-contain"
:class="[activeindex===index?'border border-blue-400':'']">
<div class="absolute inset-0 cursor-pointer bg-gray-500 hover:border hover:border-blue-400 select-none"
:class="[activeindex===index?'bg-opacity-0':'bg-opacity-20']" @click="dianji(index)"></div>
</li>
</ul>
</div>
</div>
</template>
<script setup>
import img1 from "./tupian/01.jpg"
import img2 from "./tupian/02.jpg"
import img3 from "./tupian/03.jpg"
import img4 from "./tupian/04.jpg"
import {computed, onMounted, ref, watch, defineProps} from "vue";
import {useStore} from "vuex"
import {useRoute, useRouter} from "vue-router"
const store = useStore()
const router = useRouter()
const route = useRoute()
// 传递进来的数据
const prop = defineProps({
// 播放的列表
list1: {
default(data) {
return data || []
}
},
// 是否开启循环
xunhuan: {
type: Boolean,
default: false,
},
// 是否开启自动播放
autoplay: {
type: Boolean,
default: false,
},
// 多久切换一次
autotime: {
type: Number,
default: 3,
}
})
// hover状态下不轮播
const lunbo = ref(true)
// 整个轮播组件
const lunboref = ref(null)
// 图片列表
// const imglist = ref([img1, img2,])
const imglist = ref([img1, img2, img3, img4, img1, img2, img3, img4, img1, img2, img3, img4, img1, img2, img3, img4])
// 当前激活的序号
const activeindex = ref(0)
// 每个图片的宽度
const kuandu = ref(0)
// 鼠标拖动的偏移量
const pianyix = ref(0)
const yidongjuli = computed(() => {
return activeindex.value * kuandu.value
})
const dianji = (index) => {
activeindex.value = index
}
onMounted(() => {
kuandu.value = lunboref.value.offsetWidth
// 判断是否开启自动播放
if (prop.autoplay) {
setTimeout(() => {
playfunc(1)
}, prop.autotime * 1000)
}
})
// 边界计算
watch(pianyix, () => {
if (imglist.value.length <= 4) {
pianyix.value = 0
} else if (pianyix.value > 0) {
pianyix.value = 0
} else if (pianyix.value < -(imglist.value.length - 4) * kuandu.value / 4) {
pianyix.value = -(imglist.value.length - 4) * kuandu.value / 4
}
})
const mouseputdown2 = (e) => {
let startX = e.clientX;
const zancun = pianyix.value
document.onmousemove = (e) => {
let endX = e.clientX;
pianyix.value = endX - startX + zancun;
}
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
}
}
// 点击前后箭头
const qiehuan = (index) => {
activeindex.value = activeindex.value + index
if (prop.xunhuan) {
// 开启循环
if (activeindex.value < 0) {
activeindex.value = imglist.value.length
} else if (activeindex.value > imglist.value.length - 1) {
activeindex.value = 0
}
} else {
// 没开循环
if (activeindex.value < 0) {
activeindex.value = 0
} else if (activeindex.value > imglist.value.length - 1) {
activeindex.value = imglist.value.length - 1
}
}
const index2 = Math.floor(activeindex.value / 4)
pianyix.value = -index2 * kuandu.value
}
// 自动播放
const playfunc = (canshu) => {
let index = canshu
if (!prop.xunhuan) {
if (activeindex.value <= 0) {
index = 1
} else if (activeindex.value >= imglist.value.length - 1) {
index = -1
}
}
if(lunbo.value){
qiehuan(index)
}
setTimeout(() => {
playfunc(index)
}, prop.autotime * 1000)
}
// 鼠标移入组件范围内时,轮播停止
const zanting=(status)=>{
lunbo.value = status
}
</script>
<style scoped>
</style>
2021年9月17日 17:43:01
<template>
<div class="w-full h-full border" ref="lunboref" @mouseover="zanting(false)" @mouseleave="zanting(true)">
<div class="h-4/5 w-full overflow-hidden relative">
<ul style="width:99999px;height: 100%;" :style="{transform:`translateX(-${yidongjuli}px)`}"
class="transition-all duration-500">
<li :style="{width:`${kuandu}px`}" class="h-full flex justify-center items-center float-left "
v-for="(item,index) in prop.imglist" :key="index+'a'">
<img :src="item" alt="轮播图" class="w-full h-full object-contain">
</li>
</ul>
<div :style="{width:`${kuandu/10}px`}" @click="qiehuan(-1)" v-show="activeindex>0 || prop.xunhuan"
class="group absolute top-0 bottom-0 left-0 flex justify-center items-center bg-opacity-0 hover:bg-opacity-40 bg-gray-400 cursor-pointer active:bg-gray-500 active:text-blue-300">
<span class="text-white text-opacity-0 group-hover:text-opacity-100 iconfont icon-zuojiantou2"></span>
</div>
<div :style="{width:`${kuandu/10}px`}" @click="qiehuan(1)"
v-show="activeindex<prop.imglist.length-1 || prop.xunhuan"
class="group absolute top-0 bottom-0 right-0 w-6 flex justify-center items-center bg-opacity-0 hover:bg-opacity-40 bg-gray-400 cursor-pointer active:bg-gray-500 active:text-blue-300">
<span class="text-white text-opacity-0 group-hover:text-opacity-100 iconfont icon-youjiantou2"></span>
</div>
</div>
<div class="h-1/5 w-full overflow-hidden">
<ul style="width:99999px;height: 100%;" :style="{transform:`translateX(${pianyix}px)`}" class="transition-all">
<li class="flex justify-center items-center h-full float-left relative" :style="{width:`${kuandu/4}px`}"
v-for="(item,index) in prop.imglist" :key="index" @mousedown="mouseputdown2">
<img :src="item" alt="缩略图" class="w-full h-full object-contain"
:class="[activeindex===index?'border border-blue-400':'']">
<div class="absolute inset-0 cursor-pointer bg-gray-500 hover:border hover:border-blue-400 select-none"
:class="[activeindex===index?'bg-opacity-0':'bg-opacity-20']" @click="dianji(index)"></div>
</li>
</ul>
</div>
</div>
</template>
<script setup>
import {computed, onMounted, ref, watch, defineProps} from "vue";
import {useStore} from "vuex"
import {useRoute, useRouter} from "vue-router"
const store = useStore()
const router = useRouter()
const route = useRoute()
// 传递进来的数据
const prop = defineProps({
// 播放的列表
imglist: {
type:Array,
},
// 是否开启循环
xunhuan: {
type: Boolean,
default: false,
},
// 是否开启自动播放
autoplay: {
type: Boolean,
default: false,
},
// 多久切换一次
autotime: {
type: Number,
default: 3,
}
})
// hover状态下不轮播
const lunbo = ref(true)
// 整个轮播组件
const lunboref = ref(null)
// 图片列表
// const prop.imglist = ref([img1, img2,])
// const prop.imglist = ref([img1, img2, img3, img4, img1, img2, img3, img4, img1, img2, img3, img4, img1, img2, img3, img4])
// 当前激活的序号
const activeindex = ref(0)
// 每个图片的宽度
const kuandu = ref(0)
// 鼠标拖动的偏移量
const pianyix = ref(0)
const yidongjuli = computed(() => {
return activeindex.value * kuandu.value
})
const dianji = (index) => {
activeindex.value = index
}
onMounted(() => {
kuandu.value = lunboref.value.offsetWidth
// 判断是否开启自动播放
if (prop.autoplay) {
setTimeout(() => {
playfunc(1)
}, prop.autotime * 1000)
}
})
// 边界计算
watch(pianyix, () => {
if (prop.imglist.length <= 4) {
pianyix.value = 0
} else if (pianyix.value > 0) {
pianyix.value = 0
} else if (pianyix.value < -(prop.imglist.length - 4) * kuandu.value / 4) {
pianyix.value = -(prop.imglist.length - 4) * kuandu.value / 4
}
})
const mouseputdown2 = (e) => {
let startX = e.clientX;
const zancun = pianyix.value
e.onmousemove = (e) => {
let endX = e.clientX;
pianyix.value = endX - startX + zancun;
}
e.onmouseup = () => {
e.onmousemove = null;
e.onmouseup = null;
}
}
// 点击前后箭头
const qiehuan = (index) => {
activeindex.value = activeindex.value + index
if (prop.xunhuan) {
// 开启循环
if (activeindex.value < 0) {
activeindex.value = prop.imglist.length
} else if (activeindex.value > prop.imglist.length - 1) {
activeindex.value = 0
}
} else {
// 没开循环
if (activeindex.value < 0) {
activeindex.value = 0
} else if (activeindex.value > prop.imglist.length - 1) {
activeindex.value = prop.imglist.length - 1
}
}
const index2 = Math.floor(activeindex.value / 4)
pianyix.value = -index2 * kuandu.value
}
// 自动播放
const playfunc = (canshu) => {
let index = canshu
if (!prop.xunhuan) {
if (activeindex.value <= 0) {
index = 1
} else if (activeindex.value >= prop.imglist.length - 1) {
index = -1
}
}
if(lunbo.value){
qiehuan(index)
}
setTimeout(() => {
playfunc(index)
}, prop.autotime * 1000)
}
// 鼠标移入组件范围内时,轮播停止
const zanting=(status)=>{
lunbo.value = status
}
</script>
<style scoped>
</style>
本文展示了如何使用Vue.js实现一个轮播图组件,包括基本的图片切换功能,并逐步增加了循环播放、鼠标悬停暂停、手动拖动和点击缩略图切换等功能。代码中详细注释了各个部分的作用,是Vue.js前端开发的一个实践案例。
3864





