Files
wvp-platform/web/src/views/common/VideoTimeLine/WindowListItem.vue
2025-04-28 15:04:06 +08:00

196 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div ref="windowListItem" class="windowListItem" :class="{active: active}" @click="onClick">
<span class="order">{{ index + 1 }}</span>
<canvas ref="canvas" class="windowListItemCanvas" />
</div>
</template>
<script>
export default {
name: 'WindowListItem',
props: {
index: {
type: Number
},
data: {
type: Object,
default() {
return {}
}
},
totalMS: {
type: Number
},
startTimestamp: {
type: Number
},
width: {
type: Number
},
active: {
type: Boolean,
default: false
}
},
data() {
return {
height: 0,
ctx: null
}
},
mounted() {
this.init()
this.drawTimeSegments()
},
methods: {
/**
* @Author: 王林25
* @Date: 2020-04-14 09:20:22
* @Desc: 初始化
*/
init() {
const { height } = this.$refs.windowListItem.getBoundingClientRect()
this.height = height - 1
this.$refs.canvas.width = this.width
this.$refs.canvas.height = this.height
this.ctx = this.$refs.canvas.getContext('2d')
},
/**
* @Author: 王林25
* @Date: 2020-04-14 15:42:49
* @Desc: 绘制时间段
*/
drawTimeSegments(callback, path) {
if (!this.data.timeSegments || this.data.timeSegments.length <= 0) {
return
}
const PX_PER_MS = this.width / this.totalMS // px/ms每毫秒占的像素
this.data.timeSegments.forEach((item) => {
if (
item.beginTime <= this.startTimestamp + this.totalMS &&
item.endTime >= this.startTimestamp
) {
this.ctx.beginPath()
let x = (item.beginTime - this.startTimestamp) * PX_PER_MS
let w
if (x < 0) {
x = 0
w = (item.endTime - this.startTimestamp) * PX_PER_MS
} else {
w = (item.endTime - item.beginTime) * PX_PER_MS
}
const heightStartRatio = item.startRatio === undefined ? 0.6 : item.startRatio
const heightEndRatio = item.endRatio === undefined ? 0.9 : item.endRatio
if (path) {
this.ctx.rect(
x,
this.height * heightStartRatio,
w,
this.height * (heightEndRatio - heightStartRatio)
)
} else {
this.ctx.fillStyle = item.color
this.ctx.fillRect(
x,
this.height * heightStartRatio,
w,
this.height * (heightEndRatio - heightStartRatio)
)
}
callback && callback(item)
}
})
},
/**
* @Author: 王林25
* @Date: 2020-04-14 14:25:43
* @Desc: 清除画布
*/
clearCanvas() {
this.ctx.clearRect(0, 0, this.width, this.height)
},
/**
* @Author: 王林25
* @Date: 2021-01-20 19:07:31
* @Desc: 绘制
*/
draw() {
this.$nextTick(() => {
this.clearCanvas()
this.drawTimeSegments()
})
},
/**
* @Author: 王林25
* @Date: 2021-01-20 19:26:46
* @Desc: 点击事件
*/
onClick(e) {
this.$emit('click', e)
const { left, top } = this.$refs.windowListItem.getBoundingClientRect()
const x = e.clientX - left
const y = e.clientY - top
const timeSegments = this.getClickTimeSegments(x, y)
if (timeSegments.length > 0) {
this.$emit('click_window_timeSegments', timeSegments, this.index, this.data)
}
},
/**
* @Author: 王林25
* @Date: 2021-01-20 16:24:54
* @Desc: 检测当前是否点击了某个时间段
*/
getClickTimeSegments(x, y) {
if (!this.data.timeSegments || this.data.timeSegments.length <= 0) {
return []
}
const inItems = []
this.drawTimeSegments((item) => {
if (this.ctx.isPointInPath(x, y)) {
inItems.push(item)
}
}, true)
return inItems
},
/**
* @Author: 王林25
* @Date: 2021-01-21 11:25:26
* @Desc: 获取位置信息
*/
getRect() {
return this.$refs.windowListItem ? this.$refs.windowListItem.getBoundingClientRect() : null
}
}
}
</script>
<style scoped>
.windowListItem {
width: 100%;
height: 30px;
position: relative;
border-bottom: 1px solid #999999;
user-select: none;
}
.windowListItem.active {
background-color: #000;
}
.windowListItem .order {
position: absolute;
width: 30px;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
border-right: 1px solid #999999;
}
</style>