React Hooks --- 番茄计时器🍅

648 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情

使用番茄工作法,选择一个待完成的任务,将番茄时间设为25分钟,专注工作,中途不允许做任何与该任务无关的事,直到番茄时钟响起,然后进行短暂休息一下(5分钟就行),然后再开始下一个番茄。每4个番茄时段多休息一会儿。番茄工作法极大地提高了工作的效率,还会有意想不到的成就感。

图片.png

图片.png

页面结构也是非常简单。

显示时间 + 两个按钮

<div className="Pomodoro" ref={rootRef}>
  <div className="timer">
    {displayTimer(time)}
  </div>
  <div className="types">
    <button
      className="long"
      onClick={setTimeForLongBreak}
    >
      工作
    </button>
    <button
      className="short"
      onClick={setTimeForShortBreak}
    >
      休息
    </button>
  </div>
</div>

css

.Pomodoro {
  padding: 50px;
}

.Pomodoro .timer {
  font-size: 100px;
  font-weight: bold;
  color: #fff;
}

.Pomodoro button {
  background: #2ba6cb;
  border: none;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) inset;
  color: white;
  cursor: pointer;
  display: inline-block;
  font-size: 14px;
  font-weight: bold;
  line-height: 1;
  margin: 50px 10px 0px 10px;
  padding: 10px 20px 11px;
  position: relative;
  text-align: center;
  text-decoration: none;
}

思路也很简单

使用 useState 来记录当前的时间

const [time, setTime] = useState(0);

useRef 记录计数器

const timeRef = useRef(null);

使用 useEffect 来进行倒计时

useEffect(() => {
  if (time && time !== 0) {
    timeRef.current = setTimeout(() => {
      setTime(time => time - 1)
    }, 1000);
  }
  return () => {
    clearTimeout(timeRef.current)
  }
}, [time])

当用户点击按钮时,为 time 赋值。

const setTimeForShortBreak = () => {
  setNewTime(times.shortBreak)
}

const setTimeForLongBreak = () => {
  setNewTime(times.longBreak)
}

是不是超级简单。对的,就是这么简单。

同时,调用 requestFullscreen() 方法,实现全屏。

function Timer() {
  const [isFullScreen, setIsFullScreen] = useState(false);
  const rootRef = useRef(null);

  useEffect(() => {
    window.onresize = () => {
      if (document.fullscreenElement) {
        setIsFullScreen(true)
      } else {
        setIsFullScreen(false)
      }
    }
  }, [])

  const fullScreen = () => {
    if (!isFullScreen) {
      rootRef.current.requestFullscreen()
    }
  }

  const setTimeForShortBreak = () => {
    fullScreen();
    //...
  }

  const setTimeForLongBreak = () => {
    fullScreen();
    //...
  }

  return (
    <div className="Pomodoro" ref={rootRef}>
      // ...
    </div>
  );
}

export default Timer;

按钮似乎有那么一点点丑,不要紧。

.Pomodoro button.short,
.Pomodoro button.long {
  font-size: 14px;
  background: linear-gradient(90deg, #03a9f4, #f441a5, #ffeb3b, #03a9f4);
  background-size: 400%;
  width: 175px;
  height: 45px;
  color: #fff;
  line-height: 25px;
  text-align: center;
  text-transform: uppercase;
  border-radius: 50px;
  z-index: 1;
}

图片.png

.Pomodoro button.short::before,
.Pomodoro button.long::before {
  content: "";
  position: absolute;
  left: -5px;
  right: -5px;
  top: -5px;
  bottom: -5px;
  background: linear-gradient(90deg, #03a9f4, #f441a5, #ffeb3b, #03a9f4);
  background-size: 400%;
  border-radius: 50px;
  filter: blur(20px);
  z-index: -1;
}

图片.png

.Pomodoro button.short:hover::before,
.Pomodoro button.long:hover::before {
  animation: sun 8s infinite;
}

.Pomodoro button.short:hover,
.Pomodoro button.long:hover {
  animation: sun 8s infinite;
}

@keyframes sun {
  100% {
    background-position: -400% 0;
  }
}

Jun-24-2022 10-56-40.gif