vue跑马灯组件
Daheishuai 人气:1用vue编写一个可以快进后退的跑马灯组件
由于业务需求,要实现一个会可以控制速度的跑马灯,初开始用js的setinterval每隔几毫秒来减取一个字符拼接到后面,效果不理想就放弃了。后查询用js的animate这个api改造大功告成!
效果图
组件代码
<template> <div class="marquee" @mouseover="pause(true)" @mouseleave="pause()"> <i class="marquee-btn btn-left el-icon-d-arrow-left" @mousedown="speedUp(true)" @mouseup="speedStop()" ></i> <div ref="marqueeText" class="marquee-text"> <div v-if="itemClick"> <span v-for="item in text.split(splitSymbol)" :key="item" @click="$emit('itemClickEvent', item)" >{{item + ' 、'}}</span> </div> <div v-else>{{text}}</div> </div> <i class="marquee-btn btn-right el-icon-d-arrow-right" @mousedown="speedUp()" @mouseup="speedStop()" ></i> </div> </template> <script> export default { name: "marquee", props: { text: { type: String, required: true }, speed: { type: Number, required: false, default: 110 }, // 是否每个都可以点击触发事件 itemClick: { type: Boolean, required: false, default: false }, // 每个触发事件元素的分割符号 splitSymbol: { type: String, required: false, default: '' } }, data() { return { aniInstance: null, speedTimer: null }; }, methods: { setAnimate() { const contentWidth = this.$refs.marqueeText.scrollWidth; const keyframes = [ { transform: "translateX(100%)" }, { transform: `translateX(-${contentWidth}px)` } ]; const animateOptions = { duration: (contentWidth / this.speed) * 1000, iterations: Infinity, easing: "linear" }; this.aniInstance = document.querySelector(".marquee-text").animate(keyframes, animateOptions); }, /** * 快进 * @param { Boolean } isLeft 是否为左方向 */ speedUp(isLeft = false) { const set = () => { if (this.aniInstance.currentTime > 0) { this.aniInstance.currentTime = this.aniInstance.currentTime + (isLeft ? 2000 : -2000); this.aniInstance.currentTime <= 0 && (this.aniInstance.currentTime = 0); } } // 鼠标单击 set(); // 鼠标长按 this.speedTimer = setInterval(() => { set() }, 100); }, // 快进停止 speedStop() { clearInterval(this.speedTimer); this.speedTimer = null; }, /** * 暂停、播放 * @param { Boolean } isPause 是否暂停 */ pause(isPause = false) { this.aniInstance[["play", "pause"][Number(isPause)]](); } }, mounted() { this.$nextTick(() => { this.setAnimate(); }); } }; </script> <style lang="less" scoped> .marquee { position: relative; padding: 10px 0; overflow: hidden; width: 100%; font-size: 16px; color: #fff; background-image: linear-gradient( to left, #b9565e, #cb655a, #da7655, #e58a50, #eb9f4b ); &:hover .marquee-btn { opacity: 1; } } .marquee-btn { position: absolute; top: 50%; transform: translateY(-50%); padding: 15px; color: #fff; background: rgba(1, 1, 1, 0.4); z-index: 999; cursor: pointer; opacity: 0; transition: all 0.2s linear; } .btn-left { left: 0; } .btn-right { right: 0; } .marquee-text { white-space: nowrap; span { &:hover { cursor: pointer; color: #2c3e50; } } } </style>
父组件代码
<Marquee :text="overdueInfo.content" :itemClick="true" :speed="120" splitSymbol="、" @itemClickEvent="marqueeSearch" class="marquee-box__container" ></Marquee>
加载全部内容