视频回放
This commit is contained in:
		| @@ -16,10 +16,8 @@ | |||||||
|           class="videoBox" |           class="videoBox" | ||||||
|           v-for="(m, i) in monitors" |           v-for="(m, i) in monitors" | ||||||
|           :key="m.id" |           :key="m.id" | ||||||
|           @mouseenter.stop="m.isShowPlayBtn = true" |  | ||||||
|           @mouseleave.stop="m.isShowPlayBtn = false" |  | ||||||
|           :style="currentSplitStyle"> |           :style="currentSplitStyle"> | ||||||
|           <AiMonitor :src="m.url" type="slw" :name="m.name" @close="removeMonitor(i)"></AiMonitor> |           <AiMonitor :src="m.url" type="slw" :name="m.name" @close="removeMonitor(i)" ref="AiMonitor"></AiMonitor> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
| @@ -116,6 +114,12 @@ export default { | |||||||
|       if (e === 1 && this.monitors.length) { |       if (e === 1 && this.monitors.length) { | ||||||
|         this.monitors = [this.monitors[0]] |         this.monitors = [this.monitors[0]] | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       console.log(this.$refs.AiMonitor) | ||||||
|  |  | ||||||
|  |       this.$refs.AiMonitor.forEach(e => { | ||||||
|  |         e.reset() | ||||||
|  |       }) | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     removeMonitor(i) { |     removeMonitor(i) { | ||||||
| @@ -217,7 +221,7 @@ export default { | |||||||
|   height: 100%; |   height: 100%; | ||||||
|  |  | ||||||
|   .monitorPane { |   .monitorPane { | ||||||
|     color: #fff; |     // color: #fff; | ||||||
|     flex: 1; |     flex: 1; | ||||||
|     min-width: 0; |     min-width: 0; | ||||||
|     padding: 20px 20px 20px 4px; |     padding: 20px 20px 20px 4px; | ||||||
|   | |||||||
| @@ -14,33 +14,53 @@ | |||||||
|       style="width: 100%; height: 100%;" |       style="width: 100%; height: 100%;" | ||||||
|       :src="`https://cdn.cunwuyun.cn/slw2.0/index.html?url=${src}`"> |       :src="`https://cdn.cunwuyun.cn/slw2.0/index.html?url=${src}`"> | ||||||
|     </iframe> |     </iframe> | ||||||
|     <div class="action-bar"> |     <div class="slw-bottom"> | ||||||
|       <div class="left"> |       <Timeline class="Timeline" @pause="isLiveing = false" :isLiveing="isLiveing" :width="width" ref="timeline" :style="{width: width}"></Timeline> | ||||||
|         <div class="left-btns"> |       <div class="action-bar"> | ||||||
|           <span :class="[currIndex === 0 ? 'active' : '']" @click="currIndex = 0">实时</span> |         <div class="left"> | ||||||
|           <span :class="[currIndex === 1 ? 'active' : '']" @click="currIndex = 1">历史</span> |           <div class="left-btns"> | ||||||
|         </div> |             <el-tooltip effect="dark" :content="isPause ? '播放' : '暂停'" placement="top"> | ||||||
|         <div |               <img | ||||||
|           class="volume" |                 :src="isPause ? 'https://cdn.cunwuyun.cn/slw2.0/images/play.png' : 'https://cdn.cunwuyun.cn/slw2.0/images/pause.png'" | ||||||
|           @mouseleave.stop="isShowVolume = false"> |                 @click="changePlayStatus"> | ||||||
|           <img  |             </el-tooltip> | ||||||
|             @mouseenter.stop="isShowVolume = true" |           </div> | ||||||
|             src="https://cdn.cunwuyun.cn/slw2.0/images/sound.png"> |           <div | ||||||
|           <div class="volume-slider" :class="[isShowVolume ? 'active' : '']"> |             class="volume" | ||||||
|             <el-slider |             @mouseleave.stop="isShowVolume = false"> | ||||||
|               input-size="mini" |             <img  | ||||||
|               v-model="volume" |               @mouseenter.stop="isShowVolume = true" | ||||||
|               vertical |               src="https://cdn.cunwuyun.cn/slw2.0/images/sound.png"> | ||||||
|               @change="onVolume" |             <div class="volume-slider" :class="[isShowVolume ? 'active' : '']"> | ||||||
|               height="80px"> |               <el-slider | ||||||
|             </el-slider> |                 input-size="mini" | ||||||
|  |                 v-model="volume" | ||||||
|  |                 vertical | ||||||
|  |                 @change="onVolume" | ||||||
|  |                 height="80px"> | ||||||
|  |               </el-slider> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|  |           <div class="play-status"> | ||||||
|  |             <div class="live" v-if="isLiveing"> | ||||||
|  |               <span class="label"></span> | ||||||
|  |               <i>直播中</i> | ||||||
|  |               <em>{{ form.date }}</em> | ||||||
|  |             </div> | ||||||
|  |             <div v-else class="back-btn" @click="isLiveing = true">回到直播</div> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|       </div> |         <div class="right"> | ||||||
|       <div class="right"> |           <el-tooltip effect="dark" content="选择日期" placement="top"> | ||||||
|         <img src="https://cdn.cunwuyun.cn/slw2.0/images/date.png" @click="isShowDate = true"> |             <img src="https://cdn.cunwuyun.cn/slw2.0/images/date.png" @click="isShowDate = true"> | ||||||
|         <img src="https://cdn.cunwuyun.cn/slw2.0/images/screenshots.png" title="截屏" @click="screenshots"> |           </el-tooltip> | ||||||
|         <img src="https://cdn.cunwuyun.cn/slw2.0/images/full-screen.png" :title="isFullscreen ? '退出全屏' : '全屏'" @click="fullscreen"> |           <el-tooltip effect="dark" content="截屏" placement="top"> | ||||||
|  |             <img src="https://cdn.cunwuyun.cn/slw2.0/images/screenshots.png" @click="screenshots"> | ||||||
|  |           </el-tooltip> | ||||||
|  |           <el-tooltip effect="dark" :content="isFullscreen ? '退出全屏' : '全屏'" placement="top"> | ||||||
|  |             <img src="https://cdn.cunwuyun.cn/slw2.0/images/full-screen.png" @click="fullscreen"> | ||||||
|  |           </el-tooltip> | ||||||
|  |         </div> | ||||||
|       </div> |       </div> | ||||||
|     </div> |     </div> | ||||||
|     <ai-dialog |     <ai-dialog | ||||||
| @@ -63,11 +83,17 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
|  |   import Timeline from './Timeline' | ||||||
|  |  | ||||||
|   export default { |   export default { | ||||||
|     props: ['src', 'name'], |     props: ['src', 'name'], | ||||||
|  |  | ||||||
|     name: 'slwVideo', |     name: 'slwVideo', | ||||||
|  |  | ||||||
|  |     components: { | ||||||
|  |       Timeline | ||||||
|  |     }, | ||||||
|  |  | ||||||
|     data () { |     data () { | ||||||
|       return { |       return { | ||||||
|         currIndex: 0, |         currIndex: 0, | ||||||
| @@ -75,9 +101,13 @@ | |||||||
|         isShowPlayBtn: false, |         isShowPlayBtn: false, | ||||||
|         isShow: true, |         isShow: true, | ||||||
|         isShowVolume: false, |         isShowVolume: false, | ||||||
|  |         isLiveing: true, | ||||||
|         form: { |         form: { | ||||||
|           date: '' |           date: '' | ||||||
|         }, |         }, | ||||||
|  |         date: '', | ||||||
|  |         isPause: false, | ||||||
|  |         width: '', | ||||||
|         volume: 100, |         volume: 100, | ||||||
|         videoId: `slwvideo-${new Date().getTime()}`, |         videoId: `slwvideo-${new Date().getTime()}`, | ||||||
|         id: `video-${new Date().getTime()}`, |         id: `video-${new Date().getTime()}`, | ||||||
| @@ -102,6 +132,10 @@ | |||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     mounted () { |     mounted () { | ||||||
|  |       this.form.date = this.$moment(new Date()).format('YYYY-MM-DD') | ||||||
|  |       this.$nextTick(() => { | ||||||
|  |         this.width = document.querySelector(`#${this.videoId}`).offsetWidth + 'px' | ||||||
|  |       }) | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     methods: { |     methods: { | ||||||
| @@ -117,6 +151,16 @@ | |||||||
|         } |         } | ||||||
|       }, |       }, | ||||||
|  |  | ||||||
|  |       changePlayStatus () { | ||||||
|  |         const subPage = document.querySelector(`#${this.id}`).contentWindow | ||||||
|  |         subPage.postMessage({ | ||||||
|  |           type: 'play', | ||||||
|  |           value: this.isPause | ||||||
|  |         }, '*') | ||||||
|  |          | ||||||
|  |         this.isPause = !this.isPause | ||||||
|  |       }, | ||||||
|  |  | ||||||
|       onConfirm () { |       onConfirm () { | ||||||
|         this.$refs.form.validate((valid) => { |         this.$refs.form.validate((valid) => { | ||||||
|           if (valid) { |           if (valid) { | ||||||
| @@ -141,6 +185,16 @@ | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         this.isFullscreen = !this.isFullscreen |         this.isFullscreen = !this.isFullscreen | ||||||
|  |         this.reset() | ||||||
|  |       }, | ||||||
|  |  | ||||||
|  |       reset () { | ||||||
|  |         setTimeout(() => { | ||||||
|  |           this.width = document.querySelector(`#${this.videoId}`).offsetWidth + 'px' | ||||||
|  |           this.$nextTick(() => { | ||||||
|  |             this.$refs.timeline.init() | ||||||
|  |           }) | ||||||
|  |         }, 60) | ||||||
|       }, |       }, | ||||||
|  |  | ||||||
|       screenshots () { |       screenshots () { | ||||||
| @@ -174,11 +228,31 @@ | |||||||
|     position: relative; |     position: relative; | ||||||
|     width: 100%; |     width: 100%; | ||||||
|     height: 100%; |     height: 100%; | ||||||
|  |     overflow: hidden; | ||||||
|  |  | ||||||
|     iframe { |     iframe { | ||||||
|       border: none; |       border: none; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     .slw-bottom { | ||||||
|  |       position: absolute; | ||||||
|  |       bottom: 0; | ||||||
|  |       left: 0; | ||||||
|  |       z-index: 1; | ||||||
|  |       width: 100%; | ||||||
|  |       transition: all ease-in-out 0.5s; | ||||||
|  |       // transform: translateY(100%); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     &:hover { | ||||||
|  |       .slw-title { | ||||||
|  |         transform: translateY(0%); | ||||||
|  |       } | ||||||
|  |       .slw-bottom { | ||||||
|  |         transform: translateY(0%); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     .slw-title { |     .slw-title { | ||||||
|       display: flex; |       display: flex; | ||||||
|       position: absolute; |       position: absolute; | ||||||
| @@ -192,11 +266,17 @@ | |||||||
|       line-height: 40px; |       line-height: 40px; | ||||||
|       padding: 0 16px; |       padding: 0 16px; | ||||||
|       background: rgba(0, 0, 0, 0.8); |       background: rgba(0, 0, 0, 0.8); | ||||||
|  |       transition: all ease 0.5s; | ||||||
|  |       transform: translateY(-100%); | ||||||
|  |  | ||||||
|       h2 { |       h2 { | ||||||
|  |         max-width: 70%; | ||||||
|         font-size: 16px; |         font-size: 16px; | ||||||
|         color: #fff; |         color: #fff; | ||||||
|         font-weight: normal; |         font-weight: normal; | ||||||
|  |         white-space: nowrap; | ||||||
|  |         overflow: hidden; | ||||||
|  |         text-overflow: ellipsis;   | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       .slw-title__close { |       .slw-title__close { | ||||||
| @@ -228,19 +308,80 @@ | |||||||
|  |  | ||||||
|     .action-bar { |     .action-bar { | ||||||
|       display: flex; |       display: flex; | ||||||
|       position: absolute; |  | ||||||
|       align-items: center; |       align-items: center; | ||||||
|       justify-content: space-between; |       justify-content: space-between; | ||||||
|       bottom: 0; |  | ||||||
|       left: 0; |  | ||||||
|       z-index: 1; |  | ||||||
|       width: 100%; |       width: 100%; | ||||||
|       height: 40px; |       height: 40px; | ||||||
|       padding: 0 16px; |       padding: 0 16px; | ||||||
|       background: rgba(0, 0, 0, 0.8); |       background: rgba(0, 0, 0, 0.8); | ||||||
|  |  | ||||||
|       .left { |       .left { | ||||||
|  |         display: flex; | ||||||
|  |         align-items: center; | ||||||
|  |  | ||||||
|  |         .play-status { | ||||||
|  |           display: flex; | ||||||
|  |           align-items: center; | ||||||
|  |           margin-left: 12px; | ||||||
|  |  | ||||||
|  |           em { | ||||||
|  |             margin-left: 12px; | ||||||
|  |             font-style: normal; | ||||||
|  |             color: #fff; | ||||||
|  |             font-size: 12px; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           .back-btn { | ||||||
|  |             padding: 4px 10px; | ||||||
|  |             border-radius: 6px; | ||||||
|  |             color: #ddd; | ||||||
|  |             font-size: 12px; | ||||||
|  |             cursor: pointer; | ||||||
|  |             background: #343747; | ||||||
|  |  | ||||||
|  |             &:hover { | ||||||
|  |               opacity: 0.6; | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           .live { | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             padding: 2px 5px; | ||||||
|  |             color: rgba(0,255,0,.8); | ||||||
|  |  | ||||||
|  |             i { | ||||||
|  |               font-size: 12px; | ||||||
|  |               font-style: normal; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             .label { | ||||||
|  |               width: 6px; | ||||||
|  |               height: 6px; | ||||||
|  |               margin-right: 12px; | ||||||
|  |               background: rgba(0,255,0,.8); | ||||||
|  |               border-radius: 50%; | ||||||
|  |               position: relative; | ||||||
|  |  | ||||||
|  |               &:after { | ||||||
|  |                 content: ""; | ||||||
|  |                 width: 12px; | ||||||
|  |                 height: 12px; | ||||||
|  |                 position: absolute; | ||||||
|  |                 left: 50%; | ||||||
|  |                 top: 50%; | ||||||
|  |                 -webkit-transform: translate(-50%,-50%); | ||||||
|  |                 transform: translate(-50%,-50%); | ||||||
|  |                 border-radius: 50%; | ||||||
|  |                 border: 4px solid rgba(0,255,0,.2); | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         .volume { |         .volume { | ||||||
|  |           display: flex; | ||||||
|  |           align-items: center; | ||||||
|           position: relative; |           position: relative; | ||||||
|           height: 100%; |           height: 100%; | ||||||
|  |  | ||||||
| @@ -271,13 +412,7 @@ | |||||||
|         .left-btns { |         .left-btns { | ||||||
|           display: flex; |           display: flex; | ||||||
|           align-items: center; |           align-items: center; | ||||||
|           width: 96px; |  | ||||||
|           height: 24px; |  | ||||||
|           margin-right: 10px; |           margin-right: 10px; | ||||||
|           background: #222838; |  | ||||||
|           border-radius: 100px; |  | ||||||
|           text-align: center; |  | ||||||
|           overflow: hidden; |  | ||||||
|  |  | ||||||
|           span { |           span { | ||||||
|             flex: 1; |             flex: 1; | ||||||
|   | |||||||
							
								
								
									
										262
									
								
								packages/IntelligentSecurity/components/Timeline.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								packages/IntelligentSecurity/components/Timeline.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,262 @@ | |||||||
|  | <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> | ||||||
		Reference in New Issue
	
	Block a user