Vue.js 文本行滚动

1.前言

  • 文本行滚动组件,效果如图

2.封装思路

  • 封装一个组件,接收一个数组,每个数组元素就是一个段文本
  • 组件使用httpVueLoader进行封装加载
  • 使用css位移,配合过渡效果才展示动画
  • 滚动逻辑类似与轮播图,需要将第一行文本复制一份到最后,当已经滚动到最后时,则关闭动画,重置到第一行
  • 使用定时器动态调整位移大小
  • 位移大小使用百分比,因为使用像素值有小数点误差
  • 接收5个参数:
参数名称 默认值 说明
data [] 文本行数组
size normal 字体大小 normal, small, size
color #333 字体颜色
interval 10 轮播间隔,单位/秒
loop true 是否开启自动循环

3.代码

<template>
    <div :class="['text-row-scroll-wrap','size-'+size]" :style="{'height': boxHeight,'color':color}">
        <div class="text-row-scroll-box" :style="{'transform': `translateY(${setTop})`}"
            :class="{'closeAnimation': closeAnimation}">
            <div class="ep-scroll-row" v-for="(item,i) in rowList" :key="i">{{item}}</div>
        </div>
        <div v-if="data.length==0" style="color: #999;text-align: center;">暂无数据</div>
    </div>
</template>

<script>
    module.exports = {
        data() {
            return {
                active_index: 0,//当前展示的下标位置
                timer: null,//定时器id
                closeAnimation: false,//关闭动画效果  当切换到最后一行,且动画完成时,需要回退到
            }
        },
        props: {
            size: {
                type: String,
                default: "normal"
            },
            color: {
                type: String,
                default: "#333"
            },
            data: {
                type: Array,
                default: function () {
                    return []
                }
            },
            interval: {
                type: Number,
                default: 10
            },
            loop:{
                type:Boolean,
                default: true
            }
        },
        watch:{
            data:{
                deep:true,
                handler:function(newVal,oldVal){
                    if(newVal.length > 0){
                        //初始化
                        this.init()
                    }else{
                        //关闭轮播定时器
                        clearInterval(this.timer)
                        this.active_index = 0
                    }
                },
                immediate:true
            }
        },
        mounted() {

        },
        methods:{
            //初始化轮播
            init() {
                clearInterval(this.timer)
                this.active_index = 0
                //如果列表为空 则什么也不做
                if(this.data.length==0){
                    return
                }
                //如果未开启循环 且长度==1,也无需开启定时器
                if(this.data.length == 0 && !this.loop){
                    return
                }
                //开启定时器
                this.timer = setInterval(() => {
                    //开启动画
                    if (this.closeAnimation) {
                        this.closeAnimation = false
                    }

                    //行下标++
                    this.active_index++

                    //等待动画结束
                    setTimeout(() => {
                        //判断是否开启了循环
                        if(!this.loop){
                            //判断是否已经到了最后一个
                            if(this.active_index >= this.data.length-1){
                                console.log('已经到了最后一个 关闭轮播')
                                //关闭循环定时器
                                clearInterval(this.timer)
                            }
                        }else{
                            //是否到了最后一个(伪)
                            if (this.active_index >= this.rowList.length - 1) {
                                //关闭动画
                                this.closeAnimation = true
                                //等待关闭动画的渲染
                                this.$nextTick(function () {
                                    console.log('关闭动画的渲染')
                                    console.log('重置到第一行')
                                    //重置到第一行
                                    this.active_index = 0
                                })

                            }
                        }
                    }, 0.5 * 1000 + 2)
                }, this.interval * 1000)
            }
        },
        computed: {
            //将第一行复制一份到最后,类似于轮播图
            rowList() {
                if (this.data.length == 0) {
                    return []
                } else {
                    var rowList = [...this.data]
                    rowList.push(this.data[0])
                    return rowList
                }
            },
            //最外层容器的高度应该是刚好一行的高度,每行高度由字体大小和padding决定
            //当前三种模式 ,调试后记录其每种模式下的高度
            //每个模式下 最外层容器的高度
            boxHeight() {
                if (this.size == 'small') {
                    return '24px'
                } else if (this.size == 'mini') {
                    return '20px'
                } else {
                    return '29px'
                }
            },
            //当前位移
            setTop() {
                var top = 0
                //如果没数据 则返回0
                if (this.data.length != 0) {
                    top = (this.active_index / this.rowList.length * 100 * -1) + '%'
                    return top
                }
            },
        }
    }
</script>

<style scoped>
    .text-row-scroll-wrap {
        overflow: hidden;
    }

    .text-row-scroll-box {
        transition: all 0.5s;
    }

    .text-row-scroll-box.closeAnimation {
        transition: none;
    }

    .size-normal .ep-scroll-row {
        font-size: 16px;
        padding: 3px;
    }

    .size-small .ep-scroll-row {
        font-size: 14px;
        padding: 2px;
    }

    .size-mini .ep-scroll-row {
        font-size: 12px;
        padding: 1px;
    }
</style>

4.基本使用

  • 组件引入与注册
new Vue({
        el:"#app",
        data(){
            return {
                row_list:[
                    "日检:完成比例:0% / 未完成比例:100% / 点检异常比例:0%",
                    "周检:完成比例:1.2% / 未完成比例:98.8% / 点检异常比例:0%"
                ]
            }
        },
        components:{
            "text-row-scroll": httpVueLoader('./text-row-scroll.vue?time='+new Date().getTime())
        },
    })
  • 基本使用
<text-row-scroll :data="row_list"></text-row-scroll>
posted @ 2022-04-24 17:10  ---空白---  阅读(276)  评论(0编辑  收藏  举报