Vue简短代码实现文字首尾无缝跑马灯效果

写在前面

由于HTML自带的marquee标签无法做到上一条文本和下一条文本无缝衔接,并且HTML标准已将其废弃,所以结合网上的资源自己写了一个,代码不多,仅能横向滚动,可滚动重复滚动一条或多条文本,字数不限制,若想要实现纵向滚动可使用vux组件库的marquee组件

效果图

gif动图展示出来看起来很卡,实际效果并不卡哦😁
实际不卡

跑马灯子组件代码

<template>
  <div class="marquee-wrap">
  	<!-- 滚动内容 -->
    <div class="scroll">
      <p class="marquee">{{text}}</p>
      <!-- 文字副本 -->
      <p class="copy"></p>
    </div>
    <!-- 为了计算总文本宽度,通过css在页面中隐藏 -->
    <p class="getWidth">{{text}}</p>
  </div>
</template>

<script>
export default {
  props: ['lists'], // 父组件传过来的数组
  data () {
    return {
      timer: null,
      text: ''
    }
  },
  created () {
    // 进入页面等一秒才开始滑动
    let timer = setTimeout(() => {
      this.move()
      clearTimeout(timer)
    }, 1000)
  },
  // 把父组件传入的arr转化成字符串
  mounted () {
    for (let item of this.lists) {
      this.text += ' ' + item
    }
  },
  methods: {
    move () {
      let maxWidth = document.querySelector('.marquee-wrap').clientWidth
      // 获取文字text 的计算后宽度 (由于overflow的存在,直接获取不到,需要独立的node计算)
      let width = document.querySelector('.getWidth').scrollWidth
      // 如果文本内容的宽度小于页面宽度,则表示文字小于等于一行,则不需要滚动
      if (width <= maxWidth) return
      let scroll = document.querySelector('.scroll')
      let copy = document.querySelector('.copy')
      copy.innerText = this.text // 文字副本填充
      let distance = 0 // 位移距离
      // 设置位移
      this.timer = setInterval(() => {
        distance -= 1
        // 如果位移超过文字宽度,则回到起点
        if (-distance >= width) {
          distance = 16 // 距离必须与marquee的margin宽度相同
        }
        scroll.style.transform = 'translateX(' + distance + 'px)'
      }, 20)
    }
  },
  beforeDestroy () {
  	// 清除计时器
    clearInterval(this.timer)
  }
}
</script>
<style scoped lang='less'>
  .marquee-wrap {
    width: 100%;
    overflow: hidden;
    position: relative;
    .scroll {
      display: flex;
      p{
        word-break:keep-all; // 不换行
        white-space:nowrap;
        /* 设置前后间隔 */
        &.marquee {
          margin-right: 16px;
        }
      }
    }
    /* 仅为了获取宽度,故隐藏掉 */
    .getWidth {
      word-break:keep-all; // 不换行
      white-space:nowrap;
      position: absolute;
      opacity: 0;
      top: 0;
    }
  }
</style>

父组件代码

<template>
 <div class="notice">
   <!-- 喇叭图片,可删除 -->
   <img class="icon-notice" src="./image/喇叭.png"/>
   <marquee :lists="lists"></marquee>
 </div>
</template>

<script>
// 引入跑马灯组件
import marquee from './marquee'

export default {
  data () {
    return {
      // 要展示的数据,以数组的形式
      lists: ['未认证用户不能报名,每人每次只能预约一个时段的健身项目,快来健身吧!!!']
    }
  },
  components: {
    marquee
  }
}
</script>

<style lang="less" scoped>
  .notice{
    padding: 16/75rem 28/75rem;
    font-size:24/75rem;
    color:#929292;
    line-height:38/75rem;
    display: flex;
    align-items: center;
    .icon-notice {
      width: 25/75rem;
      height: 21/75rem;
      margin-right: 14/75rem;
    }
  }
</style>

若有错误,请指正,谢谢?

Logo

前往低代码交流专区

更多推荐