前言前些时间导师接了一个数字孪生的小项目,让我一个人完成前端三维隧道看板以及填报系统的构建。
技术路线:vue element admin + element ui + arcgis api for javascript。
最近项目接近尾声,我记录一下之前遇到一下项目过程中犯得一个幼稚的错误。
需求前端实现一个日期滑块,要能选择开始和结束日期,通过滑动日期滑块选择某日期前所有模型的显隐,达到模拟施工进度的效果。
ps:模型属性没日期,需要将日期传给后端,然后后端返回模型的链接以及模型 id。
思路说多了,继续回到标题。制作一个日期滑块,自然而然地想到了利用 elemnet ui 的datepiker 组件和slider 组件。Datepiker 负责选择起始日期,然后将选择的日期传给 slider,然后调用 slider 组件的 input 方法,将日期轴上变化的时间传给后端。So easy,看来今天能早点下班。
◎ element-ui-slider组件
◎ element-ui-datepiker组件
结果等我想传值的时候,突然发现 slider 的绑定值是 number 类型,但是一年 365 天的日期不连续,甚至偶尔还有 366 天出来捣乱,我该怎么将日期跟 number 关联上?最开始的想法是计算起始日期给和 slider 绑定的 value 计算硬算出当前日期,后来考虑到大小月平闰年的,属实不现实,我直呼做不了。
但是甲方直呼 arcgis api 有现成的sample 啊,他们是怎么做到?我看了看确实有时间轴,也确实能过滤要素。但是他的日期是固定的啊,固定的时间轴谁不会啊?甲方表示不听不听,王八念经。
不过能力不够,我很抱歉,只能先做一个可以自由选择起始和终止月份的时间轴先应付着,把别的简单功能先完成,再回头做这个吧。甲方无奈之下,也只能暂时妥协。
按月份做时间轴滑块的思维过程就很流畅了,先计算起始月份和终止月份相差多少个月确定 slider 的最大值,然后根据 slider 的绑定值加上起始月份除以 12 求商并取余就能得到当前绑定值是哪年哪月了。
后来其他需求做的差不多,甲方表示时间轴的精度太低了,这样哪还有施工进度模拟的感觉,一个月有将近三十天,那就每个月取三个日期,1 号,11 号,21 号吧,效果看起来能好点。
啧,感觉他们的需求很合理啊,这么正常的需求我做不出来,肯定是我能力不够,就想去我去网上看看有没有现成的轮子。结果我检索能力也不行,找了一圈没找到合适的。
算了,我自己再想想,顺便去做了个核酸,喉咙被戳得挺不爽的,突然一时就思路清晰了,用时间戳啊,时间戳每天的时长固定的而且能跟日期相互转换。起始日期转为时间戳,然后加上 slider 绑定值的天数的时长,再转换为当前日期就完成了。这么简单的事,我一时居然想不到,果然是我还是经验不够能力不行。
代码 1
2
3
4
5
6
7
8
9
10
11
12
// Datepiker
pickDate () {
if ( this . dateselect != []) {
// Datepiker的绑定值是一个数组,存着起始日期和终止日期
const startDate = Date . parse ( this . dateselect [ 0 ])
const endDate = Date . parse ( this . dateselect [ 1 ])
// 计算起始日期和终止日期相差多少天,从而确定slider的最大值
this . datemax = ( endDate - startDate ) / ( 1 * 24 * 60 * 60 * 1000 )
this . startdate = this . timepiker [ 0 ]
this . enddate = this . timepiker [ 1 ]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Slider
formatTooltip ( val ) {
// 格式化tooltip,使tooltip显示当前日期,val为当前slider绑定值
const startdate = Date . parse ( this . dateselect [ 0 ])
const nowdate = new Date ( startdate + 1 * 24 * 60 * 60 * 1000 * val )
const Y = nowdate . getFullYear ()
const M =
nowdate . getMonth () + 1 < 10
? '0' + ( nowdate . getMonth () + 1 )
: nowdate . getMonth () + 1
const D = date . getDate () < 10 ? '0' + nowdate . getDate () : nowdate . getDate ()
const nowdate = ` ${ Y } - ${ M } - ${ D } `
//当前日期格式为"yyyy-MM-dd"
return nowDate
},
changeModel () {
// ToDo:传递this.sliderdate给后端,返回当前日期下,存在的模型的链接以及模型id。
}
效果选择起始和终止日期后,滑块会显示所有日期,拖动日期滑块即可控制对应模型的显示和隐藏。
效果如下图:
◎ 最终功能展示图
总结时间戳是 js 里很基础的概念了,不过我之前的项目经历中少有实际应用场景,所以导致我只知道有时间戳这个概念,却忘记了合理运用。
这充分证明了我的开发经验并不充足,知识常用常新,要对那些不熟却很基础的概念需要做到心中有数,能灵活使用。
另外,月份为跨度的时间轴滑块其实也是有实际应用场景的,我也把它贴在最后,权当一个教训吧。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
pickmonth () {
if ( this . timepiker != '' ) {
let month1 , month2
month1 = this . timepiker [ 0 ]. split ( '-' )
month2 = this . timepiker [ 1 ]. split ( '-' )
month1 = parseInt ( month1 [ 0 ]) * 12 + parseInt ( month1 [ 1 ])
month2 = parseInt ( month2 [ 0 ]) * 12 + parseInt ( month2 [ 1 ])
this . levelmax = Math . abs ( month2 - month1 )
this . startmonth = this . timepiker [ 0 ]
this . endmonth = this . timepiker [ 1 ]
}
}
formatTooltip ( val ) {
if ( this . timepiker != '' ) {
let date = this . timepiker [ 1 ]. split ( '-' )
let year = parseInt ( date [ 0 ])
let month = parseInt ( date [ 1 ])
if ( month - (( this . levelmax - val ) % 12 ) > 0 ) {
year = year - Math . floor (( this . levelmax - val ) / 12 )
month = month - (( this . levelmax - val ) % 12 )
} else if ( month - (( this . levelmax - val ) % 12 ) < 0 ) {
year = year - Math . ceil (( this . levelmax - val ) / 12 )
month = month + 12 - (( this . levelmax - val ) % 12 )
} else if ( month - (( this . levelmax - val ) % 12 ) == 0 ) {
year = year - Math . ceil (( this . levelmax - val ) / 12 )
month = 12
}
return year + '-' + month
}
}