基于vue原生js实现轮播图,中间大两边小,循环轮播,突破element中的走马灯最多放三个的限制。以显示轮播5个为例,可以添加多个图片进行循环。显示多少个由自己决定

实现效果图:

直接上代码

<template>
    <div>
        <!-- 低于四张 -->
        <div class="oneBox" v-if="!isShow">
            <div v-for="(item,index) in propsData" :key="index" class="oneItemBox" @click="itemImgClick(item,index)"><img :src="item.imgUrl"></div>
        </div>
        <!-- 超过五张以上或者只有三张显示 -->
        <div class="box" v-else>
            <div v-for="(item,index) in imgList" :key="index" class="itemBox" @click="itemImgClick(item,index)"><img :src="item.imgUrl"></div>
            <div class="left" @click="left">减</div>
            <div class="right" @click="right">加</div>
        </div>
    </div>
</template>

<script name="LBBox" setup>
import banner1 from '@/assets/images/banner1.png'
import banner2 from '@/assets/images/banner2.png'
import banner3 from '@/assets/images/banner3.png'
import banner4 from '@/assets/images/taitan1.jpg'
import banner5 from '@/assets/images/taitan2.jpg'
import banner6 from '@/assets/images/s8.jpg'
import banner7 from '@/assets/images/s1.jpg'
import test1 from '@/assets/images/s2.png'
import test2 from '@/assets/images/s3.jpg'
import test3 from '@/assets/images/s4.jpg'
import test4 from '@/assets/images/s4.png'
import test5 from '@/assets/images/s8.jpg'
import test6 from '@/assets/images/s7.jpg'
import {nextTick} from "vue";

let props = defineProps({
    propsData:{
        type:Array,
        default: [
            {imgUrl: test1},
            {imgUrl: test2},
            {imgUrl: test3},
            {imgUrl: test4},
            {imgUrl: test5},
            {imgUrl: test6},
            {imgUrl: banner1},
            {imgUrl: banner2},
            {imgUrl: banner3},
            {imgUrl: banner4},
            {imgUrl: banner5},
            {imgUrl: banner6},
            {imgUrl: banner7},
        ]
    }
})

let state = reactive({
    imgList: []
})
const { imgList } = toRefs(state)
let itemBox = ref(null) // 存放所有图片dom

function right() {
    // 点一次加号,就循环让当前数组的索引加一,循环后强制刷新数据,让数据更新,达到视图更新
    let zero = state.imgList[0] //保存第一个,以免进入循环第一个和最后一个重复
    for (let i = 0; i < state.imgList.length; i++) {
        if (i == state.imgList.length - 1) {
            state.imgList[i] = zero
        } else {
            state.imgList[i] = state.imgList[i + 1]
        }
    }
    updateData(props.propsData,null)
    cuttentShadowStyle()
}

function left() {
    // 点一次减号,就循环让当前数组的索引减一,循环后强制刷新数据,让数据更新,达到视图更新
    let last = state.imgList[state.imgList.length - 1] //保存最后一个,以免进入循环第一个和最后一个重复
    for (let i = state.imgList.length - 1; i >= 0; i--) {
        if (i == 0) {
            state.imgList[i] = last
        } else {
            state.imgList[i] = state.imgList[i - 1]
        }
    }
    cuttentShadowStyle()
}

function setStyle() {
    // 一开始就根据数据的奇偶数来确定中位数,中位数一般都是奇数,如果数组的length为5,则中位数为2
    // 基于中位数,给每个元素设置相应的类,类控制元素的大小
    let Axis = null
    itemBox.value = document.getElementsByClassName('itemBox')
    Axis = parseInt(state.imgList.length / 2) //拿到中间数
    itemBox.value[Axis].className = "current itemBox";
    if (Axis - 1 >= 0) {
        itemBox.value[Axis - 1].className = "current1 itemBox";
    }
    if (Axis - 2 >= 0) { //左边第一个
        itemBox.value[Axis - 2].className = "current2 itemBox";
    }
    if (Axis + 1 <= state.imgList.length - 1) {
        itemBox.value[Axis + 1].className = "current1 itemBox";
    }
    if (Axis + 2 <= state.imgList.length - 1) { //右边第一个
        itemBox.value[Axis + 2].className = "current2 itemBox";
    }
}
let timer = ref(null)
function tumble(){
    if (timer.value){
        window.clearInterval(timer.value)
        timer.value = null
    }
    if (!timer.value){
        timer.value = window.setInterval(()=>{
            right()
        },3000)
    }
}

