• 基于VUE的可以滚动的横向时间轴


    这个时间轴可以播放,翻篇,进行一些配置,

    HTML:

          <div class="timeline-container">
            <div class="item">
              <div
                class="list"
                v-for="(item, index) in dataChart"
                :key="item.id"
                @click="go(index, '')"
                :style="{
                     option.itemWidth ? `${option.itemWidth}px` : `100px`,
                    height:option.itemHeight ? `${option.itemHeight}px` : `auto`,
                    transform: `translateX(${translateNum}px)`,
                }"
              >
                <!-- 内容部分 -->
                <div
                  :class="`text ${index === currentIndex?'active':''}`"
                  :style="itemStyle(index)"
                  :title="item.text"
                >
                  {{ item.text }}
                </div>
              </div>
            </div>
            <!-- 播放/暂停,showPlayBtn:是否显示播放按钮 -->
            <div
              class="btn-play"
              @click="play"
              :style="btnStyle"
              v-if="option.showPlayBtn"
            >
              {{option.btnPlayName||'播放/暂停'}}
            </div>
          </div>

    scss:

      .timeline {
         100%;
        box-sizing: border-box;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-wrap: wrap;
        .line {
           100%;
          height: 1px;
          background: #ccc;
        }
        .timeline-container {
           100%;
          position: relative;
          height: 100%;
          display: flex;
          align-items: center;
          .item {
             100%;
            display: -webkit-box;
            align-items: center;
            overflow: hidden;
            margin-right: 10px;
            .list {
              text-align: center;
              cursor: pointer;
              transition: 0.5s all linear;
              display: flex;
              justify-content: center;
              .text {
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
                position: relative;
              }
              .active {
                transition: 0.5s all linear;
              }
            }
            .item-prev,
            .item-next {
               45px;
              height: 45px;
              border-radius: 50%;
              color: #909090;
              background-color: #e9e9e9;
              cursor: pointer;
              margin: -24px auto 0;
              display: flex;
              align-items: center;
              justify-content: center;
              border: none;
              outline: none;
              &:hover {
                color: #fff;
                background-color: red;
              }
              &.item-disabled {
                background: #666;
                cursor: no-drop;
              }
            }
          }
          .btn-play{
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
          }
        }
      }

    JS:

    <script>
    
    //dataChart:数据源
    export default {
      name: 'timeline',
      data() {
        return {
          currentIndex: 0,
          timer: null,
          onIsActive: true,
          translateNum: 0,
        };
      },
      watch: {
        autoPlay(val) {
          if (val) {
            this.setGo()
          } else {
            clearInterval(this.timer);
          }
        }
      },
      computed: {
        prevIndex() {
          if (!this.loop) {
            if (this.currentIndex == 0) {
              return 0;
            } else {
              return this.currentIndex - 1;
            }
          } else {
            if (this.currentIndex == 0) {
              return this.dataChart.length - 1;
            } else {
              return this.currentIndex - 1;
            }
          }
        },
        nextIndex() {
          if (!this.loop) {
            if (this.currentIndex == this.dataChart.length - 1) {
              return this.dataChart.length - 1;
            } else {
              return this.currentIndex + 1;
            }
          } else {
            if (this.currentIndex == this.dataChart.length - 1) {
              return 0;
            } else {
              return this.currentIndex + 1;
            }
          }
        },
        /**
         * 自动播放
         */
        autoPlay: {
          get() {
            return this.option.autoPlay || false
          },
          set(val) {
            this.option.autoPlay = val;
          }
        },
        /**
         * 循环
         */
        loop() {
          return this.option.loop || false
        },
        /**
         * 一次显示几个列表项
         */
        timelineNum() {
          return this.option.timelineNum || 6
        },
        /**
         * 一次滚动的宽度
         */
        timelineWidth() {
          return ((this.option.itemWidth||0)/this.timelineNum).toFixed(0)*(this.option.timelineNum||0) || 1
        },
        /**
         * 按钮样式
         */
        btnStyle() {
          let obj = {
            fontSize: this.option.btnFontSize ? `${this.option.btnFontSize}px` : '16px',
            color: this.option.btnColor || '#fff',
             this.option.btnWidth ? `${this.option.btnWidth}px` : 'auto',
            height: this.option.btnHeight ? `${this.option.btnHeight}px` : 'auto',
          }
    
          if (this.option.useBtnBgImg) {
            if (this.autoPlay) {
              obj.background = `url(${this.option.btnActiveBg}) no-repeat center/100% 100%`
            } else {
              obj.background = `url(${this.option.btnBg}) no-repeat center/100% 100%`
            }
          } else {
            if (this.autoPlay) {
              obj.backgroundColor = `${this.option.btnActiveBg || '#00FB69'}`
            } else {
              obj.backgroundColor = `${this.option.btnBg || '#22E47F'}`
            }
          }
          return obj;
        }
      },
      methods: {
        /**
         * 当前节点的发送事件
         */
        go(index, str) {
          if(this.currentIndex>index){
            str="prev"
          }else{
            str="next"
          }
          this.currentIndex = index;
          this.onIsActive = true;
          if (this.autoPlay) {
            this.setGo();
          }
          this.calcTranslateNum(str);
    
          const data = {
            type: 'timeLine',
            itemData: this.dataChart[index]
          };
    
        },
        /**
         * 自动切换方法
         * goSpeed:切换速度
         */
        setGo() {
          clearInterval(this.timer);
          this.timer = setInterval(() => {
            this.go(this.nextIndex);
            // this.calcTranslateNum("next");
          }, this.option.goSpeed || 2000);
        },
        /**
         * 滚动计算法
         */
        calcTranslateNum(str) {
          if (str === "next") {
            // timelineNum的倍数的时候就翻一次
            if (this.currentIndex % this.timelineNum == 0) {
              this.translateNum += this.timelineNum * -this.timelineWidth;
              return;
            }
            if (this.currentIndex === 0) {
              this.translateNum = 0;
              return;
            }
          } else if (str === "prev") {
            if (this.currentIndex <= this.timelineNum) {
              this.translateNum = 0;
              return;
            }
            if (this.currentIndex % this.timelineNum == 0) {
              this.translateNum -=this.timelineNum * -this.timelineWidth;
              return;
            }
          } 
        },
        /**
         * 列表项样式
         */
        itemStyle(index) {
          let obj = {
             '100%',
            fontSize: this.option.fontSize ? `${this.option.fontSize}px` : '16px',
            color: this.option.color || '#fff',
            marginRight: `${this.option.marginRight || 0}px`,
            padding: `${this.option.paddingTop || 0}px ${this.option.paddingRight || 0}px ${this.option.paddingDown || 0}px ${this.option.paddingLeft || 0}px`,
            boxSizing: "border-box"
          }
          if (this.option.useBgImg) {
            obj.background = `url(${index === this.currentIndex ? this.option.bgActive : this.option.bg}) no-repeat center/100% 100%`
          } else {
            obj.backgroundColor = `${index === this.currentIndex ? this.option.bgActive || '#00B7FB' : this.option.bg || '#00FB69'}`
          }
          return obj;
        },
        /**
         * 播放/暂停
         */
        play() {
          this.autoPlay = !this.autoPlay;
        },
      },
      mounted() {
        if (this.autoPlay) {
          this.setGo();
        }
      },
      beforeDestroy() {
        clearInterval(this.timer);
      },
    }
    </script>

    调用:

    <timeline :autoPlay="false" :option="option" :data="apiData"></timeline>
      new Vue({
        el: '#app',
        data() {
          return {
            option: {
              itemWidth: 30,
              itemHeight: 30,
              useBgImg:true,
              bgActive:'red',
              bg:'yellow',
              useBtnBgImg:true,
              btnActiveBg:'red',
              btnBg:'yellow',
              fontSize:10,
              color:'#00F1FB',
              timelineWidth:20,
              autoPlay:false,
              loop:true,
              goSpeed:1000,
              txtLength:2,
              btnWidth:85,
              btnHeight:30,
              showPlayBtn:false,
            },
            apiData:[
              {
                id: 1,
                text: "2020-09-28",
              },
              {
                id: 2,
                text: "2020-09-30 12:00:002020-09-28 12:00:00",
              },
              {
                id: 3,
                text: "2020-10-2 ",
              },
              {
                id: 4,
                text: "2020-10-3",
              },
              {
                id: 5,
                text: "2020-10-4",
              },
              {
                id: 6,
                text: "2020-10-5",
              },
              {
                id: 7,
                text: "2020-10-6",
              },
              {
                id: 8,
                text: "2020-10-7",
              },
              {
                id: 9,
                text: "2020-10-8",
              },
              {
                id: 10,
                text: "2020-10-9",
              },
            ]
          }
        }
      })

    效果:

    积累小的知识,才能成就大的智慧,希望网上少一些复制多一些原创有用的答案
  • 相关阅读:
    架构师之路--视频业务介绍,离线服务架构和各种集群原理
    架构师之路--怎样聊技术天,限流技术和各类编程语言
    一条项目中常用的linux命令引发的经典算法题
    架构师之路--应用架构的选型和dubbo
    乐视开放平台技术架构-servlet和spring mvc篇
    架构师之路--从业务角度谈缓存的选型
    架构师之路--谈业务的合理架构
    IO回忆录之怎样过目不忘(BIO/NIO/AIO/Netty)
    520特篇-爱的境界
    编程十年的十种武学境界
  • 原文地址:https://www.cnblogs.com/llcdbk/p/14336084.html
Copyright © 2020-2023  润新知