FPGA_WebLab/src/components/equipments/SevenSegmentDisplay.vue

257 lines
7.8 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 class="seven-segment-display" :style="{ width: width + 'px', height: height + 'px', position: 'relative' }"> <svg
xmlns="http://www.w3.org/2000/svg"
:width="width"
:height="height"
viewBox="0 0 120 220"
class="display"
>
<!-- 数码管基座 -->
<rect width="120" height="180" x="0" y="0" fill="#222" rx="10" ry="10" />
<rect width="110" height="170" x="5" y="5" fill="#333" rx="5" ry="5" />
<!-- 7 + 小数点每个段由多边形表示重新设计点位置使其更接近实际数码管 -->
<!-- a段 (顶部横线) -->
<polygon
:points="'30,20 90,20 98,28 82,36 38,36 22,28'"
:fill="isSegmentActive('a') ? segmentColor : inactiveColor"
:style="{ opacity: isSegmentActive('a') ? 1 : 0.15 }"
class="segment"
/>
<!-- b段 (右上竖线) -->
<polygon
:points="'100,30 108,38 108,82 100,90 92,82 92,38'"
:fill="isSegmentActive('b') ? segmentColor : inactiveColor"
:style="{ opacity: isSegmentActive('b') ? 1 : 0.15 }"
class="segment"
/>
<!-- c段 (右下竖线) -->
<polygon
:points="'100,90 108,98 108,142 100,150 92,142 92,98'"
:fill="isSegmentActive('c') ? segmentColor : inactiveColor"
:style="{ opacity: isSegmentActive('c') ? 1 : 0.15 }"
class="segment"
/>
<!-- d段 (底部横线) -->
<polygon
:points="'30,160 90,160 98,152 82,144 38,144 22,152'"
:fill="isSegmentActive('d') ? segmentColor : inactiveColor"
:style="{ opacity: isSegmentActive('d') ? 1 : 0.15 }"
class="segment"
/>
<!-- e段 (左下竖线) -->
<polygon
:points="'20,90 28,98 28,142 20,150 12,142 12,98'"
:fill="isSegmentActive('e') ? segmentColor : inactiveColor"
:style="{ opacity: isSegmentActive('e') ? 1 : 0.15 }"
class="segment"
/>
<!-- f段 (左上竖线) -->
<polygon
:points="'20,30 28,38 28,82 20,90 12,82 12,38'"
:fill="isSegmentActive('f') ? segmentColor : inactiveColor"
:style="{ opacity: isSegmentActive('f') ? 1 : 0.15 }"
class="segment"
/>
<!-- g段 (中间横线) -->
<polygon
:points="'30,90 38,82 82,82 90,90 82,98 38,98'"
:fill="isSegmentActive('g') ? segmentColor : inactiveColor"
:style="{ opacity: isSegmentActive('g') ? 1 : 0.15 }"
class="segment"
/> <!-- dp段 (小数点) -->
<circle
cx="108"
cy="154"
r="6"
:fill="isSegmentActive('dp') ? segmentColor : inactiveColor"
:style="{ opacity: isSegmentActive('dp') ? 1 : 0.15 }"
class="segment"
/>
</svg>
<!-- 引脚 -->
<div v-for="pin in pins" :key="pin.pinId"
:style="{
position: 'absolute',
left: `${pin.x * props.size}px`,
top: `${pin.y * props.size}px`,
transform: 'translate(-50%, -50%)'
}"
:data-pin-wrapper="`${pin.pinId}`"
:data-pin-x="`${pin.x * props.size}`"
:data-pin-y="`${pin.y * props.size}`">
<Pin
:ref="el => { if(el) pinRefs[pin.pinId] = el }"
:label="pin.pinId"
:constraint="pin.constraint"
:pinId="pin.pinId"
@pin-click="$emit('pin-click', $event)"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
import { getConstraintState, onConstraintStateChange } from '../../stores/constraints';
import Pin from './Pin.vue';
// 存储Pin引用
const pinRefs = ref<Record<string, any>>({});
// 数码管属性
interface SevenSegmentDisplayProps {
size?: number;
color?: string;
pins?: {
pinId: string;
constraint: string;
x: number;
y: number;
}[];
cathodeType?: 'common' | 'anode'; // 共阴极或共阳极
}
const props = withDefaults(defineProps<SevenSegmentDisplayProps>(), {
size: 1,
color: 'red',
cathodeType: 'common', // 默认为共阴极
pins: () => [
{ pinId: 'a', constraint: '', x: 10 , y: 170 }, // a段
{ pinId: 'b', constraint: '', x: 25-1 , y: 170 }, // b段
{ pinId: 'c', constraint: '', x: 40-2 , y: 170 }, // c段
{ pinId: 'd', constraint: '', x: 55-3 , y: 170 }, // d段
{ pinId: 'e', constraint: '', x: 70-4 , y: 170 }, // e段
{ pinId: 'f', constraint: '', x: 85-5 , y: 170 }, // f段
{ pinId: 'g', constraint: '', x: 100-6, y: 170 }, // g段
{ pinId: 'dp', constraint: '', x: 115-7, y: 170 }, // 小数点
{ pinId: 'COM', constraint: '', x: 60 , y: 10 } // 公共端,稍微低一点
]
});
const width = computed(() => 120 * props.size);
const height = computed(() => 220 * props.size);
// 计算段颜色和非激活状态颜色
const segmentColor = computed(() => props.color || 'red');
const inactiveColor = computed(() => '#FFFFFF');
// 监听props变化
watch(
() => props,
(newProps) => {
console.log('SevenSegmentDisplay props changed:', newProps);
updateSegmentStates();
},
{ deep: true }
);
// 段引脚状态
const segmentStates = ref({
a: false,
b: false,
c: false,
d: false,
e: false,
f: false,
g: false,
dp: false,
});
// 判断段是否激活
function isSegmentActive(segment: 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'dp'): boolean {
return segmentStates.value[segment];
}
// 更新引脚状态的函数
function updateSegmentStates() {
for (const pin of props.pins) {
if (['a', 'b', 'c', 'd', 'e', 'f', 'g', 'dp'].includes(pin.pinId)) {
// 如果constraint为空则默认为未激活状态
if (!pin.constraint) {
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = false;
continue;
}
const pinState = getConstraintState(pin.constraint);
// 根据阴极/阳极类型反转逻辑
if (props.cathodeType === 'common') {
// 共阴极: 高电平激活段
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = pinState === 'high';
} else {
// 共阳极: 低电平激活段
segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = pinState === 'low';
}
}
}
}
// 监听约束状态变化
function onConstraintChange(constraint: string, level: string) {
const affectedPin = props.pins.find(pin => pin.constraint === constraint);
if (affectedPin && ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'dp'].includes(affectedPin.pinId)) {
updateSegmentStates();
}
}
// 生命周期钩子
onMounted(() => {
updateSegmentStates();
onConstraintStateChange(onConstraintChange);
});
onUnmounted(() => {
// 清理约束状态监听
});
// 暴露属性和方法
defineExpose({
updateSegmentStates
});
</script>
<style scoped>
.seven-segment-display {
display: inline-block;
position: relative;
}
.segment {
transition: opacity 0.2s, fill 0.2s;
}
/* 数码管发光效果 */
.segment[style*="opacity: 1"] {
filter: drop-shadow(0 0 4px v-bind(segmentColor)) drop-shadow(0 0 2px v-bind(segmentColor));
}
</style>
<!-- 导出默认属性函数供外部使用 -->
<script lang="ts">
export function getDefaultProps() {
return {
size: 1,
color: 'red',
cathodeType: 'common',
pins: [
{ pinId: 'a', constraint: '', x: 10 , y: 170 },
{ pinId: 'b', constraint: '', x: 25-1 , y: 170 },
{ pinId: 'c', constraint: '', x: 40-2 , y: 170 },
{ pinId: 'd', constraint: '', x: 55-3 , y: 170 },
{ pinId: 'e', constraint: '', x: 70-4 , y: 170 },
{ pinId: 'f', constraint: '', x: 85-5 , y: 170 },
{ pinId: 'g', constraint: '', x: 100-6, y: 170 },
{ pinId: 'dp', constraint: '', x: 115-7, y: 170 },
{ pinId: 'COM', constraint: '', x: 60 , y: 10 }
]
};
}
</script>