<script setup lang="ts">
import { ref } from "vue";
const lightList = ref(["#fa0110", "#fed31b", "#6fe802"]); //红灯 黄灯 绿灯
let idx = ref(0);
let lightTime = ref(0);
const delay = (ms: number) => new Promise((r) => setTimeout(r, ms));
// 等待切换
const wait = async (light: string, timeout: number) => {
return new Promise((resolve, reject) => {
resolve(light);
}).then(async (res) => {
idx.value = lightList.value.findIndex((item) => item == res); //颜色切换
// 倒计时
while (timeout && timeout > 0) {
lightTime.value = timeout;
await delay(1000);
timeout--;
}
});
};
// 红绿灯
const trafficLight = async (lights: Array<number>) => {
const waitList: Array<Function> = [];
for (let i = 0; i < 3; i++) {
const lightItem = () => wait(lightList.value[i], lights[i]);
waitList.push(lightItem);
}
waitList.push(() => wait(lightList.value[1], lights[1])); //绿灯切红灯之前的黄灯
while (true) {
// 循环调用切换
for await (const cb of waitList) {
await cb();
lightTime.value = 0; //切换之前把数值置零
await delay(1000);
}
}
};
trafficLight([8, 2, 5]); //红 黄 绿
</script>
<template>
<div
v-for="(item, index) in lightList"
style="display: flex; align-items: center; gap: 16px"
>
<div
class="light"
:class="{ flicker: idx === index && lightTime <= 3 && idx !== 1 }"
:style="{ background: idx === index ? item : 'transparent' }"
></div>
<div v-show="idx === index">{{ lightTime }}</div>
</div>
</template>
<style scoped>
.light {
width: 50px;
height: 50px;
border: 1px solid #666;
border-radius: 50%;
}
.flicker {
animation: bounce 1s linear infinite;
}
@keyframes bounce {
0% {
opacity: 0.4;
}
50% {
opacity: 1;
}
100% {
opacity: 0.4;
}
}
</style>
异步实现红绿灯模型
于 2023-06-19 10:06:07 首次发布