Vue自定义时间轴,点击两个点获取时间区间

Vue 自定义时间轴,动态生成纵轴时间轴的时间点,点击时间轴获取时间区间
在这里插入图片描述
data:定义使用变量

	  fullDate: null, //最初时间(最开始有数据的时候)
      binlogDate: null, //binlog 结束时间
      selTime: null, //选中时间

      start_date: null, //开始时间戳
      end_date: null, //结束时间戳
      timeline: null, //选中时间戳
      incre_dates: [], //备份点数组
      increNum: 0, // 选中备份点
      allIncre: [], //备份点和binlog
      showLine: false, //是否显示时间轴
      dateTips: [], //0点,提示时间点数组
      onmouseup: false, // 时间轴上拖拽鼠标是否释放
      timeLine: "", // 时间轴当前值
      isClickTimeLine: true, // 是否可点击时间轴

      timeLineStart: "", // 时间轴筛选开始
      timeLineEnd: "", // 时间轴筛选结束
      timeLineAnalysisList: {} // 筛选过后的数据

js:获取到时间区间中的时间轴点,并且渲染,点击第一次是开始时间,第二次是结束时间,再次点击就是第二次为开始时间,以此类推

// 时间轴筛选时间段
    timeLineFilter() {
      let timeLineStart = "";
      let timeLineEnd = "";
      let timeLineStart0 = "";
      let timeLineEnd0 = "";
      // console.log(
      //   1432,
      //   this.timeLineStart,
      //   this.timeLineEnd,
      //   new Date(this.timeLineStart).getTime(),
      //   new Date(this.timeLineEnd).getTime()
      // );
      // console.log(1438, this.AnalysisList0);
      if (
        new Date(this.timeLineStart).getTime() <
        new Date(this.timeLineEnd).getTime()
      ) {
        timeLineStart = new Date(this.timeLineStart).getTime();
        timeLineEnd = new Date(this.timeLineEnd).getTime();
        timeLineStart0 = this.timeLineStart;
        timeLineEnd0 = this.timeLineEnd;
      } else {
        timeLineStart = new Date(this.timeLineEnd).getTime();
        timeLineEnd = new Date(this.timeLineStart).getTime();
        timeLineStart0 = this.timeLineEnd;
        timeLineEnd0 = this.timeLineStart;
      }
      let timeLineStartA = new Date(timeLineStart0.split(" ")[0]).getTime();
      let timeLineEndA = new Date(timeLineEnd0.split(" ")[0]).getTime();
      let boolA = false;

      // 重新赋值原数据
      this.timeLineAnalysisList = JSON.parse(
        JSON.stringify(this.AnalysisList0)
      );
      let timeLineAnalysisList = JSON.parse(JSON.stringify(this.AnalysisList0));

      if (this.isScreenMethod == 0) {
        // 按日期
        this.timeLineAnalysisList.beginTime = timeLineStart0.split(" ")[0];
        this.timeLineAnalysisList.endTime = timeLineEnd0.split(" ")[0];
        if (
          timeLineEnd - timeLineStart > 1 * 24 * 60 * 60 * 1000 ||
          timeLineEndA !== timeLineStartA
        ) {
          let arr = [];
          arr = timeLineAnalysisList.statsDateList.filter(i => {
            let clickDate = new Date(i.date).getTime();
            if (clickDate >= timeLineStartA && clickDate <= timeLineEndA) {
              return i;
            }
          });
          this.timeLineAnalysisList.statsDateList = arr;
          boolA = false;
          // console.log(1479, arr);
        } else {
          let arr = [];
          let arrTimes = [];
          arr = timeLineAnalysisList.statsDateList.filter(i => {
            let clickDate = new Date(i.date).getTime();
            if (clickDate >= timeLineStartA && clickDate <= timeLineEndA) {
              i.statsTimeList.forEach(item => {
                const times = new Date(item.time).getTime();
                if (times >= timeLineStart && times <= timeLineEnd) {
                  arrTimes.push(item);
                }
              });
              i.statsTimeList = arrTimes;
              return i;
            }
          });
          this.timeLineAnalysisList.statsDateList = arr;
          boolA = true;
          // console.log(1498, arr);
        }
      } else {
        // 按课节
        this.timeLineAnalysisList.beginTime = timeLineStart0;
        this.timeLineAnalysisList.endTime = timeLineEnd0;
        // this.AnalysisList.beginTime = this.startDate + " " + this.timeLineStart;
        // this.AnalysisList.endTime = this.startDate + " " + this.timeLineEnd;
        let arr = [];
        let arrTimes = [];
        // console.log(1508, this.AnalysisList0);
        arr = timeLineAnalysisList.statsDateList.filter(i => {
          let clickDate = new Date(i.date).getTime();
          if (clickDate >= timeLineStartA && clickDate <= timeLineEndA) {
            i.statsTimeList.forEach(item => {
              const times = new Date(item.time).getTime();
              if (times >= timeLineStart && times <= timeLineEnd) {
                arrTimes.push(item);
              }
            });
            i.statsTimeList = arrTimes;
            return i;
          }
        });
        this.timeLineAnalysisList.statsDateList = arr;
        // console.log(1521, arr);
      }
      this.AnalysisList = this.timeLineAnalysisList;
      // 处理图表数据
      // this.updatedData(this.AnalysisList, boolA);
    },