function itemImgClick(item,index){
    let Axis = parseInt(state.imgList.length / 2)
    if (index == Axis) return;
    switchPosition(index,Axis)
}

// 点击当前图片显示在中间,与中间的图片进行切换位置
function switchPosition(currentIndex,axisIndex){
    let temp = state.imgList[currentIndex]
    state.imgList[currentIndex] = state.imgList[axisIndex]
    state.imgList[axisIndex] = temp
    cuttentShadowStyle()  // 让中间样式高亮
}
let shadowTimer = ref('')
function cuttentShadowStyle(){
    window.clearTimeout(shadowTimer.value)
    let Axis = parseInt(state.imgList.length / 2)
    itemBox.value[Axis].style.boxShadow = `0px 0px 6px 10px #D3E7FF`
    itemBox.value[Axis].style.borderRadius = `20px`
    itemBox.value[Axis].style.transform = `scale(1.02)`
    shadowTimer.value = window.setTimeout(()=>{
        itemBox.value[Axis].style.boxShadow = `0px 0px 0px 0px #D3E7FF`
        itemBox.value[Axis].style.borderRadius = `0px`
        itemBox.value[Axis].style.transform = `scale(1)`
    },500)
}

// 当图片数据大于5时,做处理  用于更新数据,每次跳转都执行一次
function updateData(data,isOne){
    // isOne是否是第一次执行此方法,用于初始化数据,只执行一次
    if (isOne){ // 只执行一次
        for (let i=0;i<data.length;i++){
            if (i<5){
                state.imgList.push(data[i])
            }
        }
    }
    if (props.propsData.length>cuttentCheckIndex.value){ //默认显示五个轮播 默认显示五个轮播,当数据超过5个时,从第五开始加入新的数据
        cuttentCheckIndex.value++ // 第五个开始切换
        if (cuttentCheckIndex.value==data.length){
            cuttentCheckIndex.value = 0
        }
        state.imgList.push(data[cuttentCheckIndex.value])
        state.imgList.shift()
    }
}

//初始化数据
let cuttentCheckIndex = ref(4) //默认显示五个,用于记录数据的更新
let isShow = ref(true)
function initData(){
    isShow.value = (props.propsData.length==3||props.propsData.length>=5);
    if (isShow.value){
        updateData(props.propsData,true)
        nextTick(() => {
            setStyle()
            tumble()
        })
    }
}

onMounted(() => {
    initData()
})
onUnmounted(()=>{ // 清除定时器
    window.clearInterval(timer.value)
    window.clearInterval(shadowTimer.value)
})
</script>

<style lang="scss" scoped>
.oneBox{
    width: 1840px;
    height: 530px;
    border: 1px solid blue;
    margin: 0 auto;
    display: flex;
    justify-content: space-around;
    align-items: center;
    padding-bottom: 75px;
    position: relative;
    .oneItemBox{
        width: 295px;
        height: 295px;
        border: 1px solid #11ff00;
        position: relative;
        overflow: hidden;
        img {
            max-width: 100%;
            max-height: 100%;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            margin: auto;
        }
    }
}
.box {
    width: 1840px;
    height: 530px;
    border: 1px solid red;
    margin: 0 auto;
    display: flex;
    justify-content: space-around;
    align-items: end;
    padding-bottom: 75px;
    position: relative;

    .itemBox{
        position: relative;
        transition: all 0.5s;
        img {
            max-width: 100%;
            max-height: 100%;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            margin: auto;
        }
        &:hover{
            border-radius: 20px;
            transform: scale(1.02);
        }
    }

    .left, .right {
        position: absolute;
        bottom: 20px;
        cursor: pointer;
    }

    .left {
        margin-right: 40px;
    }

    .right {
        margin-left: 40px;
    }
}

