美文网首页
使用vue,来写个时间轴

使用vue,来写个时间轴

作者: yimi珊 | 来源:发表于2020-11-26 18:26 被阅读0次

    功能

    1.选择时间,获取对应数据,显示时间轴和时间点
    2.时间点hover显示对应时间
    3.整点时间显示
    4.点击时间轴,选择对应的时间点
    5.点击时间点,选择对应的时间点
    6.拖动点,选择对应的时间点
    7.限制拖动,及点击位置


    效果图

    组件代码

    1.框架:vue+axios
    2.日期组件:Ant Design of Vue(也可以自己修改成其他日期组件)
    3.日期格式化:moment

    安装: 
    npm i moment --save-dev
    ---------------------------------------
    main.js引入:
    //引入moment
    import moment from 'moment'
    import 'moment/locale/zh-cn'//中文
    Vue.prototype.$moment = moment
    ---------------------------------------
    vue文件中:
    let createDate =this.$moment(value).format('YYYY/MM/DD');
    

    4.数据返回格式


    tips:数据返回为时间戳秒钟算,而不是毫秒,所以有些地方需要*1000计算

    <template>
      <div class="time_con">
        <span>选择显示区间:</span>
        <a-date-picker
          v-model="startValue"
          format="YYYY-MM-DD"
          placeholder="开始时间"
          @openChange="handleStartOpenChange"
          :disabled-date="disabledStartDate"
          @change="changePicker"
          size="large"
        />
        <a-date-picker
          v-model="endValue"
          format="YYYY-MM-DD"
          placeholder="结束时间"
          :open="endOpen"
          @openChange="handleEndOpenChange"
          :disabled-date="disabledEndDate"
          @change="changePicker"
          size="large"
        />
        
        <div class="line_time" v-show="showLine">
          <div class="all_line" @mousedown.stop="lineMouseDown">
          <!-- <div class="all_line"> -->
            <div class="line" ref="allLineTime">
              <!-- 可以滑动的线 -->
              <div class="can_line" ref="canLine" @mousedown.stop="canLineMouseDown"></div>
              <!-- 参考点 -->
              <div class=" reference" v-for="(dateTip,dt) in dateTips" :key="'tips-'+dt" :style="setLeft(dateTip)">
                <em v-text="formatter(dateTip,1)" ></em>
              </div>
              <!-- 备份点 -->
              <div class="dot dot_all" v-for="(incre,i) in incre_dates" :key="i" :style="setLeft(incre)" @mousedown.stop="clickDot(incre)">
                <em v-text="formatter(incre)" ></em>
              </div>
              <!-- 可滑动点 -->
              <div class="dot sel_dot" ref="selDot" @mousedown.stop="dragDown">
                <em>{{selTime}}<i></i></em>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import {getBackupTimeline} from "@/plugins/axios";
    export default {
      name: "TimeLine",
      data() {
        return {
          startValue: this.$moment().format("YYYY-MM-DD"),//开始时间---时间选择
          endValue: this.$moment().format("YYYY-MM-DD"),//结束时间---时间选择
    
          endOpen: false,
          fullDate:null,//最初时间(最开始有数据的时候)
          binlogDate:null,//binlog 结束时间
          selTime:null,//选中时间
    
          start_date:null,//开始时间戳
          end_date:null,//结束时间戳
          timeline:null,//选中时间戳
          incre_dates:[],//备份点数组
          allIncre:[],//备份点和binlog
          showLine:false,//是否显示时间轴
          dateTips:[],//0点,提示时间点数组
        };
      },
      created(){
        let today = new Date();
        let forToday = this.$moment(today).subtract(7, 'd');//获取七天前的日期
        this.startValue = this.$moment(forToday).startOf('day').format("YYYY-MM-DD");//默认设置七天前的0点为开始时间
        this.endValue = this.$moment(today).endOf('day').format("YYYY-MM-DD");//默认设置今天为结束时间
        this.getBackupTimeline(1);//参数1表示第一次执行
      },
      mounted() {
    
      },
      methods: {
        //时间显示格式
        formatter(value,day) {   
          if(day)return `${this.$moment(value*1000).format('YYYY/MM/DD')}`;
          return `${this.$moment(value*1000).format('YYYY/MM/DD HH:mm:ss')}`;
        },
        //开始时间---范围
        disabledStartDate(startValue) {
          let today = new Date();
          if(this.endValue){
            return startValue.format("X")*1 > this.$moment(this.endValue).endOf('day').format("X")*1 || startValue.endOf('day').format("X")*1 < this.fullDate*1;
          }else{
            return startValue.format("X")*1 > this.$moment(today).endOf('day').format("X")*1 || startValue.format("X")*1 < this.fullDate*1;  
          }
        },
        //结束时间---范围
        disabledEndDate(endValue) {
          const startValue = this.startValue;
          let today = new Date();
          if(startValue){
            let eDate = this.$moment(startValue).add(7, 'd');
            return endValue.format("X")*1 > eDate.format("X")*1 || endValue.format("X")*1 < this.$moment(startValue).startOf('day').format("X")*1  || endValue.format("X")*1 > this.$moment(today).format("X")*1;
          }else{
            return endValue.format("X")*1 < this.fullDate || endValue.format("X")*1 > this.$moment(today).format("X")*1; 
          }
        },
        handleStartOpenChange(open) {
          if (!open) {
            this.endOpen = true;
          }
        },
        handleEndOpenChange(open) {
          this.endOpen = open;
        },
        //时间选择---修改时间
        changePicker(){
          if(this.startValue && this.endValue){
            this.getBackupTimeline();
          }
        },
        //获取时间轴数据
        getBackupTimeline(n){
          if(!n)this.showLine = true;//首次执行,不显示时间轴,只用于获取fullDate和binlogDate
            
          this.$parent.showLine = false;
          this.start_date = this.$moment(this.startValue).startOf('day').format("X")*1;
          this.end_date = this.$moment(this.endValue).endOf('day').format("X")*1;
          //请求参数
          let params={
            bak_db_id:this.$route.query.bak_db_id,
            start_date:this.start_date,
            end_date:this.end_date,
          }
          getBackupTimeline(params).then(r=>{
            if(r.data.status==2000){//请求成功
              let dt = r.data.data;
    
              this.fullDate = dt.full_date;
              this.binlogDate = dt.binlog_date; 
    
              if(n){//首次执行,获取可选择日期
                let today = new Date();
                let forToday = this.$moment(today).subtract(7, 'd');
                if(this.$moment(forToday).format('X')<this.fullDate*1){//若可选择日期大于七天前,则重新设置开始时间
                  this.startValue = this.$moment(this.fullDate*1000).startOf('day').format("YYYY-MM-DD");
                  this.start_date = this.$moment(this.startValue).startOf('day').format("X")*1;
                  this.getBackupTimeline();
                  return false
                }
              }
    
              //设置binlog
              let canLine = this.$refs.canLine;
              let binlogStart=this.start_date>this.fullDate?this.start_date:this.fullDate;//binlog开始时间
              let binlogNum = (this.binlogDate-binlogStart)/(this.end_date-this.start_date);//binlog占时间轴百分比
              if(binlogNum>0){//如果选择的时间有binlog
                canLine.style.width = binlogNum*100 + '%' ;
                canLine.style.left = (binlogStart-this.start_date)/(this.end_date-this.start_date)*100 + '%';
                canLine.style.maxWidth =100-parseFloat(canLine.style.left) + '%' ;
              }else{
                canLine.style.width = 0 + '%' ;
                if(dt.incre_dates.length<=0){
                  this.$message.warning('所选时间区间没有可选择时间点,请修改时间区间~');
                  this.showLine = false;
                  this.timeline = null;
                  this.$parent.showLine = true;
                }
              }
    
              //设置备份时间点数组
              this.incre_dates = dt.incre_dates;
              this.allIncre = dt.incre_dates.concat([this.binlogDate,this.fullDate]);//备份时间点加上binlog结束时间点和fullDate
             
              this.clickDot(dt.incre_dates[0]);//设置默认选择点
           
              this.timeline = dt.incre_dates[dt.incre_dates.length-1];
    
              //添加提示时间点---0点提示
              this.dateTips=[];
              let days = Math.abs(this.$moment(this.endValue).endOf('day').diff(this.$moment(this.startValue).startOf('day'), 'days'));
              for(let i=0;i<=days;i++){
                this.dateTips.push(this.$moment(this.startValue).add(i, 'd').startOf('day').format('X'));
              }
            }
            
          });
        },
      
        //点击时间轴---计算百分比
        lineMouseDown(e){
          let allLineTime = this.$refs.allLineTime;
          let percentNum = (e.offsetX-6)/(allLineTime.offsetWidth*1);
         
          this.setSelTime(percentNum);
        },
        //可选择线的区域点击
        canLineMouseDown(e){
          let canLine = this.$refs.canLine;
          let allLineTime = this.$refs.allLineTime;
          let percentNum = e.offsetX/(allLineTime.offsetWidth*1);
          if(parseFloat(canLine.style.left)>0){
            percentNum = e.offsetX/(allLineTime.offsetWidth*1)+(parseFloat(canLine.style.left)/100);
          }
          this.setSelTime(percentNum);
        },
        //点击备份点---计算百分比
        clickDot(incre){
          let percentNum = (incre-this.start_date)/(this.end_date-this.start_date);
          this.setSelTime(percentNum);
        },
        //设置当前值
        setSelTime(percentNum){
          let selDot = this.$refs.selDot;
          selDot.classList.remove('sel_dot_left');
          selDot.classList.remove('sel_dot_right');
    
          let percent = percentNum;
          this.timeline= (this.end_date-this.start_date)*percent+this.start_date;
          //如果当前值不在binlog范围内,则不可以滑动,只能选择就近的点
          if(this.timeline>this.binlogDate || this.timeline<this.fullDate){
            this.allIncre.sort((a,b)=>{
                return Math.abs(a-this.timeline)-Math.abs(b-this.timeline);
            });
            this.timeline = this.allIncre[0];
            percent = (this.timeline-this.start_date)/(this.end_date-this.start_date);
          }
          //设置选中点日期时间
          this.selTime = this.$moment(this.timeline*1000).format('YYYY-MM-DD HH:mm:ss');
          selDot.style.left = percent*100 + '%' ;
    
          //大于90%或者小于10%,提示框位置变化
          if(percent*100<10){
            selDot.classList.add('sel_dot_left');
          }
          if(percent*100>90){
            selDot.classList.add('sel_dot_right');
    
          }
    
        },
        //时间轴推拽
        dragDown(e){
          let allLineTimeWidth = this.$refs.allLineTime.offsetWidth*1;
          let selDot = this.$refs.selDot;
          //算出鼠标相对元素的位置
          let disX = e.clientX - selDot.offsetLeft;
    
          document.onmousemove = (e)=>{//鼠标按下并移动的事件
              //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
              let left = (e.clientX - disX)/allLineTimeWidth*100; 
              
              //移动当前元素
              if(left>=100){
                left = 100;
              }else if(left<=0){
                left = 0;
              }
              this.setSelTime(left/100);
          };
          document.onmouseup = (e) => {
            document.onmousemove = null;
            document.onmouseup = null;
          };
        },
        //设置备份点位置
        setLeft(incre){
          return  `left:${(incre-this.start_date)/(this.end_date-this.start_date)*100}%`
        },
      },
    };
    </script>
    <style lang='scss' scoped>
    .time_con{
      padding-bottom: 20px;
    }
    .line_time{
      position: relative;
      padding: 70px 0 20px;
      -webkit-user-select:none;
       -moz-user-select:none;
       -ms-user-select:none;
       user-select:none;
      .all_line{
        width: 90%;
        margin: 0 5%;
        padding: 20px 0;
      }
      .line{
        width: 100%;
        height: 3px;
        background: #ccc;
        position: relative;
      }
      .can_line{
        background: #1890ff77;
        height: 3px;
        width: 20%;
        position: absolute;
        left: 0;
        span{
          position: absolute;
          right: 0;
          margin-top: 20px;
    
        }
      }
      .reference{
        width: 1px;
        height: 8px;
        border: 0;
        background: #bbb;
        position: absolute;
        top: -3px;
        white-space: nowrap;
        em{
          color: #bbb;
          position: absolute;
          transform: translateX(-50%);
          margin-top: 15px;
          font-size: 12px;
        }
      }
      .dot{
        width: 8px;
        height: 8px;
        border-radius: 50%;
        border: 2px solid $sel_color;
        background: white;
        position: absolute;
        top: -3px;
        white-space: nowrap;
        margin-left: -4px;
      }
      .dot_all{
        em{
          display: none;
          color: $sel_color;
          transform: translateX(-50%);
          margin-top: 25px;
        }
      }
      .dot_all:hover{
        width: 10px;
        height: 10px;
        border: 2px solid $sel_color;
        top: -4px;
        em{
          display: inline-block;
        }
      }
      .sel_dot{
        width: 12px;
        height: 12px;
        top: -5px;
        border: 2px solid $text_yellow;
        box-shadow: 0 0 10px 4px #faa30255;
        z-index: 5;
        position: absolute;
        em{
          position: absolute;
          top: -50px;
          border: 1px solid #ccc;
          display: inline-block;
          padding: 0 20px;
          line-height: 26px;
          border-radius: 13px;
          white-space: nowrap;
          transform: translateX(-50%);
          color: $text_yellow;
        }
        i{
          contain: '';
          border: 1px solid #ccc;
          background: white;
          width: 10px;
          height: 10px;
          display: block;
          position: absolute;
          transform: rotate(45deg);
          bottom: -4px;
          left: 50%;
          border-top: 0;
          border-left: 0;
        }
      }
      .sel_dot_left{
        em{
          transform: translateX(-20%);
        }
        i{
          left: 20%;
        }
      }
      .sel_dot_right{
        em{
          transform: translateX(-80%);
        }
        i{
          left: 80%;
        }
      }
    }
    .ant-calendar-picker{
      margin-left: 20px;
    }
    </style>
    

    转载请著名出处~
    -----*13

    相关文章

      网友评论

          本文标题:使用vue,来写个时间轴

          本文链接:https://www.haomeiwen.com/subject/rjaaiktx.html