Vue【原创】时间轴 【time-axis】&【date-axis】
封装了关于时间轴的组件,有时候统计页面会用到。
效果图:
时间轴分为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>
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>
调用示例和参数说明:
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>
作者: Binyy
出处: https://www.cnblogs.com/loveFlex
城市:wuhan
微信:momakeyy
详细源码请移步,记得点个星星噢~ https://gitee.com/binyylovesino/lilo-ui 欢迎各路大佬指导、提问~
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接 如有问题, 可邮件(408460486@qq.com)或者微信咨询.
posted on 2023-08-29 14:58 Binyy_Wuhan 阅读(1594) 评论(0) 编辑 收藏 举报