//时间显示格式
    formatter(value, day, hours) {
      if (day) {
        return `${this.$moment(value * 1000).format("YYYY/MM/DD")}`;
      } else if (hours) {
        return `${this.$moment(value * 1000).format("HH:mm:ss")}`;
      } else {
        return `${this.$moment(value * 1000).format("YYYY/MM/DD HH:mm:ss")}`;
      }
    },
    // 滑动点的鼠标进入
    dragEnter() {
      let aa = this.$refs.selDotEm;
      aa.style.display = "block";
    },
    // 滑动点的鼠标移出
    dragLeave() {
      let aa = this.$refs.selDotEm;
      aa.style.display = "none";
    },
    //获取时间轴数据
    getBackupTimeline() {
      // console.log(2004, this.startDate);
      this.showLine = true;
      this.start_date =
        this.$moment(this.startDate)
          .startOf("day")
          .format("X") * 1;
      this.end_date =
        this.$moment(this.endDate)
          .endOf("day")
          .format("X") * 1;
      //请求成功
      let arrA = [];
      // console.log(this.AnalysisList);
      // for (let i = 0; i < this.AnalysisList.statsDateList.length; i++) {
      //   const ele = this.AnalysisList.statsDateList[i];
      //   if (ele.statsTimeList ? ele.statsTimeList.length > 0 : false) {
      //     for (let m = 0; m < ele.statsTimeList.length; m++) {
      //       const element = ele.statsTimeList[m];
      //       let str = element.time;
      //       arrA.push(str);
      //     }
      //   }
      // }
      arrA = [this.startDate, this.endDate];
      // console.log(701, arrA);
      // let dt = JSON.parse(JSON.stringify(r.data.data));
      let dt = [
        {
          incre_dates: arrA
        }
      ];

      //设置binlog
      let allLineTime = this.$refs.allLineTime;
      let canLine = this.$refs.canLine;
      this.fullDate =
        (new Date(this.startDate).getTime() - 24 * 1000 * 60 * 60) / 1000;
      this.binlogDate =
        (new Date(this.endDate).getTime() + 24 * 1000 * 60 * 60) / 1000;
      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占时间轴百分比
      // console.log(
      //   1944,
      //   this.start_date,
      //   this.end_date,
      //   this.fullDate,
      //   this.binlogDate,
      //   binlogStart,
      //   binlogNum,
      //   this.start_date > this.fullDate,
      //   this.binlogDate - binlogStart,
      //   this.end_date - this.start_date
      // );
      if (binlogNum > 0) {
        //如果选择的时间有binlog
        let atime = new Date(this.startDate).getTime();
        let btime = new Date(this.endDate).getTime();
        let num = btime - atime;

        if (parseInt(num / (1000 * 60 * 60 * 24)) <= 2) {
          allLineTime.style.height = (binlogNum / 2) * 100 + "%";
        } else if (parseInt(num / (1000 * 60 * 60 * 24)) <= 8) {
          allLineTime.style.height = binlogNum * 100 + "%";
        } else if (parseInt(num / (1000 * 60 * 60 * 24)) < 15) {
          allLineTime.style.height = binlogNum * 2 * 100 + "%";
        } else if (parseInt(num / (1000 * 60 * 60 * 24)) < 25) {
          allLineTime.style.height = binlogNum * 3 * 100 + "%";
        } else {
          allLineTime.style.height = binlogNum * 4 * 100 + "%";
        }
        canLine.style.height = binlogNum * 100 + "%";
        canLine.style.top =
          ((binlogStart - this.start_date) /
            (this.end_date - this.start_date)) *
            100 +
          "%";
        canLine.style.maxHeight = 100 - parseFloat(canLine.style.top) + "%";
        // console.log(426, binlogNum);
      } else {
        canLine.style.height = 0 + "%";
        if (dt[0].incre_dates.length <= 0) {
          this.$Message.warning({
            top: 100,
            content: "所选时间区间没有可选择时间点,请修改时间区间~"
          });
          this.showLine = false;
          this.timeline = null;
          this.$parent.showLine = true;
        }
      }

      //设置备份时间点数组
      this.incre_dates = [];
      // this.incre_dates = dt[0].incre_dates;
      let increDates0 = JSON.parse(JSON.stringify(dt[0].incre_dates));
      for (let t = 0; t < increDates0.length; t++) {
        // const element = new Date(increDates0[t]).getTime() / 1000;
        const element = this.$moment(increDates0[t]).format("X");
        this.incre_dates.push(element);
      }
      this.allIncre = dt[0].incre_dates.concat([
        this.binlogDate,
        this.fullDate
      ]); //备份时间点加上binlog结束时间点和fullDate

      // console.log(
      //   808,
      //   dt[0].incre_dates,
      //   this.$moment("2021-11-20 15:00").format("X"),
      //   this.incre_dates[this.incre_dates.length - 1]
      // );
      this.clickDot(this.incre_dates[this.incre_dates.length - 1]); //设置默认选择点
      // console.log(this.startDate);
      this.timeLineStart = this.startDate + " 00:00";
      this.timeLineEnd = increDates0[increDates0.length - 1] + " 23:59";

      this.timeline = dt[0].incre_dates[dt[0].incre_dates.length - 1];

      //添加提示时间点---0点提示
      this.dateTips = [];
      let days = Math.abs(
        this.$moment(this.endDate)
          .endOf("day")
          .diff(this.$moment(this.startDate).startOf("day"), "days")
      );
      for (let i = 0; i <= days; i++) {
        this.dateTips.push(
          this.$moment(this.startDate)
            .add(i, "d")
            .startOf("day")
            .format("X")
        );
      }
    },
    //点击时间轴---计算百分比
    lineMouseDown(e) {
      let allLineTime = this.$refs.allLineTime;
      let percentNum = (e.offsetY + 6) / (allLineTime.offsetHeight * 1);

      // this.setSelTime(percentNum);
    },
    //可选择线的区域点击
    canLineMouseDown(e) {
      // console.log(2048);
      this.onmouseup = true;
      let canLine = this.$refs.canLine;
      let allLineTime = this.$refs.allLineTime;
      let percentNum = e.offsetY / (allLineTime.offsetHeight * 1);
      if (parseFloat(canLine.style.top) > 0) {
        percentNum =
          e.offsetY / (allLineTime.offsetHeight * 1) +
          parseFloat(canLine.style.top) / 100;
      }
      if (this.isClickTimeLine) {
        this.setSelTime(percentNum);
      }
    },
    //点击备份点---计算百分比
    clickDot(incre) {
      let percentNum =
        (incre - this.start_date) / (this.end_date - this.start_date);
      if (this.isClickTimeLine) {
        this.setSelTime(percentNum);
      }
    },
    //设置当前值
    setSelTime(percentNum) {
      let selDot = this.$refs.selDot;
      selDot.classList.remove("sel_dot_left");
      selDot.classList.remove("sel_dot_right");
      // return;
      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"
      );

      // 当前值
      let selTime =
        this.selTime.split(":")[0] + ":" + this.selTime.split(":")[1];
      // console.log(2214, selTime);
      this.timeLine = selTime;
      if (this.onmouseup === true) {
        this.onmouseup = false;
        if (this.timeLineEnd) {
          this.timeLineStart = this.timeLineEnd;
          this.timeLineEnd = this.timeLine;
        } else {
          this.timeLineStart = this.startDate;
          this.timeLineEnd = this.timeLine;
        }
        // console.log(this.timeLineStart, this.timeLineEnd);
        let dt = [];
        dt = [{ incre_dates: [this.timeLineStart, this.timeLineEnd] }];
        //设置备份时间点数组
        this.incre_dates = [];
        // this.incre_dates = dt[0].incre_dates;
        let increDates0 = JSON.parse(JSON.stringify(dt[0].incre_dates));
        for (let t = 0; t < increDates0.length; t++) {
          // const element = new Date(increDates0[t]).getTime() / 1000;
          const element = this.$moment(increDates0[t]).format("X");
          this.incre_dates.push(element);
        }
        this.allIncre = dt[0].incre_dates.concat([
          this.binlogDate,
          this.fullDate
        ]); //备份时间点加上binlog结束时间点和fullDate
        this.timeLineFilter();
      }

      // let today = new Date();
      // let forToday = this.$moment(today).subtract(7, "d");
      // let dd = this.$moment(forToday).format("X");
      // console.log(this.$moment(new Date(this.startDate)).subtract(7, "d"));
      if (
        new Date(this.endDate).getTime() - new Date(this.startDate).getTime() >
        10 * 24 * 60 * 60 * 1000
      ) {
        selDot.style.top = (percent - 0.005) * 100 + "%";
      } else {
        selDot.style.top = (percent - 0.01) * 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 allLineTimeHeight = this.$refs.allLineTime.offsetHeight * 1;
      let selDot = this.$refs.selDot;
      //算出鼠标相对元素的位置
      let disY = e.clientY - selDot.offsetTop;

      if (this.isClickTimeLine) {
        document.onmousemove = e => {
          //鼠标按下并移动的事件
          //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
          let top = ((e.clientY - disY) / allLineTimeHeight) * 100;

          //移动当前元素
          if (top >= 100) {
            top = 100;
          } else if (top <= 0) {
            top = 0;
          }
          // if (this.isClickTimeLine) {
          this.setSelTime(top / 100);
          // }
        };
        this.onmouseup = false;
        // console.log(2124);
        // console.log(2124);
        document.onmouseup = e => {
          // console.log("onmouseup");
          this.onmouseup = true;
          if (this.onmouseup === true) {
            this.onmouseup = false;
            if (this.timeLineEnd) {
              this.timeLineStart = this.timeLineEnd;
              this.timeLineEnd = this.timeLine;
            } else {
              this.timeLineStart = this.startDate;
              this.timeLineEnd = this.timeLine;
            }
            // console.log(this.timeLineStart, this.timeLineEnd);
            let dt = [];
            dt = [{ incre_dates: [this.timeLineStart, this.timeLineEnd] }];
            //设置备份时间点数组
            this.incre_dates = [];
            // this.incre_dates = dt[0].incre_dates;
            let increDates0 = JSON.parse(JSON.stringify(dt[0].incre_dates));
            for (let t = 0; t < increDates0.length; t++) {
              // const element = new Date(increDates0[t]).getTime() / 1000;
              const element = this.$moment(increDates0[t]).format("X");
              this.incre_dates.push(element);
            }
            this.allIncre = dt[0].incre_dates.concat([
              this.binlogDate,
              this.fullDate
            ]); //备份时间点加上binlog结束时间点和fullDate
            this.timeLineFilter();
          }
          document.onmousemove = null;
          document.onmouseup = null;
        };
      }
    },
    //设置备份点位置
    setLeft(incre) {
      return `top:${((incre - this.start_date) /
        (this.end_date - this.start_date)) *
        100}%`;
    },
    

