vue -(滚动播放-全屏展示)

vue可视化

git地址:https://gitee.com/HuaWang400/jiajuxiaoshou

转载自:https://juejin.cn/post/6931189766109003783

滚动播报

 公共组件-路由组件

<template>
<div class="scroll">
  <div class="scroll-header"
        :style="{
          height : headerConfig.headerHeight + 'px',
          background: headerConfig.headerBackground,
        }">
    <div class="scroll-header-item"
         v-for="(item, index) in headerConfig.headerItems"
         :key = "'scroll-header-item' + index"
         :style="{
            averageWidth + 'px',
           ... headerConfig.headerStyle[index]
         }">
         {{item}}</div>
  </div>
  <div class="scroll-content" ref="scrollContent">
    <div v-for="(item, index) in rowsData"
         :key = "item.index"
         :style = "{
           height: rowHeights[index] + 'px',
           background: item.index % 2 === 0 ? rowBackground[0] : rowBackground[1]
          }"
         class="scroll-content-li">
      <div v-for="( k, i ) in Object.keys(item.data)"
           :key = "'scroll-content-li' + i"
           class="scroll-content-li-item"
           :style="{
              headerConfig.headerStyle[i].width ? headerConfig.headerStyle[i].width : averageWidth + 'px',
            }">{{item.data[k]}}</div>
    </div>
  </div>
