Skip to content

Instantly share code, notes, and snippets.

@flowsn4ke
Last active February 19, 2022 00:17
Show Gist options
  • Save flowsn4ke/d4bc2e2bd932e326ba3d0b866afde479 to your computer and use it in GitHub Desktop.
Save flowsn4ke/d4bc2e2bd932e326ba3d0b866afde479 to your computer and use it in GitHub Desktop.
import { useEffect, useRef } from "react"
const x_offset = 50
const y_offset = 50
const initial_x_axis_value = 50
const initial_y_axis_seconds_value = 5
const initial_y_axis_minutes_value = 15
const initial_y_axis_hours_value = 25
const seconds_in_minutes = 60
const minutes_in_hour = 60
const hours_scale = 12
const hours_marks_y_axis_start = 2
const hours_marks_y_axis_end = 5
const degrees_in_circle = 360
const degrees_per_seconds = degrees_in_circle / seconds_in_minutes
const degrees_per_minute = degrees_in_circle / minutes_in_hour
const degrees_per_hour = degrees_in_circle / hours_scale
const degrees_per_minute_per_hour = degrees_per_hour / minutes_in_hour
const initial_x_minus_offset = initial_x_axis_value - x_offset
const initial_y_minus_offset_seconds = initial_y_axis_seconds_value - y_offset
const initial_y_minus_offset_minutes = initial_y_axis_minutes_value - y_offset
const initial_y_minus_offset_hours = initial_y_axis_hours_value - y_offset
const hours_marks_y_start_offset = hours_marks_y_axis_start - y_offset
const hours_marks_y_end_offset = hours_marks_y_axis_end - y_offset
function getTime(time = new Date()) {
let hours, minutes, seconds;
hours = time.getHours();
minutes = time.getMinutes();
seconds = time.getSeconds();
return { hours, minutes, seconds };
}
function degreesToRadians(deg) {
return (deg * Math.PI) / 180
}
function getHandsPositions() {
const { hours, minutes, seconds } = getTime()
const seconds_theta = degreesToRadians(degrees_per_seconds * seconds)
const minutes_theta = degreesToRadians(degrees_per_minute * minutes)
const hours_theta = degreesToRadians(degrees_per_hour * hours + degrees_per_minute_per_hour * minutes)
const seconds_x1 = initial_x_minus_offset * Math.cos(seconds_theta) - initial_y_minus_offset_seconds * Math.sin(seconds_theta) + x_offset
const seconds_y1 = initial_x_minus_offset * Math.sin(seconds_theta) + initial_y_minus_offset_seconds * Math.cos(seconds_theta) + y_offset
const minutes_x1 = initial_x_minus_offset * Math.cos(minutes_theta) - initial_y_minus_offset_minutes * Math.sin(minutes_theta) + x_offset
const minutes_y1 = initial_x_minus_offset * Math.sin(minutes_theta) + initial_y_minus_offset_minutes * Math.cos(minutes_theta) + y_offset
const hours_x1 = initial_x_minus_offset * Math.cos(hours_theta) - initial_y_minus_offset_hours * Math.sin(hours_theta) + x_offset
const hours_y1 = initial_x_minus_offset * Math.sin(hours_theta) + initial_y_minus_offset_hours * Math.cos(hours_theta) + y_offset
return { seconds_x1, seconds_y1, minutes_x1, minutes_y1, hours_x1, hours_y1 }
}
export default function AnalogClock() {
const secondsRef = useRef()
const minutesRef = useRef()
const hoursRef = useRef()
const { seconds_x1, seconds_y1, minutes_x1, minutes_y1, hours_x1, hours_y1 } = getHandsPositions()
useEffect(() => {
const interval = setInterval(() => {
const { seconds_x1, seconds_y1, minutes_x1, minutes_y1, hours_x1, hours_y1 } = getHandsPositions()
secondsRef.current.setAttributeNS(null, "x1", seconds_x1)
secondsRef.current.setAttributeNS(null, "y1", seconds_y1)
minutesRef.current.setAttributeNS(null, "x1", minutes_x1)
minutesRef.current.setAttributeNS(null, "y1", minutes_y1)
hoursRef.current.setAttributeNS(null, "x1", hours_x1)
hoursRef.current.setAttributeNS(null, "y1", hours_y1)
}, 1000);
return () => clearInterval(interval);
}, [])
return <svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50" fill="#fb0" />
<g stroke="#000">
{new Array(hours_scale)
.fill(null)
.map((_, i) => {
const theta = degreesToRadians(i * degrees_per_hour)
const t_cos = Math.cos(theta)
const t_sin = Math.sin(theta)
const x1 = initial_x_minus_offset * t_cos - hours_marks_y_start_offset * t_sin + x_offset
const y1 = initial_x_minus_offset * t_sin - hours_marks_y_start_offset * t_cos + y_offset
const x2 = initial_x_minus_offset * t_cos - hours_marks_y_end_offset * t_sin + x_offset
const y2 = initial_x_minus_offset * t_sin - hours_marks_y_end_offset * t_cos + y_offset
return <line
key={`hour-marker-${i}`}
strokeWidth=".5"
x1={x1}
y1={y1}
x2={x2}
y2={y2}
/>
})}
</g>
<g stroke="#000">
<line
ref={hoursRef}
x1={hours_x1}
y1={hours_y1}
x2={x_offset}
y2={y_offset}
strokeWidth="1"
/>
<line
ref={minutesRef}
x1={minutes_x1}
y1={minutes_y1}
x2={x_offset}
y2={y_offset}
strokeWidth=".5"
/>
<line
ref={secondsRef}
x1={seconds_x1}
y1={seconds_y1}
x2={x_offset}
y2={y_offset}
strokeWidth=".1"
/>
</g>
<circle cx={x_offset} cy={y_offset} r="1" fill="#000" />
</svg>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment