pc端的滚动通知组件 NoticeBar

用于在pc端顶部的滚动通知

<template>
  <div class="notice-bar">
    <div class="direction-row">
      <div id="notice-box" class="notice-box">
        <div
          id="notice-content"
          class="notice-content"
          :style="{
            animationDuration: animationDuration,
            animationPlayState: animationPlayState,
          }"
        >
          <span class="notice-text" :style="[textStyle]">{{ showText }}</span>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'RowNotice',
  props: {
    // 显示的内容,数组
    list: {
      type: Array,
      default() {
        return []
      }
    },
    // 是否自动播放
    autoplay: {
      type: Boolean,
      default: true
    },
    // 水平滚动时的滚动速度,即每秒滚动多少px,这有利于控制文字无论多少时,都能有一个恒定的速度
    speed: {
      type: [Number, String],
      default: 30
    },
    // 播放状态,play-播放,paused-暂停
    playState: {
      type: String,
      default: 'play'
    },
    // 文字颜色,各图标也会使用文字颜色
    color: {
      type: String,
      default: ''
    },
    // 字体大小,单位px
    fontSize: {
      type: [Number, String],
      default: 14
    }
  },
  data() {
    return {
      textWidth: 0, // 滚动的文字宽度
      boxWidth: 0, // 供文字滚动的父盒子的宽度,和前者一起为了计算滚动速度
      animationDuration: '10s', // 动画执行时间
      animationPlayState: 'paused', // 动画的开始和结束执行
      showText: '' // 显示的文本
    }
  },
  computed: {
    // 文字内容的样式
    textStyle() {
      const style = {}
      if (this.color) style.color = this.color
      else if (this.type === 'none') style.color = '#606266'
      style.fontSize = this.fontSize + 'px'
      return style
    }
  },
  watch: {
    list: {
      immediate: true,
      handler(val) {
        this.showText = val.join(',')
        this.$nextTick(() => {
          this.initSize()
        })
      }
    },
    playState(val) {
      if (val === 'play') this.animationPlayState = 'running'
      else this.animationPlayState = 'paused'
    },
    speed(val) {
      this.initSize()
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initSize()
    })
  },
  methods: {
    initSize() {
      this.textWidth = document.getElementById('notice-content').clientWidth
      // 根据t=s/v(时间=路程/速度),这里为何不需要加上#notice-box的宽度,因为中设置了.notice-content样式中设置了padding-left: 100%
      // 恰巧计算出来的结果中已经包含了#u-notice-box的宽度
      this.animationDuration = `${this.textWidth / this.speed}s`
      this.animationPlayState = 'paused'
      setTimeout(() => {
        if (this.playState === 'play' && this.autoplay) this.animationPlayState = 'running'
      }, 10)
    }
  }
}
</script>
<style lang="scss" scoped>
.notice-bar {
	padding: 9px 6px;
	overflow: hidden;
}

.direction-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.notice-box {
  display: flex;
	flex: 1;
	overflow: hidden;
}

.notice-content {
	animation: u-loop-animation 10s linear infinite both;
	text-align: right;
	// 这一句很重要,为了能让滚动左右连接起来
	padding-left: 100%;
	display: flex;
	flex-wrap: nowrap;
}

.notice-text {
	font-size: 14px;
	word-break: keep-all;
	white-space: nowrap
}

@keyframes u-loop-animation {
	0% {
		transform: translate3d(0, 0, 0);
	}

	100% {
		transform: translate3d(-100%, 0, 0);
	}
}
</style>

你可能感兴趣的:(Vue,css,css3,css,javascript)