Skip to content

Commit 1f1d6f0

Browse files
committed
Refactor: Clock refactoring
1 parent cb0a145 commit 1f1d6f0

File tree

5 files changed

+125
-89
lines changed

5 files changed

+125
-89
lines changed

components/Clock/Clock.style.ts renamed to components/Clock/Clock.styled.ts

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { keyframes } from "@emotion/react";
22
import styled from "@emotion/styled";
3-
import { IGraduationStyleProps } from "./Clock.type";
4-
import { getRotatedPosition } from "./Clock.util";
53

64
const ClockFadeKeyframe = keyframes`
75
from {
@@ -88,46 +86,3 @@ export const ClockHandler = styled.div`
8886
transform: translate3d(-50%, 10%, 0);
8987
}
9088
`;
91-
92-
export const Graduation = styled.div<IGraduationStyleProps>`
93-
width: ${(props) => (props.accent ? 3 : 2)}px;
94-
height: ${(props) => (props.accent ? 20 : 14)}px;
95-
96-
position: absolute;
97-
transform-origin: center center;
98-
transform: translate3d(
99-
${(props) => {
100-
const { x, y } = getRotatedPosition(200, props.rotate);
101-
return `calc(-50% + ${x}px), calc(-50% + ${y}px), 0`;
102-
}}
103-
)
104-
rotate3d(0, 0, 1, ${(props) => -props.rotate}deg);
105-
background-color: ${(props) => (props.accent ? "white" : "grey")};
106-
107-
& > span {
108-
font-weight: 500;
109-
font-size: 22px;
110-
color: ${(props) => (props.spanAccent ? "white" : "#525252")};
111-
112-
position: absolute;
113-
left: 50%;
114-
bottom: 100%;
115-
transform-origin: center center;
116-
transform: translate3d(-50%, ${(props) => -props.gap}px, 0)
117-
rotate3d(0, 0, 1, ${(props) => props.rotate}deg)
118-
scale(${(props) => (props.spanAccent ? "1" : "0.85")});
119-
120-
transition: color 0.2s cubic-bezier(0.2, 0, 0, 1),
121-
transform 0.2s cubic-bezier(0.2, 0, 0, 1);
122-
123-
@media screen and (max-width: 600px) {
124-
font-size: 26px;
125-
}
126-
127-
.min {
128-
color: ${(props) => (props.spanAccent ? "#e0e0e0" : "#424242")};
129-
margin-left: 0.2em;
130-
font-size: 0.6em;
131-
}
132-
}
133-
`;

components/Clock/Clock.tsx

Lines changed: 28 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
import React, { useEffect, useRef, useState, PointerEvent } from "react";
1+
import React, {
2+
useEffect,
3+
useRef,
4+
useState,
5+
PointerEvent,
6+
useMemo,
7+
} from "react";
28
import {
39
ClockBackground,
410
ClockCenter,
511
ClockHandler,
612
Container,
7-
Graduation,
813
MainClock,
9-
} from "./Clock.style";
14+
} from "./Clock.styled";
1015
import {
1116
getPointerPosFromCenter,
1217
getRotationDegree,
@@ -29,6 +34,7 @@ import {
2934
clockTimeUnitAtom as CTU,
3035
isIntroTimeoutedAtom as IIT,
3136
} from "../../shared/atom";
37+
import Graduation from "./Graduation/Graduation";
3238

3339
let canSetClockDegree = false;
3440
let isOverLimited = false;
@@ -38,17 +44,17 @@ export default function Clock() {
3844
const backgroundRef = useRef<HTMLDivElement>(null);
3945
const handlerRef = useRef<HTMLDivElement>(null);
4046
const resizeRef = useRef<HTMLDivElement>(null);
41-
const [moveAreaPos, setMoveAreaPos] = useState<Vector2>(new Vector2(0, 0));
42-
const [centerPos, setCenterPos] = useState<Vector2>(new Vector2(0, 0));
43-
const [prevRelPos, setPrevRelPos] = useState<Vector2 | null>(null);
4447
const isTimingNow = useRecoilValue(ITN);
45-
const [isClockPointerDown, setIsClockPointerDown] = useRecoilState(ICPD);
46-
const setClockSize = useSetRecoilState(CS);
47-
const [clockDegree, setClockDegree] = useRecoilState(CD);
4848
const clockColor = useRecoilValue(CCV);
4949
const maxClockTime = useRecoilValue(MCT);
5050
const clockTimeUnit = useRecoilValue(CTU);
5151
const isIntroTimeouted = useRecoilValue(IIT);
52+
const setClockSize = useSetRecoilState(CS);
53+
const [moveAreaPos, setMoveAreaPos] = useState<Vector2>(new Vector2(0, 0));
54+
const [centerPos, setCenterPos] = useState<Vector2>(new Vector2(0, 0));
55+
const [prevRelPos, setPrevRelPos] = useState<Vector2 | null>(null);
56+
const [clockDegree, setClockDegree] = useRecoilState(CD);
57+
const [isClockPointerDown, setIsClockPointerDown] = useRecoilState(ICPD);
5258

5359
const onPointerDown = (e: PointerEvent) => {
5460
canSetClockDegree = true;
@@ -96,29 +102,16 @@ export default function Clock() {
96102
setIsClockPointerDown(false);
97103
};
98104

99-
const parseIndexToGraduationValue = (index: number) => {
100-
const gValue = Math.round((index * maxClockTime) / 6) / 10;
101-
102-
// If gValue is float
103-
if (gValue !== Math.floor(gValue)) {
104-
const float = gValue - Math.floor(gValue);
105-
return (
106-
<span>
107-
{Math.floor(gValue)}
108-
<span className="min">/{60 * float}</span>
109-
</span>
110-
);
111-
}
112-
113-
return <span>{gValue}</span>;
114-
};
115-
116105
const rebaseDegree = () => {
117106
setClockDegree(rebaseClockDegree(clockDegree, maxClockTime));
118107
};
119108

120109
const isIntroedOnce = () => isIntroTimeouted;
121110

111+
const Graduations = useMemo(() => {
112+
return range(60).map((i) => <Graduation key={i} index={i} />);
113+
}, []);
114+
122115
useEffect(() => {
123116
if (isClockPointerDown) return;
124117
rebaseDegree();
@@ -165,11 +158,16 @@ export default function Clock() {
165158
const onResize = () => {
166159
const stageWidth = document.body.clientWidth;
167160
const stageHeight = document.body.clientHeight;
161+
const HORIZONTAL_PADDING_SIZE = 190;
162+
const CLOCK_SIZE = 600;
168163

169-
const resizedWidth = Math.min(600, stageWidth);
170-
const resizedHeight = Math.min(600 + 190, stageHeight - 190);
164+
const resizedWidth = Math.min(CLOCK_SIZE, stageWidth);
165+
const resizedHeight = Math.min(
166+
CLOCK_SIZE + HORIZONTAL_PADDING_SIZE,
167+
stageHeight - HORIZONTAL_PADDING_SIZE
168+
);
171169
const resultSize = Math.min(resizedWidth, resizedHeight);
172-
const resultScaleRatio = Math.min(1, resultSize / 600);
170+
const resultScaleRatio = Math.min(1, resultSize / CLOCK_SIZE);
173171

174172
resizeRef.current!.style.transform = `
175173
scale(${resultScaleRatio})
@@ -203,21 +201,7 @@ export default function Clock() {
203201
onPointerMove={onPointerMove}
204202
>
205203
<ClockCenter>
206-
{range(60).map((i) => (
207-
<Graduation
208-
rotate={i * 6}
209-
accent={i % 5 == 0}
210-
gap={24}
211-
key={i}
212-
spanAccent={360 - clockDegree >= i * 6}
213-
>
214-
{i %
215-
(maxClockTime >= 60 ? 5 : 5 * Math.round(30 / maxClockTime)) ==
216-
0
217-
? parseIndexToGraduationValue(i)
218-
: null}
219-
</Graduation>
220-
))}
204+
{Graduations}
221205
<ClockBackground ref={backgroundRef} />
222206
<ClockHandler ref={handlerRef}>
223207
<div className="pointer"></div>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import styled from "@emotion/styled";
2+
import { IGraduationStyleProps } from "../Clock.type";
3+
import { getRotatedPosition } from "../Clock.util";
4+
5+
export const GraduationContainer = styled.div<IGraduationStyleProps>`
6+
width: ${(props) => (props.accent ? 3 : 2)}px;
7+
height: ${(props) => (props.accent ? 20 : 14)}px;
8+
9+
position: absolute;
10+
transform-origin: center center;
11+
transform: translate3d(
12+
${(props) => {
13+
const { x, y } = getRotatedPosition(200, props.rotate);
14+
return `calc(-50% + ${x}px), calc(-50% + ${y}px), 0`;
15+
}}
16+
)
17+
rotate3d(0, 0, 1, ${(props) => -props.rotate}deg);
18+
background-color: ${(props) => (props.accent ? "white" : "grey")};
19+
20+
& > span {
21+
font-weight: 500;
22+
font-size: 22px;
23+
color: ${(props) => (props.spanAccent ? "white" : "#525252")};
24+
25+
position: absolute;
26+
left: 50%;
27+
bottom: 100%;
28+
transform-origin: center center;
29+
transform: translate3d(-50%, ${(props) => -props.gap}px, 0)
30+
rotate3d(0, 0, 1, ${(props) => props.rotate}deg)
31+
scale(${(props) => (props.spanAccent ? "1" : "0.85")});
32+
33+
transition: color 0.2s cubic-bezier(0.2, 0, 0, 1),
34+
transform 0.2s cubic-bezier(0.2, 0, 0, 1);
35+
36+
@media screen and (max-width: 600px) {
37+
font-size: 26px;
38+
}
39+
40+
.min {
41+
color: ${(props) => (props.spanAccent ? "#e0e0e0" : "#424242")};
42+
margin-left: 0.2em;
43+
font-size: 0.6em;
44+
}
45+
}
46+
`;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useRecoilValue } from "recoil";
2+
import { IGraduationProps } from "../Clock.type";
3+
import {
4+
clockDegreeAtom as CD,
5+
maxClockTimeAtom as MCT,
6+
} from "../../../shared/atom";
7+
import { GraduationContainer } from "./Graduation.styled";
8+
9+
export default function Graduation({ index }: IGraduationProps) {
10+
const INDEX_GAP = 5;
11+
const ROTATED_DEGREE = index * 6;
12+
const clockDegree = useRecoilValue(CD);
13+
const maxClockTime = useRecoilValue(MCT);
14+
15+
const isDisplayGraduation = () => {
16+
const gapRatio = maxClockTime >= 60 ? 1 : Math.round(30 / maxClockTime);
17+
return index % (gapRatio * INDEX_GAP) == 0;
18+
};
19+
20+
const getGraduationContent = () => {
21+
const gValue = Math.round((index * maxClockTime) / 6) / 10;
22+
23+
// If gValue is float
24+
if (gValue !== Math.floor(gValue)) {
25+
const float = gValue - Math.floor(gValue);
26+
return (
27+
<span>
28+
{Math.floor(gValue)}
29+
<span className="min">/{60 * float}</span>
30+
</span>
31+
);
32+
}
33+
34+
return <span>{gValue}</span>;
35+
};
36+
37+
return (
38+
<GraduationContainer
39+
rotate={ROTATED_DEGREE}
40+
accent={index % INDEX_GAP == 0}
41+
gap={24}
42+
spanAccent={360 - clockDegree >= ROTATED_DEGREE}
43+
>
44+
{isDisplayGraduation() ? getGraduationContent() : null}
45+
</GraduationContainer>
46+
);
47+
}

components/Clock/Clock.type.ts renamed to components/Clock/Graduation/Graduation.type.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ export interface IGraduationStyleProps {
44
accent: boolean;
55
spanAccent: boolean;
66
}
7+
8+
export interface IGraduationProps {
9+
index: number;
10+
}

0 commit comments

Comments
 (0)