一个多段时间范围选择的另类组件实现

1,291 阅读4分钟

近来, 在业务场景中遇到了这么个事儿。

一个时间规则的设置功能:
通过点击滑动的方式来对某某时段进行编辑

**最终效果如下图: **

2021-06-23-10-45-22.gif

当得知这个需求的第一反应,我想到了ElementUI中的date-picker,这不一样样的嘛?

于是,我仅仅用了不到三秒的时间便打开了element的date-picker源码...

洋洋洒洒上千行。

嗯,我放弃了...

不过并不是一无所获,我敏锐地看到了一个再熟悉不过的单词,mousemove! 有了想法,那便开始。

第一步:
首先,需要一个存储所有时间段的数组,每一个时间段都有以下几个属性:
{ start: // 起点 end: // 终点 ...params //剩余的参数,例如给某个时间段设置某些属性值 }
第二步:
要开始点击了

问题来了,在新建一个时间段的时候,第一次点击为新建,而第二次点击则是结束当前时间段的编辑。

这时候,要考虑到一个情况,当第一次点击的时候点击到了已经存在的时间段上,应该是修改操作。

于是,我们可以设置一个flag标识,用来标记当前的点击是属于移动阶段还是结束阶段,并加入了一个判断,判断当前操作的地方是否是已经存在的组。

左键点击代码如下(这里面包含了一些时间段数量的限制以及一些业务方面的东西,可以忽略):

1624425272(1).jpg

新建的同时,自然而然会遇到插入的问题,也就是当前新建的组可能在任何一个地方。

那么,问题又来了。

怎么判断当前点击的位置是已经存在了的时间段呢?
同时衍生出来的另外两个问题:
(1)如何给当前所有已经选中的目标点加样式
(2)开头和结束的样式是不同的

于是,我建立了三个对象,分别用来存放开始的标记点,结束的标记点,以及所有被选中了的标记点,并且记录下他们所在的组的索引值。

1624425760(1).jpg

1624425828(1).jpg

在存放时间段的数组变化的同时,将所有需要用到的标记点对号入座。

1624425912(1).jpg 将对应的类名添加到各个标记点上。

至此,上面的问题便解决了。

第三步:
重头戏来了,开始滑动。

滑动遇到的第一个问题是,在有了开始点之后,鼠标可以往这一点的前方滑动,也可以往后面滑动,对应的开始和结束的样式也要对应的改变(参考date-picker的表现形式)。

这一点,只要判断时间段结束点比开始点小,则切换两个的数据,并将当前滑动中修改的值改为修改start的值即可。
(这里要注意,默认的滑动修改的值是时间段的end,在这里进行方向的切换)

1624426207(1).jpg

第四步:
看上图中的check函数,这里是处理在滑动过程中,出现了组与组的覆盖的情况时,要进行的逻辑判断及表现。

这里的大致逻辑为:
(1)当覆盖的时候,当前正在操作的组会将覆盖的组逼退,大家也许能从最开始的预览图中看出一二。
(2)当从覆盖状态变为分离状态的时候,原本被逼退的分组要还原回来(可以看到在点击操作的时候,进行了一次数据保存)。
(3)当确定覆盖之后,分组的状态更新为最后的模样。

1624426693(1).jpg

至此,选择时间段的功能便大体实现了,无非中间加了一些业务相关的逻辑。

当然,这个组件并没有完全完成。

第五步:

右键会弹出菜单,菜单有删除功能,也可以针对某个时间段设置一些属性。
这些便不在这里记录了,代码也很简单,我的实现方式是在右键点击的同时获取到鼠标的位置,然后弹出菜单。

至于删除,直接对数组进行操作即可。

最后,奉上一些用到了的工具函数:

1624427462(1).jpg

总结

前前后后,这个组件花了大约两天的时间,特此记录一下。

还有很多可以优化的地方,后续改进。