文档章节

vue 自定义marquee无缝滚动组件

o
 osc_gu9d45li
发布于 2019/04/09 11:08
字数 1175
阅读 26
收藏 0

精选30+云产品,助力企业轻松上云!>>>

今天介绍一下,上下,左右无缝滚动的公告栏信息组件的开发。

首先上效果:

看起来有点卡顿,实际上还是挺顺畅的。。。

 

代码:

左右滚动的组件:marqueeX

<template>
    <div class="my-outbox">
        <div class="my-inbox" ref='box'>
            <div class="my-list" v-for="(item,index) in sendVal" :key='index'>
                {{item.place}}<span class="my-uname">{{item.name}}</span>刚刚购买了产品
            </div>
            <div class="my-list" v-for="(item,index) in sendVal" :key='(index+1)*100'>
                {{item.place}}<span class="my-uname">{{item.name}}</span>刚刚购买了产品
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name:'my-marquee-left',
        props:{        
            sendVal:Array
        },
        data() {
            return {}
        }, 
        mounted:function(){
            var that = this;
            var target = this.$refs.box; 
            var initLeft = 0;
            setInterval(function(){
                initLeft ++;
                if(initLeft >= target.offsetWidth / 2 ){
                    initLeft = 0;
                }
                target.style = 'transform: translateX(-'+ initLeft +'px)';                
            },16)
        }
    }
</script>

<style lang="less" scoped>
    .my-outbox{
        color: #D7BC8D;
        overflow: hidden;
        height: 35px;
        background: #422b02;
        position: relative;
        .my-inbox{
            white-space: nowrap;
            position: absolute;
            font-size: 0;
            .my-list{
                margin-right: 25px;
                display: inline-block;
                font-size: 13px;
                height: 35px;
                line-height: 35px;
                .my-uname{
                    color: #FF8900;
                }
            }
        }
    }
</style>

   

上线滚动的组件:marqueeY

<template>
    <div class="my-outbox" ref='outbox'>
        <div class="my-inbox" ref='movebox'>
            <div class="my-listbox" v-for="(item,index) in sendVal" :key='index'>
                <div class="my-title">
                    {{item.name}}<text class="my-utel">{{item.mobile}}</text>
                    <text class="my-addr">{{item.place}}</text>
                </div>
                <div class="my-content">{{item.content}}</div>
            </div>
            <div class="my-listbox" v-for="(item,index) in sendVal" :key='(index+1)*100' v-if='isShow'>
                <div class="my-title">
                    {{item.name}}<text class="my-utel">{{item.mobile}}</text>
                    <text class="my-addr">{{item.place}}</text>
                </div>
                <div class="my-content">{{item.content}}</div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name:'my-marquee-top',
        props:{        
            sendVal:Array
        },
        data() {
            return {
                isShow:true
            }
        }, 
        mounted:function(){
            var moveTarget = this.$refs.movebox;
            var outbox = this.$refs.outbox;
            if(outbox.offsetHeight > (moveTarget.offsetHeight /2)){
                this.isShow = false;
                return
            }
            var initTop = 0;
            setInterval(function(){
                initTop ++;
                if(initTop >= moveTarget.offsetHeight / 2 ){
                    initTop = 0;
                }
                moveTarget.style = 'transform: translateY(-'+ initTop +'px)';
              
            },16)
        },
    }
</script>

<style lang="less" scoped>
    .my-outbox{
        color: #FEE7B1;
        height:300px;
        margin: 20px;
        background: #FEE7B1;
        overflow: hidden;
        border: 2px solid #C46302;
        .my-inbox{
            margin: 0 45px;
            .my-listbox{
                padding: 20px 0;
                font-size: 18px;
                border-bottom: 1px solid #C7BEB1;
                .my-title{
                    color: #DB7000;
                    margin-bottom: 10px;
                    clear: both;
                    overflow:hidden;
                    .my-utel{
                        font-size: 16px;
                        margin-left: 20px;
                    }
                    .my-addr{
                        font-size: 16px;
                        float: right;
                    }
                }
                .my-content{
                    text-align: justify;
                    word-break: break-all;
                    font-size: 14px;
                    color: #53565D;
                }
            }
        }
    }
