持续更新中。。。
上代码:https://github.com/scrollHeart/timeSplit
一、需求:
1.做一个00:00-24:00时间轴表,可进行时段拆分和删除
2.时间轴上的时刻可用手柄拖动
3.拆分规则:折中间时刻拆分成2个时间段,可拆分时段<10个,最小拆分时间粒度为15min
4.删除规则:删除该时段,此时段时间向后一时段合并,生成新时段
5.拖动规则:不得超出时间轴,最小时间粒度宽度太小时,可设置最小宽度,方便查看时间段
二、实现思路:
1.计算每秒对应的像素值,画出各时段宽度和刻度
2.编辑时,拖动手柄,重新计算各时段宽度和刻度
3.时间规则化和合理化(消除类似12:60时间的显示)
4.拆分时段,宽度和刻度计算
5.删除时段,宽度和刻度计算
6.当拆分粒度达到最小粒度时,时间段宽度很小,设置最小宽度,并确保总宽度不超出时间轴
- 以上这些在代码里都可看见,下面解释下计算宽度差额的简单算法思路
三、计算宽度差额的简单算法思路
起因:总宽度固定的,保证各时段正常展示且不超出总时间轴宽度,需要对各时段宽度进行检验和处理差额
思路:
1.先统一向后补齐宽度差额,当前时段不够最小宽度,向其邻近的下一个时段借宽度差,若邻近下一个时段仍然不够减,继续向后借,直到最后一个时段;
2.若最后一个时段仍然不够减,跳到出现差额的时段邻近的前一个时段,依次向前借差额
代码段:
methods: {
// 向前找回宽度差
findPrevWidthCapFn(p, s, obj) {
// 向前一时段找回宽度差,若前一时段宽度也小于最小宽度,则继续向前找
if (p >= 0) {
if (!obj[p].widthGap) {
if (obj[p].width >= obj[s].widthGap + this.miniLength) {
obj[p].width = obj[p].width - obj[s].widthGap;
}
else {
if (p > 0) {
// 向前一时段找回宽度差
p--;
// 继续向前找
this.findPrevWidthCapFn(p, s, obj);
}
}
}
else {
if (p > 0) {
// 向前一时段找回宽度差
p--;
// 继续向前找
this.findPrevWidthCapFn(p, s, obj);
}
}
}
},
// 向后找回宽度差
findNextWidthGapFn(newVal, p, s, n, obj) {
if (n <= newVal.length - 1) {
if (!obj[n].widthGap) {
if (obj[n].width >= obj[s].widthGap + this.miniLength) {
obj[n].width = obj[n].width - obj[s].widthGap;
}
else {
if (n >= newVal.length - 1) {
// 最后一个时段,仍无法处理宽度差额,向最小宽度的时段索引前找
p = s - 1;
// 向前一时段找回宽度差,若前一时段宽度也小于最小宽度,则继续向前找
this.findPrevWidthCapFn(p, s, obj);
}
else {
// 向后一时段找回宽度差
n++;
// 继续向后找
this.findNextWidthGapFn(newVal, p, s, n, obj);
}
}
}
else {
if (n >= newVal.length - 1) {
// 最后一个时段,仍无法处理宽度差额,向最小宽度的时段索引前找
p = s - 1;
this.findPrevWidthCapFn(p, s, obj);
}
else {
// 向后一时段找回宽度差
n++;
// 继续向后找
this.findNextWidthGapFn(newVal, p, s, n, obj);
}
}
}
},
// 每个时段检查是否有宽度差额
checkWidthGapFn(i, s, p, n, newVal, obj) {
// 设置当前时段宽度
if (obj[i].widthGap) {
s = i;
if (i >= newVal.length - 1) {
// 最后一个时段,向前找
p = i - 1;
// 向前一时段找回宽度差,若前一时段宽度也小于最小宽度,则继续向前找
// this.findPrevWidthCapFn(p);
console.log(this, 'this')
this.findPrevWidthCapFn(p, s, obj)
}
else {
n = i + 1;
// 继续向后找
// this.findNextWidthGapFn(n);
this.findNextWidthGapFn(newVal, p, s, n, obj)
}
}
},
// 计算整个时段表的宽度数组
updateWidthList(newVal) {
let list = [];
let obj = {};
newVal.forEach((item, index) => {
let period = item;
period.start_time = this.standardTime(period.start_time);
period.end_time = this.standardTime(period.end_time);
let second = (this.$moment(period.end_time, 'HH:mm')
- this.$moment(period.start_time, 'HH:mm')) / 1000;
obj[index] = {'second': second};
if (this.PTR * second < this.miniLength) {
obj[index].widthGap = this.miniLength - this.PTR * second;
obj[index].width = this.miniLength;
}
else {
obj[index].width = this.PTR * second;
}
});
// 初始化有宽度差的时段索引
// const _this = this;
let i = 0; // 遍历当前时段索引
let s = 0; // 取最小宽度的时段索引
let n = 0; // 向后查找时段索引,处理宽度差额
let p = 0; // 向前查找时段索引,处理宽度差额
for (let i = 0; i < newVal.length; i++) {
// testFn(i);
// 每个时段检查是否有宽度差额
this.checkWidthGapFn(i, s, p, n, newVal, obj);
}
for (let key in obj) {
if (obj[key].width) {
list.push(obj[key].width);
}
else {
list.push(obj[key].second * this.PTR);
}
}
this.widthList = list;
},
},
watch: {
timeList:{
immediate: false,
deep: true,
handler(newVal) {
//计算整个时段表的宽度数组
this.updateWidthList(newVal)
}
}
}
网友评论