vue 公告消息横向滚动

本文展示了如何使用Vue实现两种滚动效果:一种是纯文字滚动通知栏,通过计算和设置动画实现文字平滑滚动;另一种是消息列表在滚屏上横向滚动,利用定时器和数组操作实现消息的动态循环滚动。组件还包括了点击事件监听和响应式布局调整。
摘要由CSDN通过智能技术生成

第一种:纯文字展示,只有一句话

效果图
在这里插入图片描述

<!-- 公告栏组件 -->
<template>
  <div class="notice-bar" @click="tipClick">
    <div class="notice-bar__icon">
      <img src="@/assets/icons/notice.png"/>
      <span>{{ sub_title }}</span>
    </div>
    <div ref="wrap" class="notice-bar__wrap">
      <div ref="content" class="notice-bar__content" :style="contentStyle">{{ text }}</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'NoticeBar',
  props: {
    sub_title: {
      type: String,
      default: '通知:'
    },
    text: {
      type: String,
      default: ''
    },
    speed: {
      type: Number,
      default: 50
    },
    defaultWidth: {
      type: Number,
      default: 375
    }
  },
  data () {
    return {
      contentStyle: {
        transitionDuration: '0s',
        transform: 'translateX(0px)'
      },
      wrapWidth: 0,
      contentWidth: 0,
      time: 0,
      timer: null,
      convertSpeed: 1
    }
  },
  created () {},
  mounted () {
    if (this.text) {
      this.init()
    }
  },
  watch: {
    text (val) {
      this.init()
    }
  },
  methods: {
    init () {
      const _width = window.innerWidth
      this.convertSpeed = _width / this.defaultWidth * this.speed  // 根据分辨率转化成不同的速度
      this.wrapWidth = this.$refs.wrap.offsetWidth
      this.contentWidth = this.$refs.content.offsetWidth
      this.startAnimate()
      this.timer = setInterval(() => {
        this.startAnimate()
      }, this.time * 1000)
      this.$once('hook:beforeDestroy', () => {
        clearInterval(this.timer)
        this.timer = null
      })
    },
    startAnimate () {
      this.contentStyle.transitionDuration = '0s'
      this.contentStyle.transform = 'translateX(' + this.wrapWidth + 'px)'
      this.time = (this.wrapWidth + this.contentWidth) / this.convertSpeed
      setTimeout(() => {
        this.contentStyle.transitionDuration = this.time + 's'
        this.contentStyle.transform = 'translateX(-' + this.contentWidth + 'px)'
      }, 200)
    },
    tipClick () {
      this.$emit('click')
    }
  }
}
</script>
<style scoped lang='scss'>
    .notice-bar {
      position: relative;
      width: 100%;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: #eee;
      display: flex;
      align-items: center;
      .notice-bar__icon {
          display: flex;
          align-items: center;
        img {
          width: 20px;
          margin-right: 10px;
        }
      }
      .notice-bar__wrap {
        position: relative;
        display: flex;
        flex: 1;
        height: 100%;
        align-items: center;
        overflow: hidden;
        .notice-bar__content {
          position: absolute;
          color: #eee;
          white-space: nowrap;
          transition-timing-function: linear;
        }
      }
    }
</style>


父组件中使用

// 引入
import noticeBar from '@/views/my_components/noticeBar.vue'// 消息滚屏

// 注册组件
components:{  noticeBar }
// 使用
<notice-bar :speed="20" v-if="noticeCon" :text="noticeCon" @click="openTip" />

// 数据
   noticeCon: 'import NoticeBar from @/components/NoticeBarimport NoticeBar from @/components/NoticeBar',
// 方法
 openTip () {}

第二种: 消息列表在滚屏上横向滚动

效果图:
在这里插入图片描述

子组件

<template>
  <div class="m-slide" @mouseenter="onStop" @mouseleave="onStart">
    <div
      :style="`will-change: transform; transform: translateX(${-left}px);`"
      class="u-slide-title"
      v-for="(item, index) in sliderData"
      :key="index"
      :title="item.title"
      @click="onClickTitle(item.title)">
      {{ item.title }}
    </div>
  </div>
</template>
<script>
export default {
  name: 'Slider',
  props: {
    sliderData: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  data () {
    return {
      left: 0,
      moveTimer: null
    }
  },
  created () {
    this.onStart()
  },
  methods: {
    onClickTitle (title) { // 通知父组件点击的标题
      this.$emit('getTitle', title)
    },
    onStop () { // 暂停滚动
      clearInterval(this.moveTimer)
    },
    onStart () { // 开始滚动
      if (this.sliderData.length > 4) { // 超过4条开始滚动
        this.getSlide()
      }
    },
    getSlide () {
      this.moveTimer = setInterval(() => {
        this.moveLeft()
      }, 5) // 1s移动200次
    },
    moveLeft () {
      if (this.left >= 320) {
        this.sliderData.push(this.sliderData.shift()) // 将第一条数据放到最后
        this.left = 0
      } else {
        this.left += 0.2 // 每次移动0.2px
      }
    }
  }
}
</script>
<style lang="scss" scoped>
.m-slide {
  width: 1200px;
  margin: 60px auto;
  height: 45px;
  white-space: nowrap;
  overflow: hidden;
  .u-slide-title {
    display: inline-block;
    margin-left: 20px;
    font-size: 14px;
    font-weight: 400;
    line-height: 45px;
    // width: 300px;
    // overflow: hidden;
    // text-overflow: ellipsis;
    // white-space: nowrap;
    cursor: pointer;
    &:hover {
      color:#1890FF;
    }
  }
}
</style>

父组件中使用

// 引入
import Slider from '@/views/my_components/Slider.vue'// 消息滚屏

// 注册组件
components:{  Slider }
// 使用
<div class="notice item_box">
     <img src="@/assets/icons/notice.png" alt="">
     <div class="tit">通知:</div>
     <div class="notice_con"><Slider :sliderData="sliderData" @getTitle="getSliderTitle"/></div>
 </div>

// 数据
  sliderData: [
       {
           title: '1美国作家杰罗姆·大卫·塞林格创作的唯一一部长篇小说'
       },
       {
       title: '2首次出版于1951年'
       },
       {
       title: '3天时间内'
       },
       {
       title: '4内心世界'
       },
       {
       title: '5在青少年中引起强烈共鸣'
       }
   ],
// 方法
getSliderTitle (title) { // 获取点击的标题
      console.log('title:', title)
  },

样式

.notice{
  display: inline-flex;
       align-items: center;
       padding: 0 20px;
       height: 50px;
       overflow: hidden;
       img{
           margin-right: 10px;
       }
       .tit{
           width: 50px;
       }
       .notice_con{
           width: 93%;
           padding-right: 20px;
           white-space: nowrap;
           overflow: hidden;
       }
   }
  • 12
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值