vue文本滚动组件
青柠咖啡 人气:0看了好多网上的文本组件,发现好多都有这样那样的问题;特别是滚动的时候失真的感觉,今天整合了文本滚动的方式用CSS的
animation写出一套组件;VUE项目直接用。感觉有用的朋友关注下
效果图,gif制作有卡顿,实际效果我是没发现卡顿
1. 横向文本滚动
/* 横向文本滚动 */ <template> <div class="scroll-inner" ref="scrollInner"> <div class="scroll-wrap" ref="scrollWrap" :style="wrapStyle"> <slot></slot> </div> <div class="scroll-wrap"> <slot></slot> </div> <!-- <ul class="scroll-wrap"> <li v-for="item in runArr" :key="item"> {{item}} </li> </ul> --> </div> </template> <script> /** * speed 1 速度 * * 格式要求类名scroll、ul、li格式勿变,li内排版可自定义 * <horizontal-text-scroll> <ul class="scroll"> <li v-for="item in arr2" :key="item"> {{item}} </li> </ul> </horizontal-text-scroll> */ export default { data () { return { runArr: [], wrapWidth: 0, innerWidth: 0, retry: 0, tim: Math.floor(Math.random() * (99999 - 10000) + 10000) } }, props: { // 滚动速度 speed: { type: Number, default: 1 } }, computed: { wrapStyle () { const s = this.wrapWidth / (30 + this.speed * 5) return { animationDuration: `${s}s`, animationIterationCount: 'infinite', animationName: `move${this.tim}`, animationTimingFunction: 'linear' } } }, mounted () { this.getWrapWidth() }, methods: { getWrapWidth () { this.$nextTick(() => { this.wrapWidth = this.$refs.scrollWrap.clientWidth this.innerWidth = this.$refs.scrollInner.clientWidth console.log(this.wrapWidth) console.log(this.innerWidth) if (!this.wrapWidth && this.retry < 3) { this.getWrapWidth() this.retry++ return } else if (!this.wrapWidth && this.retry === 3){ console.error('获取元素高度失败或高度为0') return } this.createStyle() }) }, createStyle () { const style = ` @keyframes move${this.tim} { from {margin-left: 0;} to {margin-left: -${this.wrapWidth}px;} } ` let el = document.createElement('style') el.innerHTML = style document.head.appendChild(el) } } } </script> <style scoped> *{ padding: 0; margin: 0; } .scroll-inner { width: 100%; white-space: nowrap; overflow: hidden; height: 100%; } .scroll-wrap { box-sizing: border-box; min-width: 100%; height: 100%; font-size: 0; white-space: nowrap; display: inline-block; } .scroll-wrap li { height: 30px; line-height: 30px; list-style: none; display: inline-block; font-size: 16px; margin-right: 20px; } .scroll { display: inline-block; } </style>
2. 断点滚动
/* 间歇滚动 */ <template> <div class="scroll-inner"> <ul class="scroll-wrap" :style="scrollWrapClass" v-bind="$attrs"> <li v-for="(item, index) in runArr" :key="index"> {{item}} </li> </ul> </div> </template> <script> /** * 根据inner标签的高度可控制单行多行 * * scrollArr 滚动数组 * time 2000 滚动间隔 * animationTime 500 滚动动画时间 * distance 30 滚动距离 * */ export default { data () { return { isRun: false, runArr: [] } }, computed: { scrollWrapClass () { let c if (this.isRun) { c = { transition: `margin ${this.animationTime / 1000}s`, marginTop: `-${this.distance}` } } else { c = { transition: '', marginTop: '' } } return c } }, props: { // 滚动数组 scrollArr: { required: true }, // 滚动间隔 time: { type: Number, default: 2000 }, // 滚动动画时间 animationTime: { type: Number, default: 500 }, // 滚动距离 distance: { type: String, default: '30px' } }, mounted() { this.runArr = JSON.parse(JSON.stringify(this.scrollArr )) document.addEventListener('visibilitychange', this.handleVisiable) this.startScroll() }, methods: { startScroll () { this.interval = setInterval (() => { this.isRun = true this.runArr.push(this.runArr[0]) this.timeOut = setTimeout (() => { this.runArr.shift() this.isRun = false }, this.animationTime) }, this.time) }, handleVisiable (e) { if (e.target.visibilityState === 'visible') { // 要执行的方法 this.startScroll() } else { this.interval && clearInterval(this.interval) } } }, destroyed () { this.interval && clearInterval(this.interval) this.timeOut && clearTimeout(this.timeOut) } } </script> <style scoped> *{ padding: 0; margin: 0; } .scroll-wrap { box-sizing: border-box; } .scroll-wrap li { height: 30px; line-height: 30px; list-style: none; } .scroll-inner { overflow: hidden; } .scroll-wrap.active { transition: margin 0.5s; margin-top: -30px; } </style>
3. 无缝滚动
/* 无缝滚动 */ <template> <div class="scroll-inner" ref="scrollInner"> <ul class="scroll-wrap" v-bind="$attrs" :class="{canPause: canPause}" :style="wrapStyle" ref="scrollWrap"> <li v-for="item in runArr" :key="item"> {{item}} </li> </ul> <ul class="scroll-wrap" v-if="canRun"> <li v-for="item in runArr" :key="item"> {{item}} </li> </ul> </div> </template> <script> /** * scrollArr 滚动数组 * speed 1 滚动速度 * canPause false 鼠标划过停止 */ export default { data () { return { runArr: [], wrapHeight: 0, innerHeight: 0, retry: 0, canRun: true, tim: Math.floor(Math.random() * (99999 - 10000) + 10000) } }, props: { // 滚动数组 scrollArr: { required: true }, // 滚动速度 speed: { type: Number, default: 1 }, // 鼠标划过停止 canPause: { type: Boolean, default: false } }, computed: { wrapStyle () { const s = this.wrapHeight / (20 + this.speed * 5) return { animationDuration: `${s}s`, animationIterationCount: 'infinite', animationName: `move${this.tim}`, animationTimingFunction: 'linear' } } }, mounted () { this.runArr = JSON.parse(JSON.stringify(this.scrollArr)) this.getWrapHeight() }, methods: { getWrapHeight () { this.$nextTick(() => { this.wrapHeight = this.$refs.scrollWrap.clientHeight this.innerHeight = this.$refs.scrollInner.clientHeight if (!this.wrapHeight && this.retry < 3) { this.getWrapHeight() this.retry++ return } else if (!this.wrapHeight && this.retry === 3){ console.error('获取元素高度失败或高度为0') return } if (this.innerHeight >= this.wrapHeight) { this.canRun = false return } this.createStyle() }) }, createStyle () { const style = ` @keyframes move${this.tim} { from {margin-top: 0;} to {margin-top: -${this.wrapHeight}px;} } ` let el = document.createElement('style') el.innerHTML = style document.head.appendChild(el) } } } </script> <style lang="less" scoped> *{ padding: 0; margin: 0; } .scroll-wrap { box-sizing: border-box; } .canPause { &:hover{ animation-play-state: paused; } } .scroll-wrap li { height: 30px; line-height: 30px; list-style: none; } .scroll-inner { overflow: hidden; position: relative; height: 100%; } </style>
加载全部内容