<template>
<div class="outer-container">
<div class="container" ref="containerRef">
<div v-for="index in totalRectangles" :key="index - 1" class="rectangle" ref="rectangleRefs"
:style="{ backgroundColor: (index - 1) % 2 === 0 ? '#1E90FF' : '#FFB6C1' }">
</div>
<div v-for="line in lines" :key="line.color" class="line" :style="{
width: line.width + 'px',
backgroundColor: line.color,
left: line.left + 'px'
}">
<span class="line-text">{{ line.startIndex }}</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch, onUnmounted } from 'vue'
interface Line {
startIndex: number
endIndex: number
color: string
width: number
left: number
}
const totalRectangles = ref(30)
const containerRef = ref<HTMLElement | null>(null)
const rectangleRefs = ref<HTMLElement[]>([])
const lines = ref<Line[]>([
{ startIndex: 0, endIndex: 5, color: 'red', width: 0, left: 0 },
{ startIndex: 6, endIndex: 20, color: 'blue', width: 0, left: 0 },
{ startIndex: 21, endIndex: 29, color: 'green', width: 0, left: 0 }
])
const calculateLineWidths = () => {
if (!containerRef.value || rectangleRefs.value.length === 0) return
lines.value = lines.value.map(line => {
const startRect = rectangleRefs.value[line.startIndex]
const endRect = rectangleRefs.value[line.endIndex]
if (!startRect || !endRect) return line
const startPosition = startRect.getBoundingClientRect().left
const endPosition = endRect.getBoundingClientRect().right
const containerLeft = containerRef.value!.getBoundingClientRect().left
return {
...line,
width: endPosition - startPosition,
left: startPosition - containerLeft
}
})
}
const calculateIndex = (arr: number[]) => {
let len = arr.length
const res = []
for (let i = 0; i < len; i++) {
let startIndex
let endIndex
let channelTpye
if (i === 0) {
startIndex = 0
endIndex = arr[i].data.length - 1
channelTpye = arr[i].channelType
} else {
startIndex = arr[i - 1].endIndex + 1
endIndex = arr[i].data.length - 1 + startIndex
channelTpye = arr[i].channelType
}
res.push({
startIndex,
endIndex,
channelTpye,
with: 0,
left: 0
})
}
return res
}
// 监听窗口大小变化
window.addEventListener('resize', calculateLineWidths)
// 在组件挂载后计算线宽度
onMounted(() => {
calculateLineWidths()
window.addEventListener('resize', calculateLineWidths)
})
onUnmounted(() => {
window.removeEventListener('resize', calculateLineWidths)
})
// 监听长方形数量变化
watch(totalRectangles, () => {
setTimeout(calculateLineWidths, 0)
})
</script>
<style scoped>
.outer-container {
width: 500px;
margin: 0 auto;
}
.container {
display: flex;
justify-content: space-between;
padding: 20px;
position: relative;
width: 100%;
}
.rectangle {
width: 8px;
height: 20px;
}
.line {
position: absolute;
bottom: 10px;
height: 2px;
transition: all 0.3s ease;
text-align: center;
}
.line-text {
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 10px;
white-space: nowrap;
color: #333;
font-size: 12px;
}
</style>