.current {
    width: 402px;
    height: 402px;
    border: 1px solid red;
}

.current1 {
    width: 295px;
    height: 295px;
    border: 1px solid #11ff00;
}

.current2 {
    width: 241px;
    height: 241px;
    border: 1px solid #0059ff;
}
</style>

实现思路

1、初始化的时候,给当前五个图片设置固定的样式(中间图片大,两边小)

2、点击两边某个图片要是显示在中间时,当前的图片位置与中间位置进行互换

3、点击右边小图标或者点击下一张时,每个图片当前位置下标加一,当加到下标超过数组数据长度时,下标重置0开始,循环(点击左边相反)

4、每换一次下标,最中间的图片都要放大,总之按照自己需求,添加变化样式

5、单数据超过5条时,每一次切换图片下标时,都更新数据,这里需要两个数组数据,一个数组(A)存放5个,用户页面的显示。另一个数组(B)数据则是当前一共有多少张图片。每一次下标更改,都要从B里面拿到一个数据放到A里面去刷新数据

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
实现Vue2中间大、两边小的轮播图可以通过以下步骤实现: 1. 首先,在Vue组件引入所需的轮播图组件库,例如swiper或vue-awesome-swiper库,然后在组件的data选项定义轮播图的数据和样式相关属性。 2. 在模板使用v-for指令遍历轮播图数据,生成轮播图的每一项。同时,可以使用v-bind指令绑定样式属性。 3. 对于轮播图中间大、两边小的效果,可以使用CSS的transform和z-index属性来实现添加样式类,设置中间大图的z-index属性较高,使用transform:scale()属性对中间大图进行缩放。 4. 根据实际需求,可以使用定时器或者Vue的watch属性来实现自动轮播功能。 5. 可以为轮播图添加上一页和下一页的按钮,通过点击触发事件更新轮播图的当前项。 示例代码如下: ```html <template> <div> <div class="swiper-container"> <div class="swiper-wrapper"> <div v-for="(item, index) in carouselData" :key="index" :class="{ 'carousel-item': true, 'center-item': activeIndex === index }" > <img :src="item.img" alt=""> </div> </div> <div class="swiper-button-prev" @click="prev"></div> <div class="swiper-button-next" @click="next"></div> </div> </div> </template> <script> import Swiper from 'swiper' export default { data() { return { carouselData: [ { img: 'img1.jpg' }, { img: 'img2.jpg' }, { img: 'img3.jpg' }, { img: 'img4.jpg' }, { img: 'img5.jpg' } ], activeIndex: 2 // 初始中间项索引 } }, mounted() { // 初始化Swiper实例 new Swiper('.swiper-container', { navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' } }) }, methods: { prev() { this.activeIndex = (this.activeIndex - 1 + this.carouselData.length) % this.carouselData.length }, next() { this.activeIndex = (this.activeIndex + 1) % this.carouselData.length } } } </script> <style> .carousel-item { display: flex; align-items: center; justify-content: center; position: relative; } .carousel-item img { width: 200px; height: 200px; object-fit: cover; } .center-item { transform: scale(1.2); z-index: 10; } .swiper-button-prev, .swiper-button-next { color: #000; font-size: 30px; cursor: pointer; } .swiper-button-prev { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); } .swiper-button-next { position: absolute; right: 10px; top: 50%; transform: translateY(-50%); } </style> ``` 以上代码实现了一个简单的Vue2轮播图组件,通过v-for遍历数据,并使用样式类控制中间大、两边小的效果。使用Swiper库进行轮播图的初始化和导航按钮功能。中间项通过activeIndex属性控制,点击上一页和下一页按钮会更新activeIndex的值,从而实现轮播切换。 该实现方式可以根据具体需求进行自定义调整和扩展,例如增加切换动画效果、自定义轮播速度等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草样的年华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值