262 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div class="canvas" @mousemove.stop="onMousemove" @mouseup="onMouseUp" @mouseleave="isHide = true" v-if="isInit">
 | |
|     <canvas
 | |
|       :id="id"
 | |
|       :style="{height: '52px'}"
 | |
|       v-if="canvasWidth"
 | |
|       :width="canvasWidth"
 | |
|       height="52">
 | |
|     </canvas>
 | |
|     <div class="time" v-show="!isHide" :style="{left: left + 'px'}">{{ time }}</div>
 | |
|     <div class="time-scale" :style="{left: x + 'px'}">
 | |
|       <span></span>
 | |
|     </div>
 | |
|     <img
 | |
|       @mousedown="onDragDown"
 | |
|       class="drag-img"
 | |
|       :style="{left: x + 'px'}"
 | |
|       src="https://cdn.cunwuyun.cn/slw2.0/images/drag.png" />
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
|   export default {
 | |
|     props: ['isLiveing'],
 | |
| 
 | |
|     data () {
 | |
|       return {
 | |
|         ctx: null,
 | |
|         canvasWidth: '',
 | |
|         canvasHeight: '',
 | |
|         scale: 4,
 | |
|         time: '',
 | |
|         left: 0,
 | |
|         x: 0,
 | |
|         isHide: true,
 | |
|         isInit: false,
 | |
|         isChoose: false,
 | |
|         id: `timeline-${new Date().getTime()}`,
 | |
|         timer: null
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     watch: {
 | |
|       isLiveing (v) {
 | |
|         if (v) {
 | |
|           this.countdown()
 | |
|         }
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     mounted () {
 | |
|       this.$nextTick(() => {
 | |
|         this.init()
 | |
|       })
 | |
|     },
 | |
| 
 | |
|     methods: {
 | |
|       onMousemove (e) {
 | |
|         const canvasInfo = document.querySelector(`#${this.id}`).getBoundingClientRect()
 | |
|         const seconds = 24 * 60 * 60
 | |
| 
 | |
|         if (e.clientY - canvasInfo.top < 29) {
 | |
|           const x = e.clientX - canvasInfo.left
 | |
|           const unit = seconds / this.canvasWidth * x
 | |
|           this.left = x
 | |
|           this.time = this.secTotime(unit)
 | |
|           this.isHide = false
 | |
| 
 | |
|           if (!this.isChoose) return
 | |
|           this.x = e.clientX - canvasInfo.left - 4
 | |
|           this.ratioW = this.x / this.canvasWidth
 | |
|         } else {
 | |
|           this.isHide = true
 | |
|         }
 | |
|       },
 | |
| 
 | |
|       onDragDown () {
 | |
|         this.$emit('pause')
 | |
|         clearInterval(this.timer)
 | |
|         this.timer = null
 | |
|         this.isChoose = true
 | |
|       },
 | |
| 
 | |
|       onMouseUp () {
 | |
|         this.isChoose = false
 | |
|       },
 | |
| 
 | |
|       secTotime (s) {
 | |
|         var t = ''
 | |
|         if(s > -1){
 | |
|           var hour = Math.floor(s / 3600)
 | |
|           var min = Math.floor(s / 60) % 60
 | |
|           var sec = s % 60
 | |
|           if(hour < 10) {
 | |
|             t = '0'+ hour + ":"
 | |
|           } else { 
 | |
|             t = hour + ":"
 | |
|           } 
 | |
|           if(min < 10){
 | |
|             t += "0"
 | |
|           } 
 | |
|           t += min + ":"
 | |
|           if(sec < 10){
 | |
|             t += "0"
 | |
|           } 
 | |
|           t += sec.toFixed(0)
 | |
|         } 
 | |
|         return t
 | |
|       },
 | |
| 
 | |
|       init () {
 | |
|         this.$nextTick(() => {
 | |
|           this.isInit = true
 | |
|           this.$nextTick(() => {
 | |
|             this.canvasWidth = document.querySelector('.canvas').offsetWidth
 | |
|             this.canvasHeight = document.querySelector('.canvas').offsetHeight
 | |
| 
 | |
|             this.$nextTick(() => {
 | |
|               const el = document.querySelector(`#${this.id}`)
 | |
|               this.ctx = el.getContext('2d')
 | |
|               this.ctx.width  = document.querySelector('.canvas').offsetWidth
 | |
|               this.ctx.height  = document.querySelector('.canvas').offsetHeight
 | |
| 
 | |
|               if (this.x > 0) {
 | |
|                 this.x = this.canvasWidth * this.ratioW
 | |
|               } else {
 | |
|                 this.initNowTime()
 | |
|               }
 | |
| 
 | |
|               this.renderTimeLine()
 | |
|               this.renderPlayback()
 | |
| 
 | |
|               this.countdown()
 | |
|             })
 | |
|           })
 | |
|         })
 | |
|       },
 | |
| 
 | |
|       countdown () {
 | |
|         this.timer = setInterval(() => {
 | |
|           this.initNowTime()
 | |
|         }, 1000)
 | |
|       },
 | |
| 
 | |
|       initNowTime () {
 | |
|         const date = new Date()
 | |
|         const seconds = date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds()
 | |
| 
 | |
|         this.x = seconds / (24 * 60 * 60) * this.canvasWidth
 | |
|       },
 | |
| 
 | |
|       drawLine(ctx, options) {
 | |
|         const { beginX, beginY, endX, endY, lineColor, lineWidth } = options
 | |
|         ctx.beginPath()
 | |
|         ctx.lineWidth = lineWidth
 | |
|         ctx.moveTo(beginX, beginY)
 | |
|         ctx.lineTo(endX, endY)
 | |
|         ctx.strokeStyle = lineColor
 | |
|         ctx.stroke()
 | |
|       },
 | |
| 
 | |
|       renderPlayback () {
 | |
|         const ctx = this.ctx
 | |
|         for (let i = 0; i < 24 * 60 * 60; i ++) {
 | |
|           if ((i + 1) % 3 !== 0) {
 | |
|             this.drawLine(ctx, {
 | |
|               beginX: i,
 | |
|               beginY: 28,
 | |
|               endX: i,
 | |
|               endY: 0,
 | |
|               lineColor: 'rgba(0, 156, 255, 1)',
 | |
|               lineWidth: 1
 | |
|             })
 | |
|           }
 | |
|         }
 | |
|       },
 | |
| 
 | |
|       renderTimeLine () {
 | |
|         const ctx = this.ctx
 | |
|         ctx.fillStyle = 'rgba(51, 60, 83, 0.8)'
 | |
|         ctx.fillRect(0, 0, this.canvasWidth, 28)
 | |
|         ctx.fillStyle = 'rgba(32, 40, 61, 0.8)'
 | |
|         ctx.fillRect(0, 28, this.canvasWidth, 24)
 | |
| 
 | |
|         
 | |
|         ctx.fillStyle = '#fff'
 | |
|         ctx.font = '12px Arial'
 | |
|         const w = this.canvasWidth / 24 
 | |
| 
 | |
|         for (let i = 1; i < 25; i ++) {
 | |
|           this.drawLine(ctx, {
 | |
|             beginX: i * w,
 | |
|             beginY: 28,
 | |
|             endX: i * w,
 | |
|             endY: i % this.scale === 0 ? 16 : 20,
 | |
|             lineColor: i % this.scale === 0 ? 'red' : '#000',
 | |
|             lineWidth: i % this.scale === 0 ? 1 : 1
 | |
|           })
 | |
| 
 | |
|           if (i % this.scale === 0) {
 | |
|             const text = (i < 10 ? '0' + i : i) + ': 00'
 | |
|             const textWidth = ctx.measureText(text).width
 | |
|             if (i === 24) {
 | |
|               ctx.fillText(text, i * w - textWidth, 44)
 | |
|             } else {
 | |
|               ctx.fillText(text, i * w - textWidth / 2, 44)
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
|   .canvas {
 | |
|     position: relative;
 | |
|     width: 100%;
 | |
|     height: 52px;
 | |
| 
 | |
|     .drag-img {
 | |
|       position: absolute;
 | |
|       left: 0;
 | |
|       top: 0;
 | |
|       z-index: 1;
 | |
|       user-select: none;
 | |
|       cursor: e-resize;
 | |
|       -webkit-user-drag: none;
 | |
|     }
 | |
| 
 | |
|     .time-scale {
 | |
|       display: flex;
 | |
|       position: absolute;
 | |
|       align-items: center;
 | |
|       justify-content: center;
 | |
|       left: 0;
 | |
|       bottom: 0;
 | |
|       z-index: 1;
 | |
|       user-select: none;
 | |
|       width: 12px;
 | |
|       height: 24px;
 | |
| 
 | |
|       span {
 | |
|         width: 2px;
 | |
|         height: 24px;
 | |
|         background: rgba(255, 255, 255, 0.8);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     .time {
 | |
|       position: absolute;
 | |
|       bottom: 22px;
 | |
|       left: 0;
 | |
|       z-index: 1;
 | |
|       padding: 2px 4px;
 | |
|       font-size: 12px;
 | |
|       color: #fff;
 | |
|       background: rgba(0, 0, 0, 1);
 | |
|       transform: translate(-50%, 100%);
 | |
|     }
 | |
|   }
 | |
| </style> |