fix:修复七段数码管的显示问题
This commit is contained in:
		@@ -79,6 +79,7 @@ interface SevenSegmentDisplayProps {
 | 
			
		||||
  size?: number;
 | 
			
		||||
  color?: string;
 | 
			
		||||
  AFTERGLOW_BUFFER_SIZE?: number; // 余晖存储槽大小
 | 
			
		||||
  AFTERGLOW_DURATION?: number; // 余晖持续时间(毫秒)
 | 
			
		||||
  pins?: {
 | 
			
		||||
    pinId: string;
 | 
			
		||||
    constraint: string;
 | 
			
		||||
@@ -92,7 +93,7 @@ const props = withDefaults(defineProps<SevenSegmentDisplayProps>(), {
 | 
			
		||||
  size: 1,
 | 
			
		||||
  color: "red",
 | 
			
		||||
  AFTERGLOW_BUFFER_SIZE: 1, // 默认存储槽大小为100
 | 
			
		||||
  AFTERGLOW_UPDATE_INTERVAL: 5, // 默认更新间隔为2毫秒
 | 
			
		||||
  AFTERGLOW_DURATION: 2000, // 默认余晖持续时间500毫秒
 | 
			
		||||
  cathodeType: "common", // 默认为共阴极
 | 
			
		||||
  pins: () => [
 | 
			
		||||
    { pinId: "a", constraint: "", x: 10, y: 170 }, // a段
 | 
			
		||||
@@ -149,7 +150,7 @@ const afterglowBuffers = ref<Record<string, boolean[]>>({
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 余晖判定阈值(比如持续10帧才算稳定,可根据刷新间隔和人眼余晖调节)
 | 
			
		||||
const STABLE_THRESHOLD = 10;
 | 
			
		||||
const STABLE_THRESHOLD = 3;
 | 
			
		||||
 | 
			
		||||
// 实际显示的段状态(只有稳定后才改变)
 | 
			
		||||
const stableSegmentStates = ref({
 | 
			
		||||
@@ -175,10 +176,54 @@ const segmentStableCounters = ref<Record<string, number>>({
 | 
			
		||||
  dp: 0,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 判断段是否激活(用稳定状态)
 | 
			
		||||
// 段选关闭时的余晖状态保持
 | 
			
		||||
const afterglowStates = ref({
 | 
			
		||||
  a: false,
 | 
			
		||||
  b: false,
 | 
			
		||||
  c: false,
 | 
			
		||||
  d: false,
 | 
			
		||||
  e: false,
 | 
			
		||||
  f: false,
 | 
			
		||||
  g: false,
 | 
			
		||||
  dp: false,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 余晖计时器
 | 
			
		||||
const afterglowTimers = ref<Record<string, number | null>>({
 | 
			
		||||
  a: null,
 | 
			
		||||
  b: null,
 | 
			
		||||
  c: null,
 | 
			
		||||
  d: null,
 | 
			
		||||
  e: null,
 | 
			
		||||
  f: null,
 | 
			
		||||
  g: null,
 | 
			
		||||
  dp: null,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 余晖持续时间(毫秒)
 | 
			
		||||
const AFTERGLOW_DURATION = computed(() => props.AFTERGLOW_DURATION || 500);
 | 
			
		||||
 | 
			
		||||
// 当前COM口状态
 | 
			
		||||
const currentComActive = ref(false); // 初始化为false,等待第一次状态检查
 | 
			
		||||
 | 
			
		||||
// 是否处于余晖模式
 | 
			
		||||
const isInAfterglowMode = ref(false);
 | 
			
		||||
 | 
			
		||||
// 判断段是否激活(用稳定状态或余晖状态)
 | 
			
		||||
function isSegmentActive(
 | 
			
		||||
  segment: "a" | "b" | "c" | "d" | "e" | "f" | "g" | "dp",
 | 
			
		||||
): boolean {
 | 
			
		||||
  // 如果处于余晖模式,使用余晖状态
 | 
			
		||||
  if (isInAfterglowMode.value) {
 | 
			
		||||
    return afterglowStates.value[segment];
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // 如果COM口未激活,所有段都不显示
 | 
			
		||||
  if (!currentComActive.value) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // 否则使用稳定状态
 | 
			
		||||
  return stableSegmentStates.value[segment];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -186,21 +231,45 @@ function isSegmentActive(
 | 
			
		||||
function updateSegmentStates() {
 | 
			
		||||
  // 先获取COM口状态
 | 
			
		||||
  const comPin = props.pins.find((p) => p.pinId === "COM");
 | 
			
		||||
  let comActive = true;
 | 
			
		||||
  let comActive = false; // 默认未激活
 | 
			
		||||
  
 | 
			
		||||
  if (comPin && comPin.constraint) {
 | 
			
		||||
    const comState = getConstraintState(comPin.constraint);
 | 
			
		||||
    if (props.cathodeType === "anode") {
 | 
			
		||||
      // anode模式下,COM为高电平则所有段都熄灭
 | 
			
		||||
      comActive = comState !== "high";
 | 
			
		||||
      // 共阳极模式下,COM为低电平才激活
 | 
			
		||||
      comActive = comState === "low";
 | 
			
		||||
    } else {
 | 
			
		||||
      // 共阴极模式下,COM为低电平才激活
 | 
			
		||||
      comActive = comState === "low";
 | 
			
		||||
    }
 | 
			
		||||
    // 可扩展其他模式
 | 
			
		||||
  } else if (!comPin || !comPin.constraint) {
 | 
			
		||||
    // 如果没有COM引脚或者COM引脚没有约束,则认为始终激活
 | 
			
		||||
    comActive = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 如果COM口激活,更新所有段的状态到存储槽
 | 
			
		||||
  if (comActive) {
 | 
			
		||||
    updateAfterglowBuffers();
 | 
			
		||||
  // 检查COM口状态是否发生变化
 | 
			
		||||
  const comStateChanged = currentComActive.value !== comActive;
 | 
			
		||||
  currentComActive.value = comActive;
 | 
			
		||||
 | 
			
		||||
  // 如果COM从激活变为非激活,进入余晖模式
 | 
			
		||||
  if (comStateChanged && !comActive) {
 | 
			
		||||
    enterAfterglowMode();
 | 
			
		||||
    return; // 在余晖模式下,不处理其他引脚变化
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 如果COM从非激活变为激活,退出余晖模式
 | 
			
		||||
  if (comStateChanged && comActive) {
 | 
			
		||||
    exitAfterglowMode();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 关键修复:如果COM口未激活或处于余晖模式,不处理任何引脚状态变化
 | 
			
		||||
  if (!comActive || isInAfterglowMode.value) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 只有当COM口激活时,才更新段的状态
 | 
			
		||||
  updateAfterglowBuffers();
 | 
			
		||||
 | 
			
		||||
  // 先更新 segmentStates
 | 
			
		||||
  for (const pin of props.pins) {
 | 
			
		||||
    if (["a", "b", "c", "d", "e", "f", "g", "dp"].includes(pin.pinId)) {
 | 
			
		||||
@@ -215,7 +284,8 @@ function updateSegmentStates() {
 | 
			
		||||
      } else {
 | 
			
		||||
        newState = pinState === "low";
 | 
			
		||||
      }
 | 
			
		||||
      segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState && comActive;
 | 
			
		||||
      // 段状态只有在COM激活时才有效
 | 
			
		||||
      segmentStates.value[pin.pinId as keyof typeof segmentStates.value] = newState;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -255,6 +325,49 @@ function updateAfterglowBuffers() {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 进入余晖模式
 | 
			
		||||
function enterAfterglowMode() {
 | 
			
		||||
  isInAfterglowMode.value = true;
 | 
			
		||||
  
 | 
			
		||||
  // 保存当前稳定状态作为余晖状态
 | 
			
		||||
  for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
 | 
			
		||||
    const typedSegmentId = segmentId as keyof typeof stableSegmentStates.value;
 | 
			
		||||
    afterglowStates.value[typedSegmentId] = stableSegmentStates.value[typedSegmentId];
 | 
			
		||||
    
 | 
			
		||||
    // 设置定时器,在余晖持续时间后退出余晖模式
 | 
			
		||||
    if (afterglowTimers.value[segmentId]) {
 | 
			
		||||
      clearTimeout(afterglowTimers.value[segmentId]!);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    afterglowTimers.value[segmentId] = setTimeout(() => {
 | 
			
		||||
      afterglowStates.value[typedSegmentId] = false;
 | 
			
		||||
      
 | 
			
		||||
      // 检查是否所有段都已经关闭
 | 
			
		||||
      const allSegmentsOff = Object.values(afterglowStates.value).every(state => !state);
 | 
			
		||||
      if (allSegmentsOff) {
 | 
			
		||||
        exitAfterglowMode();
 | 
			
		||||
      }
 | 
			
		||||
    }, AFTERGLOW_DURATION.value);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 退出余晖模式
 | 
			
		||||
function exitAfterglowMode() {
 | 
			
		||||
  isInAfterglowMode.value = false;
 | 
			
		||||
  
 | 
			
		||||
  // 清除所有定时器
 | 
			
		||||
  for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
 | 
			
		||||
    if (afterglowTimers.value[segmentId]) {
 | 
			
		||||
      clearTimeout(afterglowTimers.value[segmentId]!);
 | 
			
		||||
      afterglowTimers.value[segmentId] = null;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // 重置余晖状态
 | 
			
		||||
    const typedSegmentId = segmentId as keyof typeof afterglowStates.value;
 | 
			
		||||
    afterglowStates.value[typedSegmentId] = false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 监听约束状态变化
 | 
			
		||||
function onConstraintChange(constraint: string, level: string) {
 | 
			
		||||
  const affectedPin = props.pins.find((pin) => pin.constraint === constraint);
 | 
			
		||||
@@ -276,6 +389,15 @@ onMounted(() => {
 | 
			
		||||
  onConstraintStateChange(onConstraintChange);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onUnmounted(() => {
 | 
			
		||||
  // 清理所有余晖定时器
 | 
			
		||||
  for (const segmentId of ["a", "b", "c", "d", "e", "f", "g", "dp"]) {
 | 
			
		||||
    if (afterglowTimers.value[segmentId]) {
 | 
			
		||||
      clearTimeout(afterglowTimers.value[segmentId]!);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 暴露属性和方法
 | 
			
		||||
defineExpose({
 | 
			
		||||
  updateSegmentStates,
 | 
			
		||||
@@ -307,6 +429,7 @@ export function getDefaultProps() {
 | 
			
		||||
    size: 1,
 | 
			
		||||
    color: "red",
 | 
			
		||||
    cathodeType: "common",
 | 
			
		||||
    AFTERGLOW_DURATION: 500, // 默认余晖持续时间500毫秒
 | 
			
		||||
    pins: [
 | 
			
		||||
      { pinId: "a", constraint: "", x: 10, y: 170 },
 | 
			
		||||
      { pinId: "b", constraint: "", x: 25 - 1, y: 170 },
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user