App.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import './App.css';
  2. import { useEffect, useState } from 'react'
  3. const Timer = ({ timeInSeconds }) => {
  4. const [time, setTime] = useState(timeInSeconds)
  5. const [isPaused, setPaused] = useState(false)
  6. const hours = Math.floor(time / (60 * 60))
  7. const minutes = Math.floor((time % (60 * 60)) / 60)
  8. const seconds = Math.ceil((time % (60 * 60)) % 60)
  9. useEffect(() => {
  10. let interval = setInterval(() => {setTime(time => time - 1)}, 1000)
  11. if (time === 0 || isPaused) {
  12. clearInterval(interval)
  13. }
  14. return () => {clearInterval(interval)}
  15. }, [time, isPaused])
  16. useEffect(() => {
  17. setTime(timeInSeconds)
  18. }, [timeInSeconds])
  19. return (
  20. <>
  21. <div>{hours}:{minutes}:{seconds}</div>
  22. <button onClick={() => setPaused(!isPaused)}> астанавись/прадалжай </button>
  23. </>
  24. )
  25. }
  26. const TimerControl = ({setTimeCB}) => {
  27. const [hours, setHours] = useState('')
  28. const [minutes, setMinutes] = useState('')
  29. const [seconds, setSeconds] = useState('')
  30. const timeToSeconds = (hours, minutes, seconds) => {
  31. let time = (+hours * 60 * 60) + (+minutes * 60) + +seconds
  32. return time
  33. }
  34. const valuesDisappear = () => {
  35. setHours('')
  36. setMinutes('')
  37. setSeconds('')
  38. }
  39. return (
  40. <div>
  41. <input type="number" placeholder="hours" value={hours} onChange={(e) => setHours(e.target.value)}></input>
  42. <input type="number" placeholder="minutes" value={minutes} onChange={(e) => setMinutes(e.target.value)}></input>
  43. <input type="number" placeholder="seconds" value={seconds} onChange={(e) => setSeconds(e.target.value)}></input>
  44. <button onClick={() => {valuesDisappear(); setTimeCB(timeToSeconds(hours, minutes, seconds))}}>Start</button>
  45. </div>
  46. )
  47. }
  48. const TimerContainer = ({seconds, refresh, render: Render}) => {
  49. const [time, setTime] = useState(seconds)
  50. const [initialTime] = useState(performance.now())
  51. useEffect(() => {
  52. let interval = setInterval(() => {
  53. setTime(seconds - Math.floor((performance.now() - initialTime) / 1000))
  54. }, refresh)
  55. if (time <= 0) {
  56. setTime(0)
  57. clearInterval(interval)
  58. }
  59. return () => clearInterval(interval)
  60. }, [time, initialTime, refresh, seconds])
  61. useEffect(() => {
  62. setTime(seconds)
  63. }, [seconds])
  64. return (
  65. <Render seconds={time}/>
  66. )
  67. }
  68. const SecondsTimer = ({seconds}) => <h2>{seconds}</h2>
  69. const LCD = ({seconds: timeInSeconds}) => {
  70. const hours = Math.floor(timeInSeconds / (60 * 60))
  71. const minutes = Math.floor((timeInSeconds % (60 * 60)) / 60)
  72. const seconds = Math.ceil((timeInSeconds % (60 * 60)) % 60)
  73. return (
  74. <div>{hours}:{minutes}:{seconds}</div>
  75. )
  76. }
  77. const Watch = ({seconds: timeInSeconds}) => {
  78. const hours = Math.floor(timeInSeconds / (60 * 60))
  79. const minutes = Math.floor((timeInSeconds % (60 * 60)) / 60)
  80. const seconds = Math.ceil((timeInSeconds % (60 * 60)) % 60)
  81. const ratioH = 360 / 12 / 60 / 60
  82. const ratioM = 360 / 60 / 60
  83. const ratioS = 360 / 60
  84. const getAngle = (ratio, value) => (ratio * value)
  85. return (
  86. <>
  87. <div>{hours}:{minutes}:{seconds}</div>
  88. <div style={{position: 'relative'}}>
  89. <img src='http://draw.asmer.fe.a-level.com.ua/ClockFace/ClockFace.png' style={{position: 'absolute'}} />
  90. <img src='http://draw.asmer.fe.a-level.com.ua/ClockFace/ClockFace_H.png' style={{position: 'absolute', transform: `rotate(${getAngle(ratioH, timeInSeconds)}deg)`}}/>
  91. <img src='http://draw.asmer.fe.a-level.com.ua/ClockFace/ClockFace_M.png' style={{position: 'absolute', transform: `rotate(${getAngle(ratioM, timeInSeconds)}deg)`}}/>
  92. <img src='http://draw.asmer.fe.a-level.com.ua/ClockFace/ClockFace_S.png' style={{position: 'absolute', transform: `rotate(${getAngle(ratioS, timeInSeconds)}deg)`}} />
  93. </div>
  94. </>
  95. )
  96. }
  97. function App() {
  98. const [time, setTime] = useState(0)
  99. return (
  100. <div>
  101. <Timer timeInSeconds={time} />
  102. <TimerControl setTimeCB={seconds => setTime(seconds)}/>
  103. <TimerContainer seconds={1800} refresh={100} render={SecondsTimer}/>
  104. <TimerContainer seconds={5000} refresh={100} render={LCD}/>
  105. <TimerContainer seconds={time} refresh={100} render={Watch}/>
  106. </div>
  107. );
  108. }
  109. export default App;