乘风原创程序

  • vue实现可以快进后退的跑马灯组件
  • 2022/4/8 16:56:24
  • 本文实例为大家分享了vue开发实现跑马灯效果组件的具体代码,供大家参考,具体内容如下

    用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>