Vu案例:图片轮播图

轮播图应该是在学编程的时候经常遇到的组件,在我看来一个轮播图的好坏在于代码是否简洁易懂,滑动的时候是否流畅,不卡顿,这样才算是一个好的轮播图。

最近也写了一个,直接上图看效果:

效果图

点击左右的两个箭头按钮可以来回切换图片,下方的小圆点对应着图片的位置,处于哪张图片,哪个小圆点就会变成长条状的。

实现间隔3秒切换一下的效果,我用的是一个定时器setInterval,在渲染完页面后就会隔3秒执行一次next函数。

next() {
            this.translateX++
            this.tsion = true
            if (this.translateX > this.src.length - 1) {
                setTimeout(() => {
                    this.tsion = false
                    this.translateX = 0
                }, 500)
            }
        }
    },
    mounted() {
        setInterval(()=>{
            this.next()
        },3000)
    },

如何做到不卡顿或是在最后一张的时候回去和第一张衔接呢?

我的处理方法是在第一张图片的前面插入最后一张图片,在最后一张图片插入第一张图片,这样等到了最后一张图片的时候,再点击向下就会跳到第一张图片,当js检测移动到超出data里src属性的图片路径的行为时,就会关闭transition过渡属性,然后跳转到data里src属性的第一张图片这里,然后在循环开始时把transition过渡属性加回去。

<div class="show-box" :style="{'transform':'translateX('+translate+'px)','transition':tsion?'all 0.5s':'none'}">
                    <img src="./images/8.jpg" alt="">
                    <img v-for='(item,index) in src' :src="item" alt="">
                    <img src="./images/1.jpg" alt="">
 </div>
// 上一张
        last() {
            this.translateX--
            this.tsion = true
            if (this.translateX < 0) {
                setTimeout(() => {
                    this.tsion = false
                    this.translateX = this.src.length - 1
                }, 500)
            }
        },
        // 下一张
        next() {
            this.translateX++
            this.tsion = true
            if (this.translateX > this.src.length - 1) {
                setTimeout(() => {
                    this.tsion = false
                    this.translateX = 0
                }, 500)
            }
        },

这是全部的代码:

<!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>图片轮播图</title>
    <link rel="stylesheet" href="./css/index.css">
</head>

<body>
    <div id="app">
        <div class="big-box">
            <div class="img-box">
                <div class="show-box" :style="{'transform':'translateX('+translate+'px)','transition':tsion?'all 0.5s':'none'}">
                    <img src="./images/8.jpg" alt="">
                    <img v-for='(item,index) in src' :src="item" alt="">
                    <img src="./images/1.jpg" alt="">
                </div>
            </div>
            <div class="arrowhead-box">
                <span @click='last'></span>
                <span @click='next'></span>
            </div>
            <div class="swiper-box" ref="swiper">
                <span v-for='(item,index) in src' @click='swiper(index)'></span>
            </div>
        </div>
    </div>
    <script src="../../js/vue.js"></script>
    <script src="./js/index.js"></script>
</body>

</html>
body {
    margin: 0;
    padding: 0;
    background-image: linear-gradient(to top, #37ecba 0%, #72afd3 100%);
}

span {
    margin: 0;
    padding: 0;
}

.big-box {
    width: 650px;
    height: 400px;
    background-color: #999;
    margin: 100px auto;
    position: relative;
    box-shadow: 0 0 3pc rgba(0, 0, 0, 0.4);
}

.img-box {
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.show-box {
    display: flex;
    height: 100%;
    width: 100%;
    transition: all 0.5s;
}

.show-box img {
    float: left;
    min-width: 650px;
    min-height: 400px;
}


.arrowhead-box {
    position: absolute;
    top: 40%;
    float: left;
    width: 100%;
    height: 50px;
}

.arrowhead-box span {
    float: left;
    display: block;
    width: 60px;
    height: 60px;
    border-radius: 50px;
    background:url('../images/last.png') no-repeat;
    background-color: rgba(0, 0, 0, 0.4);
    background-position: 6px 14px;
    cursor: pointer;
    opacity: 0.5;
}

.arrowhead-box span:nth-child(2) {
    float: right;
    transform:rotate(180deg);
}

.arrowhead-box span:hover {
    opacity: 1;
}

.swiper-box {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.swiper-box span {
    float: left;
    width: 12px;
    height: 12px;
    background-color: white;
    border-radius: 50px;
    margin-left: 10px;
    cursor: pointer;
    transition: all 0.5s ease-out;
}

.swiper-box span:nth-child(1) {
    width: 100px;
}

Vue.config.productionTip = false

new Vue({
    el: '#app',
    data: {
        src: ['./images/1.jpg', './images/2.jpg', './images/3.jpg', './images/4.jpg',
            './images/5.jpg', './images/6.jpg', './images/7.jpg', './images/8.jpg'
        ],
        translateX: 0,
        tsion: true
    },
    methods: {
        // 上一张
        last() {
            this.translateX--
            this.tsion = true
            if (this.translateX < 0) {
                setTimeout(() => {
                    this.tsion = false
                    this.translateX = this.src.length - 1
                }, 500)
            }
        },
        // 下一张
        next() {
            this.translateX++
            this.tsion = true
            if (this.translateX > this.src.length - 1) {
                setTimeout(() => {
                    this.tsion = false
                    this.translateX = 0
                }, 500)
            }
        },
        swiper(i){
            this.translateX = i
        }
    },
    mounted() {
        setInterval(()=>{
            this.next()
        },3000)
    },
    computed: {
        translate() {
            return -(this.translateX + 1) * 650
        }
    },
    watch: {
        translateX: {
            handler(val) {
                let a = this.$refs.swiper.querySelectorAll('span')
                a.forEach(element => {
                    element.style.width = '12px'
                });

                if (this.translateX < 0) {
                    val = this.src.length - 1
                }
                if (this.translateX > this.src.length - 1) {
                    val = 0
                }
                a[val].style.width = '100px'
            },
        }
    }
})

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):