首页 > 编程 > JavaScript > 正文

详解vue 自定义marquee无缝滚动组件

2019-11-19 11:50:55
字体:
来源:转载
供稿:网友

先上效果图:

(1) 看起来可能有点卡顿,但是实际上页面上看起来挺顺畅的。

(2) 思路就是获取每一个列表的宽度,设置定时器移动列表,当移动的距离达到一个列表的宽度的时候,把这个距离放到数组的最后。这样就能达成无缝循环滚动了。

 大致的情况就是下面这样:

 

接下来就是代码的实现:

index.vue 引入组件

<template> <div>  <marqueeLeft :send-val='send'></marqueeLeft > </div></template><script> import marqueeLeft from '../components/marquee' export default {  data:function(){   return{    send:[{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: "杨先生"}]   }  },  components:{ marqueeLeft }, }</script>

marquee.vue 组件页面

<template> <div class="my-outbox">  <div class="my-inbox" ref='box'>   <div class="my-list" v-for="(item,index) in sendVal" :key='index' ref='list'>    {{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 {    nowTime:null,//定时器标识    disArr:[],//每一个内容的宽度   }  },   mounted:function(){   var that = this;   var item = this.$refs.list;    var len = this.sendVal.length;   var arr = [];   var margin = this.getMargin(item[0]) //因为设置的margin值一样,所以取第一个就行。   for(var i = 0;i < len;i++){    arr.push(item[i].clientWidth + margin)//把宽度和 margin 加起来就是每一个元素需要移动的距离   }   this.disArr = arr;   this.moveLeft();  },  beforeDestroy:function(){   clearInterval(this.nowTime);//页面关闭清除定时器   this.nowTime = null;//清除定时器标识  },  methods:{   //获取margin属性   getMargin:function(obj){    var marg = window.getComputedStyle(obj,null)['margin-right'];    marg = marg.replace('px','')    return Number(marg) //强制转化成数字   },   //移动的方法   moveLeft:function(){    var outbox = this.$refs.box;    var that=this;    var startDis = 0;//初始位置    this.nowTime = setInterval(function(){     startDis -= 0.5;     if(Math.abs(startDis) > Math.abs(that.disArr[0])){      that.disArr.push(that.disArr.shift())//每次移动完一个元素的距离,就把这个元素的宽度      that.sendVal.push(that.sendVal.shift())//每次移动完一个元素的距离,就把列表数据的第一项放到最后一项      startDis = 0;     }     outbox.style = 'transform: translateX('+ startDis +'px)'; //每次都让盒子移动指定的距离    },1000/60)   }  } }</script><style lang="less" scoped> .my-outbox{  color: #D7BC8D;  overflow: hidden;  height: 35px;  background: #422b02;  .my-inbox{   white-space: nowrap;   .my-list{    margin-right: 25px;    display: inline-block;    font-size: 13px;    height: 35px;    line-height: 35px;    .my-uname{     color: #FF8900;    }   }  } }</style>

(1) 添加一个获取margin的方法,是为了保证如果是使用 rem em 等单位时,margin值不会出现偏差的情况

(2) 如果引入组件的页面中,send-val的值是异步请求的。那么,在marquee.vue组件页面,多数情况会获取不了 refs 。这时候我自己的解决方法是:

<marqueeLeft :send-val='send' v-if='send'></marqueeLeft >

 表示只有当 send 不为空的时候才渲染该组件,不过这种情况会导致如果 请求响应太慢,组件会一直渲染不出来,就可能会影响布局。

(3) 如果不想每次都去设置transform,那么可以把transform放到该元素上,然后修改data中的数据就行了,比如:

<div class="my-inbox" :style='transform: translateX('+ cssStyle +'px)'></div>
// 然后在 js 中把 每次移动的值,赋值给cssStyle就行了。不过我感觉这种没什么区别

 如果想实现,上下无缝滚动,这种效果。思路和左右无缝滚动一样,基本上只需要把 transform 改成 Y轴移动 ,每个列表的宽度改成高度就行了。

不清楚这种方式实现是否会有什么问题,FPS一直保持在 接近60左右。暂时没发现什么缺点。。。

以上所述是小编给大家介绍的vue自定义marquee无缝滚动组件详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表