做一名遵守交通规则的程序员(红黄蓝灯交替亮🚥)

2,334 阅读3分钟

第1秒红灯亮,第2秒黄灯亮,第3秒蓝灯亮;如何让三个灯不断交替重复亮灯?

红绿灯长啥样?大家应该都见过吧

但是就是说,咱没有 UI 小姐姐给咱画图呀

没关系,找一个,抄一下呗

咱是程序员,不是画图的

图片.png

就这个了

ok, 先开始绘制页面了

先观察,背景是渐变蓝色

html {
    background: linear-gradient(#08f, #fff);
    padding: 40px;
    width: 170px;
    height: 100%;
    margin: 0 auto;
}

HTML 结构也很清晰

无标题-2022-01-09-1040.png

<div className="trafficlight">
    <div className="protector"></div>
    <div className="protector"></div>
    <div className="protector"></div>
    <div className="red"></div>
    <div className="yellow"></div>
    <div className="green"></div>
</div>

中间的主体部分

.trafficlight{
    background: #222;
    width: 170px;
    height: 400px;
    position: relative;
}

刷新看一下

图片.png

加一点点小细节

background-image: linear-gradient(transparent 2%, #111 2%, transparent 3%, #111 30%);
border-radius: 20px;
border: solid 5px #333;

图片.png

加个帽檐

.trafficlight:before{
    background: #222;
    background-image: radial-gradient(#444, #000);
    content: "";
    width: 170px;
    height: 150px;
    margin: 0 auto;
    position: absolute;
    top: -20px;
    margin-left: 0px;
    border-radius: 50%;
    z-index: -1;
}

图片.png

来个杆子

.trafficlight:after{
    background: #222;
    background-image: linear-gradient(-90deg, #222 0%, #444 30%, #000);
    content: "";
    width: 50px;
    height: 500px;
    margin-left: 60px;
    position: absolute;
    top: 150px;
    z-index: -1;
}

图片.png

旁边那三个小翅膀

.protector{
    background: transparent;
    width: 180px;
    height: 0;
    position: absolute;
    top: 20px;
    left: -35px;
    border-right: solid 30px transparent;
    border-left: solid 30px transparent;
    border-top: solid 90px #111;
    border-radius: 10px;
    z-index: -1;
}

.protector:nth-child(2){
    top: 140px;
}

.protector:nth-child(3){
    top: 260px;
}

图片.png

还不错,差最后一步,再来三个灯

.red{
    background-image: radial-gradient(rgb(83, 80, 80), transparent);
    background-size: 5px 5px;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    position: absolute;
    top: 20px;
    left: 35px;
}


.yellow{
    background-image: radial-gradient(rgb(83, 80, 80), transparent);
    background-size: 5px 5px;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    position: absolute;
    top: 145px;
    left: 35px;
}


.green{
    background-image: radial-gradient(rgb(83, 80, 80), transparent);
    background-size: 5px 5px;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    position: absolute;
    top: 270px;
    left: 35px;
}

图片.png

不使用Promise

按照逻辑依次执行:首先是红灯亮,调用黄灯亮;黄灯亮,调用蓝灯亮;蓝灯亮,再调用红灯亮...可以看到循环回调的现象。

那怎么亮?其实就是再添加一个类名,让其颜色显示出来。

const [highRedColor, setHightRedColor] = useState('');
const [highYellowColor, setHighYellowColor] = useState('');
const [highGreenColor, setHighGreenColor] = useState('');

const lightRed = () => {
    setHightRedColor('highRedColor');
    setHighYellowColor('');
    setHighGreenColor('');
};

const lightYellow = () => {
    setHighYellowColor('highYellowColor');
    setHightRedColor('');
    setHighGreenColor('');
}

const lightGreen = () => {
    setHighGreenColor('highGreenColor');
    setHightRedColor('');
    setHighYellowColor('');
}

添加定时器

import logo from './logo.svg';
import './App.css';
import { useState, useEffect } from 'react';

function App() {
  const [highRedColor, setHightRedColor] = useState('');
  const [highYellowColor, setHighYellowColor] = useState('');
  const [highGreenColor, setHighGreenColor] = useState('');

  const lightRed = () => {
    setTimeout(() => {
      setHightRedColor('highRedColor');
      setHighYellowColor('');
      setHighGreenColor('');
      lightYellow();
    }, 1000);
  };

  const lightYellow = () => {
    setTimeout(() => {
      setHighYellowColor('highYellowColor');
      setHightRedColor('');
      setHighGreenColor('');
      lightGreen();
    }, 1000);
  }

  const lightGreen = () => {
    setTimeout(() => {
      setHighGreenColor('highGreenColor');
      setHightRedColor('');
      setHighYellowColor('');
      lightRed();
    }, 1000);
  }

  useEffect(() => {
    lightRed()
  }, [])
  return (
    <div className="App">
      <div id="traffic-light">
        <input type="radio" name="traffic-light-color" id="color1" value="color1" className={ highRedColor ? 'highRedColor' : '' } />
        <input type="radio" name="traffic-light-color" id="color2" value="color2" className={ highYellowColor ? 'highYellowColor' : '' } />
        <input type="radio" name="traffic-light-color" id="color3" value="color3" className={ highGreenColor ? 'highGreenColor' : '' } />
      </div>
    </div>
  );
}

export default App;

高亮类名

.highRedColor {
    background: red;
    background-image: radial-gradient(brown, transparent);
    border: dotted 2px red;
    box-shadow:
      0 0 20px #111 inset,
      0 0 10px red;
}

.highYellowColor {
    background: yellow;
    background-image: radial-gradient(orange, transparent);
    border: dotted 2px yellow;
    box-shadow:
      0 0 20px #111 inset,
      0 0 10px yellow;
}

.highGreenColor {
    background: green;
    background-image: radial-gradient(lime, transparent);
    border: dotted 2px lime;
    box-shadow:
      0 0 20px #111 inset,
      0 0 10px lime;
}

Jan-09-2022 10-59-01.gif

使用Promise

链式调用

const lightRed = () => {
    setHightRedColor('highRedColor');
    setHighYellowColor('');
    setHighGreenColor('');
};

const lightYellow = () => {
    setHighYellowColor('highYellowColor');
    setHightRedColor('');
    setHighGreenColor('');
}


const lightGreen = () => {
    setHighGreenColor('highGreenColor');
    setHightRedColor('');
    setHighYellowColor('');
}

const light = (delay, cb) => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            cb()
            resolve()
        }, delay);
    })
}

const step = () => {
    Promise.resolve().then(() => {
        return light(3000, lightRed)
    }).then(() => {
        return light(2000, lightYellow)
    }).then(() => {
        return light(1000, lightGreen)
    }).then(() => {
        step()
    })
}

useEffect(() => {
    step()
}, [])

async await升级版

const loop = async () => {
    await light(3000, lightRed)
    await light(2000, lightYellow)
    await light(1000, lightGreen)
    loop()
}

useEffect(() => {
    loop()
}, [])