如何实现钉钉日程的摆列效果?

755 阅读4分钟

进入正题,以下是钉钉日程的大致效果,该效果如何实现?

通过图中可以大致看到有以下几点需要考虑

  • 任务块的高度会依据任务的起始时间和结束时间自动计算
  • 任务块的宽度会根据当前任务时间段是否有冲突而自动计算,如果在同一时间有二个任务,则每个任务占总宽度的50%(如图任务1、2、3、4),即时间段的宽度 = 总宽度/该时间区间有多少个任务
  • 如果任务耗时<30min,则固定任务块的高度为30min的高度(图中所示任务6)

实现思路:

  • 考虑到每一个任务块的位置都是根据起始时间与任务所在时间段内是否有其他会议进行摆放的,所以使用绝对布局,通过控制每个任务块的top与left进行相应的展示
  • 而比较难处理的部分就是同一时间段有好几个任务时的展示逻辑,以下是大致的思路
    • 遍历activeStageData获取所有会议的id得到allId;
    • 对activeStageData的每项间相互比较,判断二者的任务时间(endTime-beginTime)是否重叠,将重叠的任务id(item1.id, item2.id) push至zoneOverlappingArr;
    • 对二维数组zoneOverlappingArr的每项进行遍历判断相互间是否包含重复的任务id,如果存在重复的任务id,则合并二个数组;得到zoneOverlappingArr;
    • 对zoneOverlappingArr进行降维得到flattenZoneOverlappingArr;
    • 取allId与flattenZoneOverlappingArr的差集的得到zoneOnlyOneArr(代表该时间段里只有一个任务)
    • allStageGroupId = [zoneOnlyOneArr, ...zoneOverlappingArr];
    • 遍历activeStageData,对每项计算width、height、top、left。
      • height = (endTime - beginTime)/3600000 * stageHeight;
      • top=HH* stageHeight + MM* stageHeight/60;(根据beginTime得到相应的小时HH与分钟MM);
      • 在zoneOverlappingArr与任务id获得idInStageGroupInfo,idInStageGroupInfo主要包括对应的索引以及所对应的数组。
      • 通过idInStageGroupInfo即可获得对应的width与left

以上就是实现类似效果的思路;如有其他的实现思路欢迎交流。

实现效果图

测试数据

    activeStageData = [{
	"id": "task-000",
	"beginTime": 1581356700000,
	"endTime": 1581360300000,
	"summary": "任务"
}, {
	"id": "task-111",
	"beginTime": 1581357600000,
	"endTime": 1581361200000,
	"summary": "任务1"
}, {
	"id": "task-222",
	"beginTime": 1581357600000,
	"endTime": 1581361200000,
	"summary": "任务2"
}, {
	"id": "task-333",
	"beginTime": 1581363000000,
	"endTime": 1581366600000,
	"summary": "任务3"
}, {
	"id": "task-444",
	"beginTime": 1581363960000,
	"endTime": 1581367560000,
	"summary": "任务4"
}, {
	"id": "task-555",
	"beginTime": 1581368400000,
	"endTime": 1581372000000,
	"summary": "任务5"
}, {
	"id": "task-666",
	"beginTime": 1581372900000,
	"endTime": 1581374700000,
	"summary": "任务6"
}];

每个步骤处理后的数据

步骤 数据
1 allId = ["task-000", "task-111", "task-222", "task-333", "task-444", "task-555", "task-666"]
2 zoneOverlappingArr = [["task-000","task-111"],["task-000","task-222"],["task-111","task-222"],["task-333","task-444"]]
3 zoneOverlappingArr = [["task-000","task-111","task-222"],["task-333","task-444"]]
4 flattenZoneOverlappingArr = ["task-000","task-111","task-222","task-333","task-444"]
5 zoneOnlyOneArr = ["task-555", "task-666"]
6 allStageGroupId = [["task-555","task-666"],["task-000","task-111","task-222"],["task-333","task-444"]]
7 最终结果数据

结果数据

最终结果:
[{
	"id": "task-000",
	"beginTime": 1581356700000,
	"endTime": 1581360300000,
	"summary": "任务",
	"width": "25.67%",
	"left": "16%",
	"positionTop": 203,
	"meetingStageHeight": 95
}, {
	"id": "task-111",
	"beginTime": 1581357600000,
	"endTime": 1581361200000,
	"summary": "任务1",
	"width": "25.67%",
	"left": "42.67%",
	"positionTop": 228,
	"meetingStageHeight": 95
}, {
	"id": "task-222",
	"beginTime": 1581357600000,
	"endTime": 1581361200000,
	"summary": "任务2",
	"width": "25.67%",
	"left": "69.34%",
	"positionTop": 228,
	"meetingStageHeight": 95
}, {
	"id": "task-333",
	"beginTime": 1581363000000,
	"endTime": 1581366600000,
	"summary": "任务3",
	"width": "39.00%",
	"left": "16%",
	"positionTop": 378,
	"meetingStageHeight": 95
}, {
	"id": "task-444",
	"beginTime": 1581363960000,
	"endTime": 1581367560000,
	"summary": "任务4",
	"width": "39.00%",
	"left": "56%",
	"positionTop": 404.6666666666667,
	"meetingStageHeight": 95
}, {
	"id": "task-555",
	"beginTime": 1581368400000,
	"endTime": 1581372000000,
	"summary": "任务5",
	"width": "80%",
	"left": "16%",
	"positionTop": 528,
	"meetingStageHeight": 95
}, {
	"id": "task-666",
	"beginTime": 1581372900000,
	"endTime": 1581374700000,
	"summary": "任务6",
	"width": "80%",
	"left": "16%",
	"positionTop": 653,
	"meetingStageHeight": 47.5
}]