背景
公司要求做日程模块的移动端展示,当天日程按照时间轴加载出来,单个时间端占满宽度,两个日程冲突时平分宽度。
思路
- 写出时间轴做背景单个高度为40px
- 日程用绝对定位加载高度为日程时长(例如:11:00-13:00时长为2小时)公式为
(beginTime.getTime()-endTime.getTime())/1000/60/60*40
- 同理Top为11:00与00:00的差
- 宽度为展示区域的宽度,同一时间段日程平分即 宽度除以同一时间的日程数
- Left为 固定的居左距离+(左侧冲突日程数-1)*平均宽度
注意点
- 注意因为只展示今日的跨天日程如(2019-10-14 18:00 ~ 2019-10-15 08:00)开始时间统一处理为2019-10-15 00:00
- 同一时间日程有可能冲突
- 宽度不是固定的如:8:00 - 10:00、12:00-15:00 、13:00-16:00 展示形状应该是一个“T”形
代码简述
核心代码目的把日程按照时间不冲突分成多列
this.daydata.forEach(itm => {
const todayBegin = this.daydata.date.getTime()
const todayEnd = this.daydata.date.getTime() + (24 * 60 * 60 * 1000)
const realBegin = itm.realStartTime.getTime()
const realEnd = itm.realEndTime.getTime()
// 只保留当日的时间范围
itm.todayBegin = (todayBegin > realBegin ? todayBegin : realBegin)
itm.todayEnd = (realEnd > todayEnd ? todayEnd : realEnd)
// 是否创建新列
let add = true
clos.forEach(it => {
// 是否有交集,有交集创建新列,无交集拼接 此时数据会出现重复
let intersection = false
it.forEach(i => {
if ((i.todayEnd > itm.todayBegin && i.todayEnd < itm.todayEnd) || (i.todayBegin < itm.todayBegin && i.todayEnd > itm.todayEnd) || (i.todayBegin > itm.todayBegin && i.todayBegin < itm.todayEnd)) {
intersection = true
}
})
if (!intersection) {
add = false
it.push(itm)
}
})
if (add) {
clos.push([itm])
}
})
最初算法
/**判断所有可能相交的情况
* 1. A[1,5], B[4,8] A尾部与B首部相交(A1端必须在[B1,B2]之间)
* 2. A[1,5], B[2,4] A包含B(B的两个端点都位于A中)
* 3. A[2,5], B[1,3] A首部与B尾部相交(A1端必须在[B1,B2]之间)
* 4. A[4,5], B[1,8] A被包含于B (同2)
**/
if ((i.todayEnd > itm.todayBegin && i.todayEnd < itm.todayEnd) || (i.todayBegin < itm.todayBegin && i.todayEnd > itm.todayEnd) || (i.todayBegin > itm.todayBegin && i.todayBegin < itm.todayEnd)) {
intersection = true
}
算法优化:
it.forEach(i => {
if (Math.max(i.todayBegin, itm.todayBegin) < Math.min(i.todayEnd, itm.todayEnd)) {
intersection = true
}
})
数据分列后时间上不再冲突,合并重复数据,计算宽度根据定位加载数据
网友评论