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%;
}