四年前在码云fork过一个全屏时钟仓库,是大圣老师用来配合早起学习用的,而我简单修改后就放到那儿啦。
倒是近两年开始跟着直播跳操,开始把这个全屏时钟用起来了,习惯性地放在分屏看下时间。很不幸的是,最近Gitee Pages
打不开了。打开Time.is
用了几天,发现还是更习惯之前的时钟模式。
因此,就在这次Astro
版本的博客网站中,使用devv.ai
的react传授术,重构了一个全屏时钟。
第一个版本,完全就是主打能用就行,UI是完全没带管的。
简要内核
时间的刷新展示
作为一个时钟,最最关键的就是:获取当前时间,然后不断刷新时间的展示。
初始版本使用了setInterval()
计时器实现,在这个版本决定改用requestAnimationFrame()
来执行时间的获取和刷新任务。
import React, { useEffect, useRef, useState } from 'react'
function Clock() {
const [currentTime, setCurrentTime] = useState(new Date())
const updateClock = () => {
setCurrentTime(new Date())
requestRef.current = requestAnimationFrame(updateClock)
}
useEffect(() => {
requestRef.current = requestAnimationFrame(updateClock)
return () => cancelAnimationFrame(requestRef.current)
}, [])
}
全屏与退出全屏
重构这个时间展示工具就是为了在使用中减少纷杂因素的干扰,所以全屏必不可少。
初始版本使用的document
的原始API,通过使用document.documentElement.requestFullscreen()
和document.fullscreenElement
兼容性方案来实现全屏状态的切换,在这个版本用了react-full-screen
依赖库来简化DOM的兼容使用,只需要在点击时判断当前全屏状态并给予切换。
import { FullScreen, useFullScreenHandle } from 'react-full-screen'
const handle = useFullScreenHandle()
const handleBodyClick = () => {
if (handle.active) {
handle.exit()
}
else {
handle.enter()
}
}
return (
<>
<FullScreen handle={handle}>
{/* <!----> */}
</FullScreen>
</>
)
拓展业务
Time.is
还是很强大的,虽然目前好多功能个人是用不到的,但是总会想有亿点点定制,不然也不会自己吭哧瘪肚地复制粘贴代码搞自己的站。为了不让自己想定制的时候还需要去改代码,就需要拓展出来定制的功能。
比如根据语言显示日期/定制不一样的数字显示字体/定制主题配色。
语言切换
const locales = [
{ code: 'en-US', label: 'English (US)' },
{ code: 'zh-CN', label: '中文 (中国)' },
{ code: 'fr-FR', label: 'Français (France)' },
{ code: 'de-DE', label: 'Deutsch (Deutschland)' },
{ code: 'ja-JP', label: '日本語 (日本)' },
]
const [locale, setLocale] = useState(locales[0].code)
const hour = currentTime.getHours().toString().padStart(2, '0')
const minute = currentTime.getMinutes().toString().padStart(2, '0')
const second = currentTime.getSeconds().toString().padStart(2, '0')
const year = currentTime.getFullYear()
const formattedDate = currentTime.toLocaleDateString(locale, {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
})
const handleLocaleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
setLocale(event.target.value)
}
定制字体
const fontSchemes = [
{ id: 'default', label: '默认', fontFamily: '', fontWeight: 600 },
{ id: 'timeis', label: 'Time.is', fontFamily: 'TimeTravelerPal', fontWeight: 400 },
]
const [fontScheme, setFontScheme] = useState(fontSchemes[0])
const handleFontChange = (index: number) => {
setFontScheme(fontSchemes[index])
}
定制主题
const colorSchemes = [
{ background: '#1f1c19', color: '#caccdf' }, // 默认配色
{ background: '#282c34', color: '#61dafb' }, // 深色配色
{ background: '#ffffff', color: '#000000' }, // 浅色配色
{ background: '#ff6347', color: '#ffffff' }, // 番茄配色
{ background: '#4caf50', color: '#ffffff' }, // 绿色配色
]
const [colorScheme, setColorScheme] = useState(colorSchemes[0])
const handleColorChange = (index: number) => {
setColorScheme(colorSchemes[index])
}