滚动公告-vue2数据可视化公告滚动组件

122 阅读2分钟

在可视化页面的设计中,公告滚动组件至关重要。我们要仔细记录它的相关信息,如位于页面何处,外观是怎样的风格,滚动的速度如何,公告内容怎样设置,还有鼠标悬停等交互功能情况,为页面的完善提供精准的数据支撑。 为实现公告滚动效果,直接引入一个三方库不是上上选,自己封装一个组件,在此记录一下。 废话不多说,直接贴代码。

子组件代码:

<template>
  <div class="list-scroll-home" ref="box">
    <slot></slot>
    <!--如果内容不够多,隐藏第二个插槽,同时也无滚动效果-->
    <slot v-if="isScroll"></slot>
  </div>
</template>


<script>
export default {
  name: 'ListScroll',
  props: {
    // 步长,默认为1
    speed: {
      default: 1,
      type: Number
    },
    // 数据数组长度,默认为0
    dataListHeight: {
      default: 0,
      type: Number
    }
  },
  data() {
    return {
      height: 0,
      // 是否开启滚动效果
      isScroll: true
    }
  },
  watch: {
    // 监听数据变化,
    dataListHeight: {
      handler(val) {
        this.isScroll = true
        // 当数据发生变换后,等待新的dom及slot都被渲染出来,在进行后续判断
        this.$nextTick(() => {
          // 在盒子内容高度小于可视高度时不滚动
          if (this.boxHeight < this.slot0.clientHeight) {
            this.start(this.height)
            this.setEvet()
          } else {
            this.isScroll = false
          }
        })
      },
      // 该回调将会在侦听开始之后被立即调用
      immediate: true
    }
  },
  computed: {
    slot0() {
      return this.$refs.box.children[0]
    },
    slot1() {
      return this.$refs.box.children[1]
    },
    // 盒子的可视高度
    boxHeight() {
      return this.$refs.box.clientHeight
    }
  },
  methods: {
    // 鼠标移入停止滚动 移出继续滚动
    setEvet() {
      // 移入
      this.$refs.box.onmouseenter = () => {
        this.isScroll = false
      }
      // 移出
      this.$refs.box.onmouseleave = () => {
        this.isScroll = true
        this.$nextTick(() => {
          this.start(this.height)
        })
      }
    },
    // 滚动方法
    start(height) {
      this.slot0.style = `transform:translateY(-${height}px);`
      this.slot1.style = `height:${this.boxHeight}px;transform:translateY(-${height}px);overflow:hidden;`
      if (height >= this.slot0.clientHeight) {
        this.height = 0
      } else {
        this.height += this.speed
      }
      if (!this.isScroll) return
      // 执行频率与屏幕刷新率有关系,
      // window.requestAnimationFrame() 方法会告诉浏览器你希望执行一个动画。它要求浏览器在下一次重绘之前,调用用户提供的回调函数。
      window.requestAnimationFrame(() => {
        this.start(this.height)
      })
    }
  }
}
</script>


<style scoped lang="scss">
.list-scroll-home {
  overflow: hidden;
}
</style>

组件应用:

<template>
  <div class="notice-body">
    <!--添加scroll-box类名,限定滚动区域宽高-->
    <list-scroll class="scroll-box" :speed="0.5" :data-list-height="noticeList.length">
      <!--插槽内容的宽高,会影响滚动区域,高度比scroll-box高的话,会启动滚动效果-->
      <div class="notice-body-card" ref="noticeCard">
        <div class="notice-one" v-for="(item, index) in noticeList" :key="index">{{ item }}</div>
      </div>
    </list-scroll>
  </div>
</template>


<script>
import ListScroll from './listScroll'


export default {
  components: {
    ListScroll
  },
  data() {
    return {
      noticeList: []
    }
  },
  created() {
    this.initData()
  },
  methods: {
    initData() {
      // 模拟异步请求数据
      setTimeout(() => {
        this.noticeList = [
          'aaaaaaaaaaaaaaaaaaaaaaaaa',
          'bbbbbbbbbbbbbbbbbbbbbbbbb',
          'ccccccccccccccccccccccccc',
          'ddddddddddddddddddddddddd',
          'eeeeeeeeeeeeeeeeeeeeeeeee',
          'fffffffffffffffffffffffff'
        ]
      })
    }
  }
}
</script>


<style scoped lang="scss">
.notice-body {
  margin: 28px 24px 10px;
  height: calc(100% - 54px);
  overflow: hidden;


  .scroll-box {
    height: 132px;
  }


  .notice-body-card {
    max-height: 390px;
    width: 100%;
    overflow: hidden;
    margin-bottom: 2px;


    .notice-one {
      width: 100%;
      height: 24px;
      line-height: 24px;
      margin-bottom: 2;
      font-size: 12px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
}
</style>