html:筛选时间区间,生成时间轴的点

    // iview 时间选择器
    <div class="Condition">
        <div class="conditionLeft">
          <DatePicker
            :editable="false"
            :clearable="false"
            type="date"
            format="yyyy-MM-dd"
            :placeholder="isScreenMethod == 0 ? '开始日期' : '时间选择'"
            style="width: 150px"
            :value="startDate"
            v-model="startDate"
            :options="startTimeOptions"
            @on-change="startTimeChange"
          ></DatePicker>
          <span v-if="isScreenMethod == 0">-</span>
          <DatePicker
            :editable="false"
            :clearable="false"
            type="date"
            format="yyyy-MM-dd"
            v-if="isScreenMethod == 0"
            placeholder="结束日期"
            style="width: 150px"
            :options="endTimeOptions"
            v-model="endDate"
            :value="endDate"
            @on-change="endTimeChange"
          ></DatePicker>
        </div>
      </div>
      
    // 时间轴
    <div class="pageBottom">
      <div class="time_con">
        <div class="line_time">
          <div style="height: 100%;padding: 0px 10px;">
            <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 class="can_lineWidth"></div>
                </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"
                  @mouseenter="dragEnter"
                  @mouseleave="dragLeave"
                >
                  <em ref="selDotEm">{{ selTime }}<i></i></em>
                </div>
              </div>
            </div>
          </div>
        </div>
    </div>