</style>

   

使用组件:

<marqueeX send-val='data1'  v-if='data1' />
<marqueeY send-val='data2'  v-if='data2' />

 

测试数据:

data: {
    "msg": [{
        "place": "来自烟台市的",
        "name": "许先生"
    }, {
        "place": "来自东莞市的",
        "name": "曹先生"
    }, {
        "place": "来自郑州市的",
        "name": "邹女士"
    }, {
        "place": "来自海口市的",
        "name": "戚先生"
    }, {
        "place": "来自南京市的",
        "name": "陈先生"
    }, {
        "place": "来自金华市的",
        "name": "吴先生"
    }, {
        "place": "来自泉州市的",
        "name": "卫先生"
    }, {
        "place": "来自哈尔滨市的",
        "name": "钱先生"
    }, {
        "place": "来自成都市的",
        "name": "尤先生"
    }, {
        "place": "来自惠州市的",
        "name": "张先生"
    }, {
        "place": "来自宁波市的",
        "name": "喻女士"
    }, {
        "place": "来自石家庄市的",
        "name": "吕先生"
    }, {
        "place": "来自大连市的",
        "name": "蒋女士"
    }, {
        "place": "来自南昌市的",
        "name": "赵先生"
    }, {
        "place": "来自珠海市的",
        "name": "黄女士"
    }, {
        "place": "来自天津市的",
        "name": "金先生"
    }, {
        "place": "来自绍兴市的",
        "name": "韩先生"
    }, {
        "place": "来自西安市的",
        "name": "褚先生"
    }, {
        "place": "来自苏州市的",
        "name": "姜先生"
    }, {
        "place": "来自南宁市的",
        "name": "陈女士"
    }, {
        "place": "来自沈阳市的",
        "name": "华先生"
    }],
    "comment": [{
        "name": "冯先生",
        "mobile": "170****8441",
        "place": "重庆",
        "content": "从小跟着奶奶长大,她信了一辈子的佛了,我从以前的出了事都会拜佛到今天的每日一拜,已经是一种信仰了,只要多积德行善,下一世咱还是条好汉。"
    }, {
        "name": "姜女士",
        "mobile": "180****2717",
        "place": "包头",
        "content": "第三世的我是只萌萌的小白兔,果然兔兔那么可爱,千万不能吃兔兔。╮(๑•́ ₃•̀๑)╭"
    }, {
        "name": "曹女士",
        "mobile": "171****5347",
        "place": "辽阳",
        "content": "稀里糊涂点进来,还以为跟三生三世十里桃花一个性质的电视剧呢0.0,不过这个真的好准,我小时候和青年时代算的就跟结果说的一模一样。"
    }, {
        "name": "魏先生",
        "mobile": "151****3555",
        "place": "无锡",
        "content": "以前总听说因果循环报应不爽,但一直不明白是啥意思,看了我前四世的身份后我终于明白了,真实,简直太真实了。"
    }]
}
View Code

  

(1) 上下滚动和左右滚动的 js 代码 基本没什么区别,只是我在上下滚动的代码中加入了判断如果数据太短就不显示克隆的内容和不执行滚动事件

(2) 大致的思路就是让装内容的盒子一直滚动至内容底部,然后在大于或者等于这个位置的时候,就把当前滚动的位置 置为0,相当于初始化。

(3) 引用组件的时候,使用 v-if  是因为我用setTimeout模拟后台延时返回数据,然后在数据没拿到的时候就不显示该组件。

(4) 因为有克隆的内容部分,所以那部分也需要设置key,一定要注意同一组件中,key不要搞成一样。

 


更新:

使用 requestAnimationFrame 来实现一帧一帧的绘制移动的距离:

只更新 marqueeX 的实现方法,marqueeY实现方式是一样的:

