Vue【原创】时间轴 【time-axis】&【date-axis】

发布时间 2023-08-29 15:01:38作者: Binyy_Wuhan

封装了关于时间轴的组件,有时候统计页面会用到。

效果图:

时间轴分为2种,一种是time-axis:范围选择模式,一种是date-axis:步长选择模式。

代码中涉及到的工具类和图片资源,请移步页面底部的gitee地址下载源码。

 

time-axis:

  1 <template>
  2     <div class="timeline" :style="{ 'background-color': themeObject.backgroudColor }">
  3         <div class="start"><input v-model="st" @keyup="excute" :style="{ color: themeObject.color }" :disabled="interactive.inputDisabled" /></div>
  4         <div ref="line" class="line">
  5             <div ref="pgs" class="progress" :style="{ 'background-color': themeObject.progressColor }">
  6                 <div ref="slide" class="slidebar" :style="{ width: slideWidth + 'px', left: lbarLeft + 'px', background: themeObject.slideBackground }"></div>
  7                 <div ref="lbar" class="leftbar" :style="{ left: lbarLeft + 'px', 'z-index': lzindex, 'background-color': themeObject.barColor }"></div>
  8                 <div ref="rbar" class="rightbar" :style="{ left: rbarLeft + 'px', 'z-index': rzindex, 'background-color': themeObject.barColor }"></div>
  9             </div>
 10         </div>
 11         <div class="end"><input v-model="et" @keyup="excute" :style="{ color: themeObject.color }" :disabled="interactive.inputDisabled" /></div>
 12     </div>
 13 </template>
 14 
 15 <script>
 16 import { debounce } from '../../../src/utils';
 17 
 18 const reg = new RegExp(
 19     /(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)$/
 20 );
 21 
 22 const TYPE_LEFT = 0;
 23 const TYPE_RIGHT = 1;
 24 const TYPE_CENTER = 2;
 25 // const MAX_DAYS = 90
 26 
 27 const BAR_TYPE_LEFT = 0x01;
 28 const BAR_TYPE_RIGHT = 0x02;
 29 
 30 const THEME_DARK = 'dark';
 31 const THEME_LIGHT = 'light';
 32 
 33 export default {
 34     name: 'LiloTimeAxis',
 35     model: {
 36         prop: 'data',
 37         event: 'changed'
 38     },
 39     props: {
 40         data: {
 41             type: Object,
 42             required: false,
 43             default() {
 44                 return {
 45                     startTime: null,
 46                     endTime: null
 47                 };
 48             }
 49         },
 50         min: {
 51             type: String,
 52             required: true,
 53             default: null
 54         },
 55         max: {
 56             type: String,
 57             required: false,
 58             default: null
 59         },
 60         theme: {
 61             type: String,
 62             default: THEME_LIGHT
 63         },
 64         customTheme: {
 65             type: Object,
 66             default: null
 67         },
 68         interactive: {
 69             type: Object,
 70             required: false,
 71             default() {
 72                 return {
 73                     inputDisabled: false,
 74                     leftButtonDisabled: false,
 75                     rightButtonDisabled: false,
 76                     slideButtonDisabled: false
 77                 };
 78             }
 79         },
 80         range: {
 81             type: Number,
 82             required: false,
 83             default: 0
 84         }
 85     },
 86     data() {
 87         return {
 88             st: '',
 89             et: '',
 90             lbarLeft: 0,
 91             rbarLeft: 0,
 92             lzindex: 1,
 93             rzindex: 2,
 94             barType: BAR_TYPE_LEFT
 95         };
 96     },
 97     created() {},
 98     mounted() {
 99         this.type = -1;
100         this.move = false;
101         this.defaultLeft = 0;
102         this.defaultSlideWidth = 0;
103         this.maxWidth = 0;
104         this.allDays = 0;
105         // this.maxDays = MAX_DAYS
106         this.pst = '';
107         this.pet = '';
108 
109         this._addEvents();
110         this._initDatePrototype();
111 
112         if (this._validateData()) {
113             this._checkRange(false);
114             this._redraw();
115         }
116         window.requestAnimationFrame(this._updateDisplayList);
117     },
118     beforeDestroy() {
119         this._removeEvents();
120     },
121     computed: {
122         slideWidth() {
123             return this.rbarLeft - this.lbarLeft;
124         },
125         themeObject() {
126             if (this.customTheme) {
127                 return this.customTheme;
128             } else {
129                 switch (this.theme) {
130                     case THEME_DARK:
131                         return {
132                             color: '#ffffff',
133                             backgroudColor: '#000000',
134                             progressColor: '#3e3e3e',
135                             barColor: '#ffffff',
136                             slideBackground: `url(${require('./assets/slider_pattern2.png')})`
137                         };
138                     case THEME_LIGHT:
139                         return {
140                             color: '#000000',
141                             backgroudColor: '#ffffff',
142                             progressColor: '#ababab',
143                             barColor: '#ffffff',
144                             slideBackground: '#072C4C'
145                             // slideBackground: `url(${require('./assets/slider_pattern2.png')})`
146                         };
147                     default:
148                         return {
149                             color: '#ffffff',
150                             backgroudColor: '#000000',
151                             progressColor: '#3e3e3e',
152                             barColor: '#ffffff',
153                             slideBackground: '#072C4C'
154                             // slideBackground: `url(${require('./assets/slider_pattern2.png')})`
155                         };
156                 }
157             }
158         }
159     },
160     watch: {
161         // ================================== watch ================================== //
162         data: {
163             handler: function(newVal, oldVal) {
164                 if (newVal.startTime && newVal.endTime) {
165                     if (newVal.startTime !== oldVal.startTime || newVal.endTime !== oldVal.endTime) {
166                         // if(this._validateData()) {
167                         this._redraw();
168                         // }
169                     }
170                 }
171             },
172             deep: false
173         },
174         min(newVal, oldVal) {
175             if (newVal) {
176                 if (this._validateData()) {
177                     this._redraw();
178                 }
179             }
180         },
181         max(newVal, oldVal) {
182             if (newVal) {
183                 if (this._validateData()) {
184                     this._redraw();
185                 }
186             }
187         }
188     },
189     methods: {
190         onLbarDown(e) {
191             this.move = true;
192             this.type = TYPE_LEFT;
193             this.defaultLeft = e.target.offsetLeft;
194             this.defaultPageX = e.pageX;
195             this.maxWidth = this.$refs.pgs.clientWidth;
196             this.lzindex = 2;
197             this.rzindex = 1;
198             this.barType = BAR_TYPE_LEFT;
199         },
200         onRbarDown(e) {
201             this.move = true;
202             this.type = TYPE_RIGHT;
203             this.defaultLeft = e.target.offsetLeft;
204             this.defaultPageX = e.pageX;
205             this.maxWidth = this.$refs.pgs.clientWidth;
206             this.lzindex = 1;
207             this.rzindex = 2;
208             this.barType = BAR_TYPE_RIGHT;
209         },
210         onSlideDown(e) {
211             this.move = true;
212             this.type = TYPE_CENTER;
213             this.defaultLeft = e.target.offsetLeft;
214             this.defaultPageX = e.pageX;
215             this.maxWidth = this.$refs.pgs.clientWidth;
216             this.defaultSlideWidth = this.slideWidth;
217         },
218         onDocMove(e) {
219             if (this.move) {
220                 const dx = e.pageX - this.defaultPageX;
221                 let left = this.defaultLeft + dx;
222                 if (this.type === TYPE_LEFT) {
223                     if (left <= 0) {
224                         left = 0;
225                     }
226                     if (left >= this.rbarLeft) {
227                         left = this.rbarLeft;
228                     }
229                     this.lbarLeft = left;
230                     const ldays = (left / this.maxWidth) * this.allDays;
231                     this.st = this._getDate_(this._min, ldays);
232                 } else if (this.type === TYPE_RIGHT) {
233                     if (left <= this.lbarLeft) {
234                         left = this.lbarLeft;
235                     }
236                     if (left >= this.maxWidth) {
237                         left = this.maxWidth;
238                     }
239                     this.rbarLeft = left;
240                     const rdays = (left / this.maxWidth) * this.allDays;
241                     this.et = this._getDate_(this._min, rdays);
242                 } else {
243                     if (left <= 0) {
244                         left = 0;
245                     }
246                     if (left >= this.maxWidth - this.defaultSlideWidth) {
247                         left = this.maxWidth - this.defaultSlideWidth;
248                     }
249                     this.lbarLeft = left;
250                     this.rbarLeft = this.lbarLeft + this.defaultSlideWidth;
251                     const ldays = (left / this.maxWidth) * this.allDays;
252                     this.st = this._getDate_(this._min, ldays);
253                     const rdays = ((left + this.defaultSlideWidth) / this.maxWidth) * this.allDays;
254                     this.et = this._getDate_(this._min, rdays);
255                 }
256                 this._checkRange();
257             }
258         },
259         onDocUp(e) {
260             if (this.move) {
261                 this.move = false;
262                 this._redraw();
263             }
264         },
265         excute: debounce(function() {
266             const startTime = this.st;
267             const endTime = this.et;
268             const f1 = reg.test(startTime.replace(/\//g, '-'));
269             const f2 = reg.test(endTime.replace(/\//g, '-'));
270             if (f1 && f2) {
271                 this._redraw();
272             } else {
273                 alert('日期格式错误,请按照2021/01/01格式输入');
274             }
275         }, 2000),
276         onResize() {
277             this._redraw();
278         },
279 
280         // ================================== private ================================== //
281 
282         _addEvents() {
283             if (!this.interactive.leftButtonDisabled) {
284                 this.$refs.lbar.addEventListener('mousedown', this.onLbarDown);
285             }
286             if (!this.interactive.rightButtonDisabled) {
287                 this.$refs.rbar.addEventListener('mousedown', this.onRbarDown);
288             }
289             if (!this.interactive.slideButtonDisabled) {
290                 this.$refs.slide.addEventListener('mousedown', this.onSlideDown);
291             }
292             window.addEventListener('resize', this.onResize);
293             document.addEventListener('mousemove', this.onDocMove);
294             document.addEventListener('mouseup', this.onDocUp);
295         },
296         _removeEvents() {
297             if (!this.interactive.leftButtonDisabled) {
298                 this.$refs.lbar.removeEventListener('mousedown', this.onLbarDown);
299                 this.$refs.lbar.addEventListener('mousedown', this.onLbarDown);
300             }
301             if (!this.interactive.rightButtonDisabled) {
302                 this.$refs.rbar.removeEventListener('mousedown', this.onRbarDown);
303                 this.$refs.rbar.addEventListener('mousedown', this.onRbarDown);
304             }
305             if (!this.interactive.slideButtonDisabled) {
306                 this.$refs.slide.removeEventListener('mousedown', this.onSlideDown);
307                 this.$refs.slide.addEventListener('mousedown', this.onSlideDown);
308             }
309             window.removeEventListener('resize', this.onResize);
310             document.removeEventListener('mousemove', this.onDocMove);
311             document.removeEventListener('mouseup', this.onDocUp);
312         },
313         _redraw() {
314             this.dirty = true;
315         },
316         _updateDisplayList() {
317             if (this.dirty) {
318                 this._validateDisplayList();
319 
320                 const startTime = this.st;
321                 const endTime = this.et;
322                 if (this.pst != startTime || this.pet != endTime) {
323                     this.$emit('changed', { startTime, endTime });
324                 }
325                 this.pst = this.st;
326                 this.pet = this.et;
327 
328                 this.dirty = false;
329             }
330 
331             window.requestAnimationFrame(this._updateDisplayList);
332         },
333         _validateData() {
334             this._min = this.min || this.data.startTime;
335             this._max = this.max || this.data.endTime;
336             this.st = this.data.startTime;
337             this.et = this.data.endTime;
338 
339             return this._min && this._max && this.st && this.et;
340         },
341         _validateDisplayList() {
342             const cw = this.$refs.line.clientWidth;
343             this.$refs.pgs.style.width = cw + 'px';
344 
345             this.maxWidth = this.$refs.pgs.clientWidth;
346             this.allDays = this._getDaycount_(this._min, this._max);
347 
348             const ldays = this._getDaycount_(this._min, this.st);
349             const rdays = this._getDaycount_(this._min, this.et);
350 
351             this.lbarLeft = this.maxWidth * (ldays / this.allDays);
352             this.rbarLeft = this.maxWidth * (rdays / this.allDays);
353         },
354         _checkRange(draw = true) {
355             if (this.range > 0) {
356                 const delta = this._getDaycount_(this.st, this.et);
357                 if (delta > this.range) {
358                     if (this.barType === BAR_TYPE_LEFT) {
359                         this.st = this._getDate_(this.et, -this.range + 1);
360                     } else if (this.barType === BAR_TYPE_RIGHT) {
361                         this.et = this._getDate_(this.st, this.range - 1);
362                     } else {
363                     }
364                     if(draw) {
365                         this._validateDisplayList();
366                     }
367                 }
368             }
369         },
370         _initDatePrototype() {
371             Date.prototype.toLocaleString = function() {
372                 return this.getFullYear() + '/' + (this.getMonth() + 1) + '/' + this.getDate() + ' ' + this.getHours() + ':' + this.getMinutes() + ':' + this.getSeconds();
373             };
374         },
375         _getDaycount_(time1, time2) {
376             const aa = new Date(time1).getTime();
377             const bb = new Date(time2).getTime();
378             const mm = 24 * 60 * 60 * 1000;
379             const count = (bb - aa) / mm;
380             return count;
381         },
382         _getDate_(time1, count) {
383             const aa = new Date(time1).getTime();
384             const mm = 24 * 60 * 60 * 1000;
385             const bb = count * mm + aa;
386             const tm = new Date(bb).toLocaleString().split(' ')[0];
387             const tm2 = tm.split('/');
388             const year = tm2[0];
389             const month = parseInt(tm2[1]) < 10 ? '0' + parseInt(tm2[1]) : tm2[1];
390             const day = parseInt(tm2[2]) < 10 ? '0' + parseInt(tm2[2]) : tm2[2];
391             return year + '/' + month + '/' + day;
392         }
393     }
394 };
395 </script>
396 
397 <style lang="scss" scoped>
398 .timeline {
399     display: flex;
400     -webkit-transition: all 0.3s ease 0s;
401     transition: all 0.3s ease 0s;
402     border: 1px solid rgba(62, 62, 62, 1);
403     background-color: rgba(0, 0, 0, 0.9);
404     background-image: url('./assets/texture_small.png');
405     backdrop-filter: blur(10px);
406     -webkit-backdrop-filter: blur(10px);
407     // border-radius: 5px;
408     height: 40px;
409     line-height: 40px;
410     -moz-user-select: none;
411     -webkit-user-select: none;
412     user-select: none;
413     &:hover {
414         background-color: rgba(0, 0, 0, 1);
415     }
416     .start {
417         flex: 0 0 120px;
418         input {
419             background: transparent;
420             border: none;
421             width: 80px;
422             color: white;
423             // text-align: center;
424             letter-spacing: 1px;
425             font-weight: bold;
426             outline: none;
427             margin-left: 20px;
428         }
429     }
430     .end {
431         flex: 0 0 120px;
432         // text-align: center;
433         letter-spacing: 1px;
434         font-weight: bold;
435         input {
436             background: transparent;
437             border: none;
438             width: 80px;
439             color: white;
440             // text-align: center;
441             letter-spacing: 1px;
442             font-weight: bold;
443             outline: none;
444             margin-left: 20px;
445         }
446     }
447     .line {
448         height: 100%;
449         flex: 1;
450         .progress {
451             position: absolute;
452             // width: calc(100% - 280px);
453             height: 10px;
454             margin-top: 15px;
455             // border-radius: 5px;
456             background-color: rgba(62, 62, 62, 1);
457             // background-image: url('../assets/texture_small.png');
458             font-size: 0;
459             .leftbar {
460                 // -webkit-transition: all 0.15s ease 0s;
461                 // transition: all 0.15s ease 0s;
462                 position: absolute;
463                 top: -6px;
464                 width: 6px;
465                 height: 20px;
466                 background-color: white;
467                 border: 1px solid rgba(62, 62, 62, 1);
468                 cursor: url('./assets/move.png') 15 15, default;
469             }
470             .slidebar {
471                 // -webkit-transition: all 0.15s ease 0s;
472                 // transition: all 0.15s ease 0s;
473                 position: absolute;
474                 height: 10px;
475                 cursor: pointer;
476                 background: url('./assets/slider_pattern2.png');
477             }
478             .rightbar {
479                 // -webkit-transition: all 0.15s ease 0s;
480                 // transition: all 0.15s ease 0s;
481                 position: absolute;
482                 top: -6px;
483                 width: 6px;
484                 height: 20px;
485                 background-color: white;
486                 border: 1px solid rgba(62, 62, 62, 1);
487                 cursor: url('./assets/move.png') 15 15, default;
488             }
489         }
490     }
491 }
492 </style>
View Code

 

 

date-axis:

  1 <template>
  2     <div class="timeline" :style="{ 'background-color': themeObject.backgroudColor }">
  3         <div class="start"><input :value="st" @keyup="excute" :style="{ color: themeObject.color }" disabled /></div>
  4         <div ref="line" class="line">
  5             <div ref="pgs" class="progress" :style="{ 'background-color': themeObject.progressColor }">
  6                 <div ref="sbar" class="scalebar">
  7                     <div v-for="(item, index) in segment" class="scale" 
  8                         :style="{ 'border': themeObject.scaleBorder }"
  9                         @mouseover="onScaleMouseover(index)" 
 10                         @mouseout="onScaleMouseout(index)" 
 11                         @click="onScaleClick(index)">
 12                     </div>
 13                 </div>
 14                 <div ref="slide" class="slidebar" :style="{ width: slideWidth + 'px', left: slideLeft + 'px', background: themeObject.slideBackground }"></div>
 15             </div>
 16         </div>
 17         <div class="end"><input :value="et" @keyup="excute" :style="{ color: themeObject.color }" disabled /></div>
 18     </div>
 19 </template>
 20 
 21 <script>
 22 import { debounce } from '../../../src/utils';
 23 
 24 const THEME_DARK = 'dark';
 25 const THEME_LIGHT = 'light';
 26 
 27 export default {
 28     name: 'LiloDateAxis',
 29     model: {
 30         prop: 'data',
 31         event: 'changed'
 32     },
 33     props: {
 34         data: {
 35             type: Object,
 36             required: false,
 37             default() {
 38                 return {
 39                     startTime: null,
 40                     endTime: null
 41                 };
 42             }
 43         },
 44         min: {
 45             type: String,
 46             required: true,
 47             default: null
 48         },
 49         max: {
 50             type: String,
 51             required: false,
 52             default: null
 53         },
 54         theme: {
 55             type: String,
 56             default: THEME_LIGHT
 57         },
 58         customTheme: {
 59             type: Object,
 60             default: null
 61         },
 62         interactive: {
 63             type: Object,
 64             required: false,
 65             default() {
 66                 return {
 67                     slideButtonDisabled: false
 68                 };
 69             }
 70         }
 71     },
 72     data() {
 73         return {
 74             st: '',
 75             et: '',
 76             range: 0,
 77             allDays: 0,
 78             segment: 0,
 79             scales: [],
 80             slideWidth: 0,
 81             slideLeft: 0
 82         };
 83     },
 84     created() {},
 85     mounted() {
 86         this._addEvents();
 87         this._initDatePrototype();
 88 
 89         if (this._validateData()) {
 90             this._redraw();
 91         }
 92 
 93         window.requestAnimationFrame(this._updateDisplayList);
 94     },
 95     beforeDestroy() {
 96         this._removeEvents();
 97     },
 98     computed: {
 99         themeObject() {
100             if (this.customTheme) {
101                 return this.customTheme;
102             } else {
103                 switch (this.theme) {
104                     case THEME_DARK:
105                         return {
106                             color: '#ffffff',
107                             backgroudColor: '#000000',
108                             progressColor: '#3e3e3e',
109                             barColor: '#ffffff',
110                             slideBackground: `url(${require('./assets/slider_pattern2.png')})`,
111                             scaleBorder: '1px solid #000000'
112                         };
113                     case THEME_LIGHT:
114                         return {
115                             color: '#000000',
116                             backgroudColor: '#ffffff',
117                             progressColor: '#ababab',
118                             barColor: '#ffffff',
119                             slideBackground: '#072C4C',
120                             // slideBackground: `url(${require('./assets/slider_pattern2.png')})`
121                             scaleBorder: '1px solid #072C4C'
122                         };
123                     default:
124                         return {
125                             color: '#ffffff',
126                             backgroudColor: '#000000',
127                             progressColor: '#3e3e3e',
128                             barColor: '#ffffff',
129                             slideBackground: '#072C4C',
130                             // slideBackground: `url(${require('./assets/slider_pattern2.png')})`
131                             scaleBorder: '1px solid #072C4C'
132                         };
133                 }
134             }
135         }
136     },
137     watch: {
138         // ================================== watch ================================== //
139         data: {
140             handler: function(newVal, oldVal) {
141                 if (newVal.startTime && newVal.endTime) {
142                     if (newVal.startTime !== oldVal.startTime || newVal.endTime !== oldVal.endTime) {
143                         if (this._validateData()) {
144                             this._redraw();
145                         }
146                     }
147                 }
148             },
149             deep: false
150         },
151         min(newVal, oldVal) {
152             if (newVal) {
153                 if (this._validateData()) {
154                     this._redraw();
155                 }
156             }
157         },
158         max(newVal, oldVal) {
159             if (newVal) {
160                 if (this._validateData()) {
161                     this._redraw();
162                 }
163             }
164         }
165     },
166     methods: {
167         onScaleClick(index) {
168             if (this.interactive.slideButtonDisabled) {
169                 return;
170             }
171 
172             const o = this.scales[index];
173             this.st = o.startTime;
174             this.et = o.endTime;
175 
176             this._redraw();
177         },
178         onScaleMouseover(index) {
179             const o = this.scales[index];
180             this.st = o.startTime;
181             this.et = o.endTime;
182         },
183         onScaleMouseout(index) {
184             this.st = this.pst;
185             this.et = this.pet;
186         },
187         excute: debounce(function() {}, 2000),
188         onResize() {
189             this._redraw();
190         },
191 
192         // ================================== private ================================== //
193 
194         _addEvents() {
195             window.addEventListener('resize', this.onResize);
196         },
197         _removeEvents() {
198             window.removeEventListener('resize', this.onResize);
199         },
200         _redraw() {
201             this.dirty = true;
202         },
203         _updateDisplayList() {
204             if (this.dirty) {
205                 this._validateDisplayList();
206 
207                 const startTime = this.st;
208                 const endTime = this.et;
209                 if (this.pst != startTime || this.pet != endTime) {
210                     this.$emit('changed', { startTime, endTime });
211                 }
212                 this.pst = this.st;
213                 this.pet = this.et;
214                 this.dirty = false;
215             }
216 
217             window.requestAnimationFrame(this._updateDisplayList);
218         },
219         _validateData() {
220             this._min = this.min || this.data.startTime;
221             this._max = this.max || this.data.endTime;
222             this.st = this.data.startTime;
223             this.et = this.data.endTime;
224 
225             return this._min && this._max && this.st && this.et;
226         },
227         _validateDisplayList() {
228             this.range = this._getDaycount_(this.st, this.et) + 1;
229             this.allDays = this._getDaycount_(this._min, this._max) + 1;
230             this.segment = this.allDays / this.range;
231             if ((this.segment | 0) !== this.segment) {
232                 throw new Error('总天数必须被时间段天数整除,例如一共20天,每个时间段2天,则合理。');
233             }
234             this.scales = [];
235             for (let i = 0; i < this.allDays; i += this.range) {
236                 const startTime = this._getDate_(this._min, i);
237                 const endTime = this._getDate_(this._min, i + this.range - 1);
238                 this.scales.push({ startTime, endTime });
239             }
240 
241             const startIndex = this._findIndex(this.st, 'startTime');
242             const endIndex = this._findIndex(this.et, 'endTime');
243             if (startIndex === -1 || endIndex === -1) {
244                 throw new Error('[min-max]区间段内找不到[startTime,endTime]起始日期。');
245             }
246 
247             this.slideWidth = this.$refs.line.clientWidth / this.segment;
248             this.slideLeft = startIndex * this.slideWidth;
249         },
250         _findIndex(time, key) {
251             for (let i = 0; i < this.scales.length; i++) {
252                 const o = this.scales[i];
253                 if (o[key] === time) {
254                     return i;
255                 }
256             }
257             return -1;
258         },
259         _initDatePrototype() {
260             Date.prototype.toLocaleString = function() {
261                 return this.getFullYear() + '/' + (this.getMonth() + 1) + '/' + this.getDate() + ' ' + this.getHours() + ':' + this.getMinutes() + ':' + this.getSeconds();
262             };
263         },
264         _getDaycount_(time1, time2) {
265             const aa = new Date(time1).getTime();
266             const bb = new Date(time2).getTime();
267             const mm = 24 * 60 * 60 * 1000;
268             const count = (bb - aa) / mm;
269             return count;
270         },
271         _getDate_(time1, count) {
272             const aa = new Date(time1).getTime();
273             const mm = 24 * 60 * 60 * 1000;
274             const bb = count * mm + aa;
275             const tm = new Date(bb).toLocaleString().split(' ')[0];
276             const tm2 = tm.split('/');
277             const year = tm2[0];
278             const month = parseInt(tm2[1]) < 10 ? '0' + parseInt(tm2[1]) : tm2[1];
279             const day = parseInt(tm2[2]) < 10 ? '0' + parseInt(tm2[2]) : tm2[2];
280             return year + '/' + month + '/' + day;
281         }
282     }
283 };
284 </script>
285 
286 <style lang="scss" scoped>
287 .timeline {
288     display: flex;
289     -webkit-transition: all 0.3s ease 0s;
290     transition: all 0.3s ease 0s;
291     border: 1px solid rgba(62, 62, 62, 1);
292     background-color: rgba(0, 0, 0, 0.9);
293     background-image: url('./assets/texture_small.png');
294     backdrop-filter: blur(10px);
295     -webkit-backdrop-filter: blur(10px);
296     // border-radius: 5px;
297     height: 40px;
298     line-height: 40px;
299     -moz-user-select: none;
300     -webkit-user-select: none;
301     user-select: none;
302     &:hover {
303         background-color: rgba(0, 0, 0, 1);
304     }
305     .start {
306         flex: 0 0 120px;
307         input {
308             background: transparent;
309             border: none;
310             width: 80px;
311             color: white;
312             // text-align: center;
313             letter-spacing: 1px;
314             font-weight: bold;
315             outline: none;
316             margin-left: 20px;
317         }
318     }
319     .end {
320         flex: 0 0 120px;
321         // text-align: center;
322         letter-spacing: 1px;
323         font-weight: bold;
324         input {
325             background: transparent;
326             border: none;
327             width: 80px;
328             color: white;
329             // text-align: center;
330             letter-spacing: 1px;
331             font-weight: bold;
332             outline: none;
333             margin-left: 20px;
334         }
335     }
336     .line {
337         height: 100%;
338         flex: 1;
339         .progress {
340             position: absolute;
341             // width: calc(100% - 280px);
342             left: 120px;
343             right: 120px;
344             height: 30%;
345             top: 35%;
346             // border-radius: 5px;
347             // background-color: rgba(62, 62, 62, 1);
348             // background-image: url('../assets/texture_small.png');
349             font-size: 0;
350             .slidebar {
351                 -webkit-transition: all 0.25s ease-out 0s;
352                 transition: all 0.15s ease-out 0s;
353                 position: absolute;
354                 height: 100%;
355                 cursor: pointer;
356                 background: url('./assets/slider_pattern2.png');
357                 // border-radius: 10px;
358                 box-sizing: border-box;
359                 border: 1px solid #000000;
360             }
361             .scalebar {
362                 position: absolute;
363                 width: 100%;
364                 height: 100%;
365                 cursor: pointer;
366                 display: flex;
367                 justify-content: flex-end;
368                 align-items: center;
369                 .scale {
370                     -webkit-transition: all 0.15s ease-out 0s;
371                     transition: all 0.15s ease-out 0s;
372                     flex: 1;
373                     height: 100%;
374                     box-sizing: border-box;
375                     // border-radius: 10px;
376                     &:hover {
377                         background-color: rgba($color: #ffffff, $alpha: 0.4) !important;
378                     }
379                 }
380             }
381         }
382     }
383 }
384 </style>
View Code

 

 

调用示例和参数说明

  1 <template>
  2     <div class="root">
  3         <div>
  4             <div class="time-title">1.【lilo-time-axis】基础用法</div>
  5             <el-button @click="setTime('001')">绑定方式修改时间</el-button>
  6             <lilo-time-axis 
  7                 v-model="example001.data" 
  8                 :min="example001.min"
  9                 class="timeline" 
 10                 :customTheme="example001.customTheme" 
 11                 @changed="timeChanged">
 12             </lilo-time-axis>
 13             <div class="time-text">开始时间:{{ example001.data.startTime }}</div>
 14             <div class="time-text">结束时间:{{ example001.data.endTime }}</div>
 15         </div>
 16 
 17         <div>
 18             <div class="time-title">2.【lilo-time-axis】锁定时间轴,禁用起始按钮和时间条</div>
 19             <el-button @click="setTime('002')">绑定方式修改时间</el-button>
 20             <lilo-time-axis
 21                 v-model="example002.data"
 22                 :interactive="example002.interactive"
 23                 :min="example002.min"
 24                 :max="example002.max"
 25                 class="timeline"
 26                 :theme="example002.theme"
 27                 @changed="timeChanged"
 28             >
 29                 <!-- :customTheme="customTheme"-->
 30                 <!-- :theme="theme"-->
 31             </lilo-time-axis>
 32             <div class="time-text">开始时间:{{ example002.data.startTime }}</div>
 33             <div class="time-text">结束时间:{{ example002.data.endTime }}</div>
 34         </div>
 35 
 36         <div>
 37             <div class="time-title">3.【lilo-date-axis】初始化的起始时间间隔为步长,请保证[时间间隔]能被max-min[时间段]整除,且[时间间隔]不要跨区间,例如下面例子:总时间段60天,时间间隔为2天,30个小时间段</div>
 38             <!-- <el-button @click="setTheme('003')">绑定方式修改时间</el-button> -->
 39             <lilo-date-axis
 40                 v-model="example003.data"
 41                 :interactive="example003.interactive"
 42                 :min="example003.min"
 43                 :max="example003.max"
 44                 class="timeline"
 45                 :theme="example003.theme"
 46                 @changed="timeChanged"
 47             >
 48                 <!-- :customTheme="customTheme"-->
 49                 <!-- :theme="theme"-->
 50             </lilo-date-axis>
 51             <div class="time-text">开始时间:{{ example003.data.startTime }}</div>
 52             <div class="time-text">结束时间:{{ example003.data.endTime }}</div>
 53         </div>
 54         
 55         <div>
 56             <div class="time-title">4.【lilo-time-axis】设置最大时间范围 (range = 5)</div>
 57             <lilo-time-axis 
 58                 v-model="example004.data"
 59                 :range="example004.range"
 60                 :min="example004.min"
 61                 class="timeline"
 62                 @changed="timeChanged">
 63             </lilo-time-axis>
 64             <div class="time-text">开始时间:{{ example004.data.startTime }}</div>
 65             <div class="time-text">结束时间:{{ example004.data.endTime }}</div>
 66         </div>
 67         
 68     </div>
 69 </template>
 70 
 71 <script>
 72 export default {
 73     name: 'example-time-date-axis',
 74     data() {
 75         return {
 76             example001: {
 77                 data: {
 78                     startTime: '2021/06/01',
 79                     endTime: '2022/06/01'
 80                 },
 81                 min: '2021/01/01',
 82                 // max: '2022/08/01', //max如果在组件上未声明,则不参与绑定,默认取endTime
 83                 // theme: 'light', //dark,light(default light)
 84                 customTheme: {
 85                     //if not null, be first
 86                     color: '#000000',
 87                     backgroudColor: '#BBDAFA',
 88                     progressColor: '#8d8d8d',
 89                     barColor: '#ffffff',
 90                     // slideBackground: `url(${require('../../../assets/slider_pattern2.png')})`
 91                     slideBackground: '#00417a'
 92                 }
 93             },
 94             example002: {
 95                 data: {
 96                     startTime: '2021/06/01',
 97                     endTime: '2022/06/01'
 98                 },
 99                 interactive: {
100                     inputDisabled: true,
101                     leftButtonDisabled: true,
102                     rightButtonDisabled: true,
103                     slideButtonDisabled: true
104                 },
105                 min: '2021/01/01',
106                 max: '2022/08/01',
107                 theme: 'dark' //dark,light(default light)
108             },
109             example003: {
110                 data: {
111                     startTime: '2022/08/21',
112                     endTime: '2022/08/22'
113                 },
114                 interactive: {
115                     slideButtonDisabled: false
116                 },
117                 min: '2022/08/01',
118                 max: '2022/08/30',
119                 theme: 'dark' //dark,light(default light)
120             },
121             example004: {
122                 data: {
123                     startTime: '2022/09/17',
124                     endTime: '2022/09/27'
125                 },
126                 range: 5,
127                 min: '2022/09/13',
128                 theme: 'dark' //dark,light(default light)
129             }
130         };
131     },
132     mounted() {},
133     methods: {
134         setTime(type) {
135             const date = {
136                 startTime: '2022/04/01',
137                 endTime: '2022/08/01'
138             };
139             const min = '2022/02/01';
140             const max = '2022/08/26';
141             this[`example${type}`].data = date;
142             this[`example${type}`].min = min;
143             this[`example${type}`].max = max;
144         },
145         timeChanged(val) {
146             console.log(val);
147         }
148     }
149 };
150 </script>
151 
152 <style>
153 .root {
154     padding: 10px;
155 }
156 .time-title {
157     margin-top: 10px;
158     margin-bottom: 5px;
159     /* color: #034631; */
160     font-weight: bold;
161 }
162 .time-text {
163     margin-top: 10px;
164 }
165 </style>