</div>

css: 时间轴样式

/* 左侧 */
.line_time {
  width: 10%;
  height: 100%;
  position: relative;
  padding: 10px 0 20px;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  overflow-y: auto;
  overflow-x: hidden;
}
.line_time .all_line {
  height: 100%;
  /* margin: 0 5%; */
  padding: 20px 0;
  display: flex;
  justify-content: flex-end;
  /* overflow-y: auto; */
}
.line_time .line {
  height: 100%;
  width: 3px;
  background: url("../../assets/img/smart/vertical_icon@2x.png") no-repeat;
  background-size: cover;
  position: relative;
}
.line_time .can_line {
  /* background: linear-gradient(0deg, #072a76 0%, #041d53 46%, #02194c 100%); */
  width: 50px;
  height: 20%;
  margin-left: -23px;
  position: absolute;
  top: 0;
  z-index: 1;
}
.line_time .can_line span {
  position: absolute;
  bottom: 0;
  margin-top: 20px;
}
.can_lineWidth {
  width: 3px;
  background: linear-gradient(0deg, #072a76 0%, #041d53 46%, #02194c 100%);
  height: 100%;
  margin: 0 auto;
}
.line_time .reference {
  height: 1px;
  width: 8px;
  border: 0;
  background: #bbb;
  position: absolute;
  top: -3px;
  white-space: nowrap;
}
.line_time .reference em {
  height: 55px;
  width: 130px;
  color: #bbb;
  position: absolute;
  top: -25px;
  transform: translateX(-80%);
  /* margin-top: 15px; */
  font-size: 12px;
  background-image: url("../../assets/img/timeLine/label_icon@3x.png");
  background-size: 100% 100%;
  display: flex;
  align-items: center;
  padding-left: 10px;
  color: #2bf6ff;
  font-size: 12px;
}
.line_time .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  /* border: 2px solid $sel_color; */
  /* background: #2efeff; */
  position: absolute;
  top: -3px;
  white-space: nowrap;
  margin-left: -4px;
  z-index: 1;
}
.line_time .dot_all {
  background: #2efeff;
}
.line_time .dot_all em {
  display: none;
  /* color: $sel_color; */
  transform: translateX(-50%);
  margin-top: 25px;
}
.line_time .dot_all:hover {
  width: 10px;
  height: 10px;
  color: #2efeff;
  /* border: 2px solid $sel_color; */
  /* left: 10px; */
}
.line_time .dot_all:hover em {
  display: inline-block;
}
.line_time .sel_dot {
  width: 28px;
  height: 25px;
  top: -5px;
  left: -4px;
  /* border: 2px solid $text_yellow; */
  /* box-shadow: 0 0 10px 4px #faa30255; */
  z-index: 5;
  position: absolute;
  background-image: url("../../assets/img/timeLine/pointing_icon@3x.png");
  background-size: 100% 100%;
  background-color: initial;
}
.line_time .sel_dot em {
  position: absolute;
  top: -22px;
  left: -25px;
  border: 1px solid #ccc;
  display: inline-block;
  padding: 0 20px;
  line-height: 26px;
  border-radius: 13px;
  white-space: nowrap;
  transform: translateX(-50%);
  color: #fff;
}
.line_time .sel_dot i {
  contain: "";
  border: 1px solid #ccc;
  background: white;
  width: 10px;
  height: 10px;
  display: block;
  position: absolute;
  transform: rotate(45deg);
  left: 4px;
  top: 30%;
  border-top: 0;
  border-left: 0;
}
/* .line_time .sel_dot_left em { */
/* transform: translateY(-20%); */
/* } */
.line_time .sel_dot_left i {
  top: 20%;
}
/* .line_time .sel_dot_right em { */
/* transform: translateY(-80%); */
/* } */
.line_time .sel_dot_right i {
  top: 80%;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值