2022-04-20 18:11:05 +08:00
< template >
2022-04-21 10:00:07 +08:00
< div :class = "wrapper" class = "canvas" v-if = "isInit" style="height: 52px" >
2022-04-28 11:21:45 +08:00
< canvas class = "canvas" :id = "id" :canvas-id = "id" : style = "{width: canvasWidth + 'px', height: canvasHeight + 'px'}" v-if = "canvasWidth" :width="canvasWidth" @click.stop="onClick" :height="canvasHeight" >
2022-04-20 18:11:05 +08:00
< / canvas >
2022-04-28 15:58:10 +08:00
< em : style = "{height: '24px', left: x + 'px'}" > < / em >
< img class = "drag-img" : style = "{ left: x + 'px'}" @touchstart ="touchstart" @touchmove ="touchmove" @touchend ="touchend" src = "https://cdn.cunwuyun.cn/slw2.0/images/drag.png" / >
2022-04-20 18:11:05 +08:00
< / div >
< / template >
< script >
export default {
props : [ 'isLiveing' , 'times' ] ,
data ( ) {
return {
2022-04-28 11:21:45 +08:00
x : 0 ,
id : ` timeline- ${ new Date ( ) . getTime ( ) } ` ,
2022-04-20 18:11:05 +08:00
ctx : null ,
time : '' ,
left : 0 ,
2022-04-28 11:21:45 +08:00
timer : null ,
scale : 4 ,
2022-04-20 18:11:05 +08:00
ratioW : '' ,
isHide : true ,
isInit : false ,
isChoose : false ,
wrapper : ` canvas- ${ new Date ( ) . getTime ( ) } ` ,
2022-04-28 11:21:45 +08:00
canvasWidth : '' ,
canvasHeight : ''
2022-04-20 18:11:05 +08:00
}
} ,
watch : {
isLiveing ( ) {
this . countdown ( )
} ,
times : {
deep : true ,
handler ( v ) {
if ( v . length && this . ctx ) {
this . init ( )
}
}
}
} ,
mounted ( ) {
this . $nextTick ( ( ) => {
this . init ( )
} )
} ,
destroyed ( ) {
clearInterval ( this . timer )
} ,
methods : {
2022-04-28 15:58:10 +08:00
touchmove ( e ) {
this . x = e . touches [ 0 ] . clientY
} ,
touchstart ( e ) {
} ,
touchend ( e ) {
clearInterval ( this . timer )
this . timer = null
const time = this . secTotime ( ( 24 * 60 * 60 ) / this . canvasWidth * this . x )
this . $emit ( 'replay' , time )
2022-04-20 18:11:05 +08:00
} ,
onClick ( e ) {
2022-04-21 10:00:07 +08:00
this . x = e . target . y
2022-04-20 18:11:05 +08:00
clearInterval ( this . timer )
this . timer = null
const time = this . secTotime ( ( 24 * 60 * 60 ) / this . canvasWidth * this . x )
this . $emit ( 'replay' , time )
} ,
secTotime ( s ) {
let second = parseInt ( s )
let minute = 0
let hour = 0
if ( second > 60 ) {
minute = parseInt ( second / 60 )
second = parseInt ( second % 60 )
if ( minute > 60 ) {
hour = parseInt ( minute / 60 )
minute = parseInt ( minute % 60 )
}
}
hour = ` ${ parseInt ( hour ) > 9 ? parseInt ( hour ) : '0' + parseInt ( hour ) } `
minute = ` ${ parseInt ( minute ) > 9 ? parseInt ( minute ) : '0' + parseInt ( minute ) } `
second = ` ${ parseInt ( second ) > 9 ? parseInt ( second ) : '0' + parseInt ( second ) } `
return ` ${ hour } : ${ minute } : ${ second } `
} ,
init ( ) {
if ( this . timer ) {
clearInterval ( this . timer )
this . timer = null
}
this . ratioW = this . x / this . canvasWidth
this . $nextTick ( ( ) => {
this . isInit = true
this . $nextTick ( ( ) => {
2022-04-21 10:00:07 +08:00
this . canvasWidth = uni . getSystemInfoSync ( ) . windowHeight
this . canvasHeight = document . querySelector ( ` . ${ this . wrapper } ` ) . offsetHeight
2022-04-20 18:11:05 +08:00
this . $nextTick ( ( ) => {
const el = document . querySelector ( ` # ${ this . id } ` )
this . ctx = uni . createCanvasContext ( ` ${ this . id } ` )
if ( this . x > 0 ) {
this . x = this . ratioW * this . canvasWidth
} else {
this . initNowTime ( )
}
this . renderTimeLine ( )
this . renderPlayback ( )
this . countdown ( )
} )
} )
} )
} ,
countdown ( ) {
this . timer = setInterval ( ( ) => {
if ( this . isLiveing ) {
this . initNowTime ( )
} else {
this . x = this . x + this . canvasWidth / ( 24 * 60 * 60 )
}
} , 1000 )
} ,
initNowTime ( ) {
const date = new Date ( )
const seconds = date . getHours ( ) * 3600 + date . getMinutes ( ) * 60 + date . getSeconds ( )
this . x = this . canvasWidth / ( 24 * 60 * 60 ) * seconds
} ,
drawLine ( ctx , options ) {
const { beginX , beginY , endX , endY , lineColor , lineWidth } = options
ctx . lineWidth = lineWidth
2022-04-22 10:45:41 +08:00
ctx . strokeStyle = lineColor
ctx . beginPath ( )
2022-04-20 18:11:05 +08:00
ctx . moveTo ( beginX , beginY )
ctx . lineTo ( endX , endY )
ctx . stroke ( )
2022-04-22 10:45:41 +08:00
ctx . closePath ( )
2022-04-20 18:11:05 +08:00
} ,
renderPlayback ( ) {
const ctx = this . ctx
const unit = this . canvasWidth / ( 24 * 60 * 60 )
this . times . forEach ( item => {
this . drawLine ( ctx , {
beginX : item . startTime * unit ,
beginY : 28 ,
endX : item . startTime * unit ,
endY : 0 ,
lineColor : 'rgba(0, 156, 255, 1)' ,
lineWidth : item . endTime * unit - item . startTime * unit
} )
} )
2022-04-22 10:45:41 +08:00
ctx . draw ( true )
2022-04-20 18:11:05 +08:00
} ,
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 % ;
2022-04-28 15:58:10 +08:00
& > em {
position : absolute ;
bottom : 0 ;
z - index : 11 ;
width : 4 px ;
height : 24 px ;
background : # fff ;
transform : translateX ( - 50 % ) ;
}
2022-04-20 18:11:05 +08:00
. drag - img {
position : absolute ;
left : 0 ;
top : 0 ;
z - index : 1 ;
user - select : none ;
cursor : e - resize ;
- webkit - user - drag : none ;
2022-04-22 10:45:41 +08:00
transform : translateX ( - 50 % ) ;
2022-04-20 18:11:05 +08:00
}
. time - scale {
display : flex ;
position : absolute ;
align - items : center ;
justify - content : center ;
left : 0 ;
bottom : 0 ;
z - index : 1 ;
user - select : none ;
width : 12 px ;
height : 24 px ;
span {
width : 2 px ;
height : 24 px ;
background : rgba ( 255 , 255 , 255 , 0.8 ) ;
}
}
. time {
position : absolute ;
bottom : 22 px ;
left : 0 ;
z - index : 1 ;
padding : 2 px 4 px ;
font - size : 12 px ;
color : # fff ;
background : rgba ( 0 , 0 , 0 , 1 ) ;
transform : translate ( - 50 % , 100 % ) ;
}
}
< / style >