export default {
        name:'my-marquee-left',
        props:{        
            sendVal:Array
        },
        data() {
            return {
                initLeft:0,
                animateTarget:null
            }
        }, 
        mounted:function(){
            this.animateTarget = this.$refs.box;
            requestAnimationFrame(this.animateFn);
        },
        methods:{
            animateFn(){
                this.initLeft++;
                if (this.initLeft >= this.animateTarget.offsetWidth / 2) {
                    this.initLeft = 0;
                }
                this.animateTarget.style = "transform: translateX(-" + this.initLeft + "px)";
                requestAnimationFrame(this.animateFn)
       }
        }
}   

  

 

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
基于VUE,VUX组件开发的网易新闻页面搭建过程

根据妙味课堂上的一个教程练习总结,供自己复习用 一、功能介绍 一个网易新闻客户端的浏览页面,通过网易新闻的api接口实时获取新闻数据,用vux搭建样式框架,以轮播图,文字滚动,图文列表等...

osc_sraynp8f
2018/04/02
1
0
移动端&PC端 vue-concise-slider 轮播组件

vue-concise-slider,一个简单的滑动组件,配置简单,支持自适应/全屏+按钮+分页,同时兼容移动端和PC端 特点 简单配置 轻量 (~35kB gzipped) 多种滑动样式 目前已实现 全屏自适应 移动端兼容 垂...

osc_2snvc4af
2019/09/30
13
0
legend2---开发日志11(如何提高终极开发效率)

legend2---开发日志11(如何提高终极开发效率) 一、总结 一句话总结: 实在没必要摸索着做,直接学了做,用专门的东西来做,岂不是要省时省事很多。岂不美哉。 1、vue中的滚动字幕动画效果如...

osc_3dayg3dw
2019/04/22
1
0
文字无缝滚动效果,鼠标移入时暂停

    项目背景:基于vue的项目     昨天需要写一个效果,需要将数据自动轮播,然后鼠标移入时,轮播暂停。就像文字走马灯的效果类似。走马灯的效果可以使用css实现。     这里说一...

osc_hu8sgifq
2019/10/12
25
0
vue-gemini-scrollbar(vue组件-自定义滚动条)

介绍 无需配置横向或纵向滚动,自定义滚动条完全按照原生的方式去显示(也就是如果区域存在纵向滚动条,使用它后将替换纵向滚动条)。正因为如此,请不要使用::-webkit-scrollbar来修饰原生滚...

osc_ipgs1x3t
2018/05/15
15
0

没有更多内容

加载失败,请刷新页面

加载更多

SpringCloud- 第六篇 Hystrix参数配置(三)

1:概述 Hystrix使用Archaius作为配置属性的默认实现。官方配置文档: https://github.com/Netflix/Hystrix/wiki/Configuration 每个属性有四个优先级,依次增大: 1:代码的全局默认值 2:动...

osc_7z601p6x
10分钟前
0
0
SpringBoot2 整合JTA组件,多数据源事务管理

本文源码:GitHub·点这里 || GitEE·点这里 一、JTA组件简介 1、JTA基本概念 JTA即Java-Transaction-API,JTA允许应用程序执行分布式事务处理,即在两个或多个网络计算机资源上访问并且更新...

osc_sju4uxml
11分钟前
0
0
Springboot + Vue + shiro 实现前后端分离、权限控制

本文总结自实习中对项目的重构。原先项目采用Springboot+freemarker模版,开发过程中觉得前端逻辑写的实在恶心,后端Controller层还必须返回Freemarker模版的ModelAndView,逐渐有了前后端分...

osc_lbt7zo1x
13分钟前
0
0
docker-compose部署配置jenkins

docker-compose部署配置jenkins 一、docker-compose文件 version: '3.1'services: jenkins: image: jenkins/jenkins:lts volumes: - /data/jenkins/:/var/jenkins_home ......

osc_4p2c0ecc
15分钟前
3
0
第五周

1、查找/etc目录下大于1M且类型为普通文件的所有文件 2、打包/etc/目录下面所有conf结尾的文件,压缩包名称为当天的时间,并拷贝到/usr/local/src目录备份。 3、利用sed 取出ifconfig命令中本...

osc_hxm151is
16分钟前
20
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部