</div>
</template>
<script>
export default {
  name: 'scroll',
  props: {
    header: {
      type: Object,
      required: true
    },
    rows: {
      type: Array,
      required: true
    },
    capacity: {
      type: Number,
      required: true
    },
    rowBackground: {
      type: Array,
      default: function () {
        return ['hsl(207deg 84% 51% / 8%)', 'transparent']
      }
    },
    duration: {
      type: Number,
      default: 3000
    }
  },
  data () {
    return {
      headerConfig: null,
      averageWidth: 0,
      rowHeight: 0,
      currentIndex: 0,
      rowsx: null,
      rowsData: null,
      step: 1,
      rowHeights: new Array(this.rows.length).fill(0)
    }
  },
  watch: {
    rows: {
      handler (newValue, oldValue) {
        this.handleRowData()
        const index = this.currentIndex > 0 ? this.currentIndex - 1 : this.currentIndex
        const temp = this.rowsx.slice(index)
        temp.push(...this.rowsx.slice(0, index))
        this.rowsData = temp
        clearTimeout(this.timer)
        this.timer = setTimeout(() => {
          this.animation()
        }, this.duration)
      },
      deep: true
    }
  },
  methods: {
    handleRowData () {
      let temp = this.rows.slice()
      if (this.rows.length > this.capacity) {
        temp = this.rows.slice().concat(this.rows.slice())
      }
      this.rowsx = temp.map((item, index) => {
        return {
          data: item,
          index: index
        }
      })
      this.rowsData = this.rowsx.slice()
    },
    setConfig () {
      const headerConfigDefault = {
        headerItems: [],
        headerBackground: 'transparent',
        headerHeight: 60,
        headerStyle: []
      }
      this.headerConfig = Object.assign(headerConfigDefault, this.header)
      this.handleRowData()
    },
    setHeaderWidth () {
      const width = this.$el.clientWidth
      let fixedWidth = 0
      let n = 0
      this.headerConfig.headerStyle.forEach(item => {
        if (item.width) {
          fixedWidth += parseInt(item.width)
          n++
        }
      })
      this.averageWidth = (width - fixedWidth) / (this.header.headerItems.length - n)
    },
    animation () {
      clearTimeout(this.timer)
      const len = this.rowsx.length
      if (len <= this.capacity) return
      const temp = this.rowsx.slice(this.currentIndex)
      temp.push(...this.rowsx.slice(0, this.currentIndex))
      this.rowHeights = new Array(len).fill(this.rowHeight)
      this.rowHeights.splice(0, this.step, ...new Array(this.step).fill(0))
      this.rowsData = temp
      this.currentIndex += this.step

      const isLast = this.currentIndex - len
      if (isLast >= 0) this.currentIndex = isLast

      this.timer = setTimeout(() => {
        this.animation()
      }, this.duration)
    },
    setContentHeight () {
      const height = this.$el.clientHeight
      const h = height - this.headerConfig.headerHeight
      this.$refs.scrollContent.style.height = h + 'px'
      const min = Math.min(this.rows.length, this.capacity)
      this.rowHeight = h / min
      this.rowHeights = new Array(min).fill(this.rowHeight)
    }
  },
  created () {
    if (!this.header.headerItems || this.header.headerItems.length === 0) return
    this.setConfig()
    this.$nextTick(() => {
      this.setHeaderWidth()
      this.setContentHeight()
      this.timer = setTimeout(() => {
        this.animation()
      }, this.duration)
    })
  }
}
</script>
<style lang="less" scoped>
.scroll{
  height: 100%;
   100%;
  text-align: center;
  &-header{
    display: flex;
    align-items: center;
    &-item{
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }
  &-content{
    overflow: hidden;
    &-li{
      display: flex;
      align-items: center;
      overflow: hidden;
      transition: all 0.3s linear;
      &-item{
        display:-webkit-box;
        -webkit-box-orient:vertical;
        -webkit-line-clamp:2;
        overflow:hidden;
        padding:0 10px;
      }
    }
  }
}
</style>
components/Common/Scroll.vue
<template>
    <div class="star-product">
      <div class="title">明星产品销售概况</div>
      <div class="list">
        <scroll
          :header="header"
          :rows="list"
          :duration="duration"
          :capacity="6"
        ></scroll>
      </div>
    </div>
</template>
<script>
import Scroll from "@/components/Common/Scroll";
export default {
  components: {
    Scroll,
  },
  data() {
    return {
      starProduct:  [   
        {
          name: "A品牌木门",
          sales: 92090,
          orders: 51,
        },
        {
          name: "B品牌沙发",
          sales: 602090,
          orders: 107,
        },
        {
          name: "C品牌衣柜",
          sales: 802090,
          orders: 94,
        },
        {
          name: "D品牌木门",
          sales: 92090,
          orders: 51,
        },
        {
          name: "E品牌沙发",
          sales: 602090,
          orders: 107,
        },
        {
          name: "F品牌木门",
          sales: 92090,
          orders: 51,
        },
        {
          name: "G品牌木门",
        //   sales: 92090,
        //   orders: 51,
        },
        // {
        //   name: "H品牌沙发",
        //   sales: 602090,
        //   orders: 107,
        // },
      ],

      header: {
        headerItems: ["产品", "销售额", "订单量",],
        headerHeight: 140,
        headerStyle: [
          {
            fontSize: "45px",
          },
          {
             "260px",
            fontSize: "45px",
          },
          {
             "260px",
            fontSize: "45px",
          },
        ],
      },
      rowBg: ["red", "green"],
      duration: 3000,
    };
  },
  computed: {
    list() {
      return this.starProduct;
    },
  },
};
</script>
<style lang="less" scoped>
.star-product {
  height: 100%;
   100%;
  display: flex;
  flex-direction: column;
  .title {
    height: 100px;
    font-size: 40px;
    font-weight: bold;
  }
  .list {
    flex: 1;
     100%;
    font-size: 36px;
  }
}
</style>
components/Scroll.vue

全屏/退出

<template>
  <div class="display-header">
    <span class="sub">数据更新于:{{ time }}</span>
    <span class="title">2020秋季家具交易会实时销售数据可视化平台</span>
    <span class="sub full-screen" @click="toggleScreen">{{ operationText }}</span>
  </div>
</template>
<script>
let timer
export default {
  data () {
    return {
      isFullScreen: false
    }
  },
  computed: {
    operationText () {
      return this.isFullScreen ? '退出' : '全屏'
    },
    time () {
      const t = this.$store.state.updateTime
      return `${t.toLocaleDateString()} ${t.toLocaleTimeString()}`
    }
  },
  methods: {
    toggleScreen () {
      const main = document.body
      if (this.isFullScreen) {
        if (document.exitFullscreen) {
          document.exitFullscreen()
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen()
        } else if (document.webkitCancelFullScreen) {
          document.webkitCancelFullScreen()
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen()
        }
      } else {
        if (main.requestFullscreen) {
          main.requestFullscreen()
        } else if (main.mozRequestFullScreen) {
          main.mozRequestFullScreen()
        } else if (main.webkitRequestFullScreen) {
          main.webkitRequestFullScreen()
        } else if (main.msRequestFullscreen) {
          main.msRequestFullscreen()
        }
      }
    },
    changeFullScreenStatus () {
      this.isFullScreen = !this.isFullScreen
    }
  },
  mounted () {
    if (document.body.requestFullscreen) {
      document.addEventListener('fullscreenchange', this.changeFullScreenStatus)
    } else if (document.body.msRequestFullscreen) {
      document.addEventListener('MSFullscreenChange', this.changeFullScreenStatus)
    }
  },
  destroyed () {
    clearInterval(timer)
    if (document.body.requestFullscreen) {
      document.removeEventListener('fullscreenchange', this.changeFullScreenStatus)
    } else if (document.body.msRequestFullscreen) {
      document.removeEventListener('MSFullscreenChange', this.changeFullScreenStatus)
    }
  }
}
</script>
<style lang="scss" scoped>
.display-header{
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 30px;
  .title{
    font-size: 60px;
    color: #fff;
    letter-spacing: .1em;
  }
  .sub{
     1000px;
    color: rgba(255,255,255,.3);
  }
  .full-screen{
    cursor: pointer;
    position: relative;
    text-align: right;
    &:before{
      content: '';
      position: absolute;
      top: -20px;
      bottom: -20px;
      left: -20px;
      right: -20px;
    }
  }
}
</style>
DisplayHeader/index.vue
作者:华王 博客:https://www.cnblogs.com/huahuawang/
原文地址:https://www.cnblogs.com/huahuawang/p/14900899.html