|
@@ -1,10 +1,354 @@
|
|
|
|
|
|
-import './App.css';
|
|
|
-import React, {useState, useRef, useEffect} from 'react';
|
|
|
+import './App.scss';
|
|
|
+import React, {useState, useEffect, useRef} from 'react';
|
|
|
+import ClockFace from '../src/assets/ClockFace.png';
|
|
|
+import ClockFace_M from '../src/assets/ClockFace_M.png';
|
|
|
+import ClockFace_H from '../src/assets/ClockFace_H.png';
|
|
|
+import ClockFace_S from '../src/assets/ClockFace_S.png';
|
|
|
+
|
|
|
+function Timer ({ms = 10, hour = 0, min = 0, sec = 0} ) {
|
|
|
+ const [count, setCount] = useState(ms);
|
|
|
+ const intervalRef = useRef();
|
|
|
+ const intervalRefHour = useRef();
|
|
|
+ const intervalRefMin = useRef();
|
|
|
+ const intervalRefSec = useRef();
|
|
|
+ const [h, setHour] = useState(hour);
|
|
|
+ const [m, setMin] = useState(min);
|
|
|
+ const [s, setSec] = useState(sec);
|
|
|
+ const [stop, setStop] = useState(true);
|
|
|
+ const [start, setStart] = useState(true);
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ intervalRef.current = setInterval(() => {
|
|
|
+ setCount((count) => count - 1)
|
|
|
+ }, 1000);
|
|
|
+
|
|
|
+ return () => clearInterval(intervalRef.current);
|
|
|
+ }
|
|
|
+ , [start])
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ const intervalRefHour = setInterval(() => {
|
|
|
+ setHour( (h) => +h + 1)
|
|
|
+ }, 3600000);
|
|
|
+ return () => clearInterval(intervalRefHour)
|
|
|
+ }
|
|
|
+ , []
|
|
|
+ )
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ const intervalRefMin = setInterval(() => {
|
|
|
+ setMin( (m) => +m + 1)
|
|
|
+ }, 60000);
|
|
|
+ return () => clearInterval(intervalRefMin)
|
|
|
+ }
|
|
|
+ , []
|
|
|
+ )
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ const intervalRefSec = setInterval(() => {
|
|
|
+ setSec( (s) => +s + 1)
|
|
|
+ }, 1000);
|
|
|
+ return () => clearInterval(intervalRefSec)
|
|
|
+ }
|
|
|
+ , []
|
|
|
+ )
|
|
|
+
|
|
|
+ const cancelIntervalButton = () => {
|
|
|
+ if (stop) {
|
|
|
+ clearInterval(intervalRef.current);
|
|
|
+ setStop(!stop);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!stop) {
|
|
|
+ setStart(!start);
|
|
|
+ setStop(!stop);
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (count < 1) {
|
|
|
+ cancelIntervalButton(intervalRef.current);
|
|
|
+ setStop('stop');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (h > 24) {
|
|
|
+ clearInterval(intervalRefHour);
|
|
|
+ setHour(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m > 60) {
|
|
|
+ clearInterval(intervalRefMin);
|
|
|
+ setMin(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s > 60) {
|
|
|
+ clearInterval(intervalRefSec);
|
|
|
+ setSec(0);
|
|
|
+ }
|
|
|
+ }, [count, h, m, s]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <h3>Timer</h3>
|
|
|
+ <p>{h}:{m}:{s}</p>
|
|
|
+ <p>{count}</p>
|
|
|
+ <button onClick = {cancelIntervalButton}>{stop ? 'Stop' : 'Start'}</button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function Timer1 ({seconds = 10, hour = 0, min = 0, sec = 0} ) {
|
|
|
+ const [count, setCount] = useState(seconds);
|
|
|
+ const intervalRef = useRef();
|
|
|
+ const intervalRefHour = useRef();
|
|
|
+ const intervalRefMin = useRef();
|
|
|
+ const intervalRefSec = useRef();
|
|
|
+ const [h, setHour] = useState(hour);
|
|
|
+ const [m, setMin] = useState(min);
|
|
|
+ const [s, setSec] = useState(sec);
|
|
|
+ const [stop, setStop] = useState(true);
|
|
|
+ const [start, setStart] = useState(true);
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ intervalRef.current = setInterval(() => {
|
|
|
+ setCount((count) => count - 1)
|
|
|
+ }, 1000);
|
|
|
+
|
|
|
+ return () => clearInterval(intervalRef.current);
|
|
|
+ }
|
|
|
+ , [start])
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ const intervalRefHour = setInterval(() => {
|
|
|
+ setHour( (h) => +h + 1)
|
|
|
+ }, 3600000);
|
|
|
+ return () => clearInterval(intervalRefHour)
|
|
|
+ }
|
|
|
+ , []
|
|
|
+ )
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ const intervalRefMin = setInterval(() => {
|
|
|
+ setMin( (m) => +m + 1)
|
|
|
+ }, 60000);
|
|
|
+ return () => clearInterval(intervalRefMin)
|
|
|
+ }
|
|
|
+ , []
|
|
|
+ )
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ const intervalRefSec = setInterval(() => {
|
|
|
+ setSec( (s) => +s + 1)
|
|
|
+ }, 1000);
|
|
|
+ return () => clearInterval(intervalRefSec)
|
|
|
+ }
|
|
|
+ , []
|
|
|
+ )
|
|
|
+
|
|
|
+ const cancelIntervalButton = () => {
|
|
|
+ if (stop) {
|
|
|
+ clearInterval(intervalRef.current);
|
|
|
+ setStop(!stop);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!stop) {
|
|
|
+ setStart(!start);
|
|
|
+ setStop(!stop);
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (count < 1) {
|
|
|
+ cancelIntervalButton(intervalRef.current);
|
|
|
+ setStop('stop');
|
|
|
+ }
|
|
|
+
|
|
|
+ if (h > 24) {
|
|
|
+ clearInterval(intervalRefHour);
|
|
|
+ setHour(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m > 60) {
|
|
|
+ clearInterval(intervalRefMin);
|
|
|
+ setMin(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s > 60) {
|
|
|
+ clearInterval(intervalRefSec);
|
|
|
+ setSec(0);
|
|
|
+ }
|
|
|
+ }, [count, h, m, s]);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <p>{h}:{m}:{s}</p>
|
|
|
+ <p>{count}</p>
|
|
|
+ <button onClick = {cancelIntervalButton}>{stop ? 'Stop' : 'Start'}</button>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function TimerControl () {
|
|
|
+ const [h, setHour] = useState(0);
|
|
|
+ const [m, setMin] = useState(0);
|
|
|
+ const [s, setSec] = useState(0);
|
|
|
+ const [open, setOpen] = useState(false);
|
|
|
+
|
|
|
+ const openTimer = () => {
|
|
|
+ setOpen(!open)
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="wrapperTimerControl">
|
|
|
+ <h3>TimerControl</h3>
|
|
|
+ <input type="number" min="0" max="59" onChange = {(e) => setHour(e.target.value)}></input>
|
|
|
+ <input type="number" min="0" max="59" onChange = {(e) => setMin(e.target.value)}></input>
|
|
|
+ <input type="number" min="0" max="59" onChange = {(e) => setSec(e.target.value)}></input>
|
|
|
+ <button onClick = {openTimer} >Start</button>
|
|
|
+ {open && <Timer hour = {h} min = {m} sec = {s}/>}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const SecondsTimer = ({seconds}) => <h2>{seconds}</h2>
|
|
|
+
|
|
|
+function TimerContainer ({seconds, refresh, render:S}) {
|
|
|
+ const [timer, setTimer] = useState(seconds);
|
|
|
+ const idInterval = useRef();
|
|
|
+
|
|
|
+
|
|
|
+ useEffect( () => {
|
|
|
+ const startPerf = performance.now();
|
|
|
+ idInterval.current = setInterval(() => {
|
|
|
+
|
|
|
+ setTimer((timer => {
|
|
|
+ const res = timer - (performance.now() - startPerf);
|
|
|
+ return res < 1 ? 0 : res;
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ , refresh);
|
|
|
+
|
|
|
+ return () => clearInterval(idInterval.current);
|
|
|
+ }, [timer]);
|
|
|
+
|
|
|
+ useEffect(() =>{
|
|
|
+ if (timer < 1) {
|
|
|
+ clearInterval(idInterval.current);
|
|
|
+ }
|
|
|
+ }, [timer]);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return (
|
|
|
+ <S seconds = {timer}/>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function Timer2 ({watch: W} ) {
|
|
|
+ const time = new Date().toLocaleTimeString().split(':');
|
|
|
+ const [h, setH] = useState(+time[0]);
|
|
|
+ const [m, setM] = useState(+time[1]);
|
|
|
+ const [s, setS] = useState(+time[2]);
|
|
|
+
|
|
|
+ useEffect(
|
|
|
+ () => {
|
|
|
+ const intervalWatch = setInterval(() => {
|
|
|
+ const time1 = new Date().toLocaleTimeString().split(':');
|
|
|
+ setH(+time1[0]);
|
|
|
+ setM(+time1[1]);
|
|
|
+ setS(+time1[2]);
|
|
|
+ }, 1000);
|
|
|
+ return () => clearInterval(intervalWatch.current)
|
|
|
+ }
|
|
|
+ , []
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ return (
|
|
|
+ <W degH = {30*h} degM = {6*m} degS = {6*s}/>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function Watch({ degH, degM, degS }) {
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ <img src = {ClockFace} alt = "Clock" style = {{position: 'absolute'}}></img>
|
|
|
+ <img src = {ClockFace_H} alt = "Clock"
|
|
|
+ style = {
|
|
|
+ {
|
|
|
+ position: "absolute",
|
|
|
+ transform: `rotate(${degH}deg)`,
|
|
|
+ }
|
|
|
+ }></img>
|
|
|
+ <img src = {ClockFace_M} alt = "Clock"
|
|
|
+ style = {
|
|
|
+ {
|
|
|
+ position: 'absolute',
|
|
|
+ transform: `rotate(${degM}deg)`,
|
|
|
+ }
|
|
|
+ }></img>
|
|
|
+ <img src = {ClockFace_S} alt = "Clock"
|
|
|
+ style = {
|
|
|
+ {
|
|
|
+ position: 'absolute',
|
|
|
+ transform: `rotate(${degS}deg)`,
|
|
|
+ }
|
|
|
+ }></img>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+function TimerControl1 () {
|
|
|
+ const [h, setHour] = useState(0);
|
|
|
+ const [m, setMin] = useState(0);
|
|
|
+ const [s, setSec] = useState(0);
|
|
|
+ const [open, setOpen] = useState(false);
|
|
|
+ const openTimer = () => {
|
|
|
+ setOpen(!open)
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="wrapperTimerControl">
|
|
|
+ <input type="number" min="0" max="59" onChange = {(e) => setHour(e.target.value)}></input>
|
|
|
+ <input type="number" min="0" max="59" onChange = {(e) => setMin(e.target.value)}></input>
|
|
|
+ <input type="number" min="0" max="59" onChange = {(e) => setSec(e.target.value)}></input>
|
|
|
+ <button onClick = {openTimer} >{open ? 'Reset' : 'Start'}</button>
|
|
|
+ {open && <TimerContainer seconds = {(h*60*60 + m*60 + s) * 1000} refresh = {1000} render={SecondsTimer}/> }
|
|
|
+ </div>
|
|
|
+
|
|
|
+ )
|
|
|
+}
|
|
|
|
|
|
function App() {
|
|
|
return (
|
|
|
<div className="App">
|
|
|
+ <TimerControl/>
|
|
|
+ <h3>TimerContainer </h3>
|
|
|
+ <TimerContainer seconds={18000} refresh={1000} render={SecondsTimer}/>
|
|
|
+ <h3>LCD</h3>
|
|
|
+ <TimerContainer seconds={18000} refresh={1000} render={Timer1}/>
|
|
|
+ <h3>Watch</h3>
|
|
|
+ <Timer2 watch={Watch}/>
|
|
|
+ <h3 style = {{marginTop: "450px"}}>TimerControl + TimerContainer</h3>
|
|
|
+ <TimerControl1/>
|
|
|
+
|
|
|
|
|
|
</div>
|
|
|
);
|