Skip to content

Commit edd1de4

Browse files
committed
added a smooth clock - first attempt
1 parent 8bdcccc commit edd1de4

File tree

3 files changed

+450
-43
lines changed

3 files changed

+450
-43
lines changed
Lines changed: 200 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,206 @@
1-
<!DOCTYPE HTML>
2-
<!--
3-
COPYRIGHT 2009, 2010, 2011, 2012, 2013, 2014 by the Open Rails project.
4-
5-
This file is part of Open Rails.
6-
7-
Open Rails is free software: you can redistribute it and/or modify
8-
it under the terms of the GNU General Public License as published by
9-
the Free Software Foundation, either version 3 of the License, or
10-
(at your option) any later version.
11-
12-
Open Rails is distributed in the hope that it will be useful,
13-
but WITHOUT ANY WARRANTY; without even the implied warranty of
14-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15-
GNU General Public License for more details.
16-
17-
You should have received a copy of the GNU General Public License
18-
along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
19-
-->
1+
<!DOCTYPE html>
2+
<!-- https://www.cssscript.com/analog-clock-scss/ -->
203
<html>
214
<head>
22-
<title>OPEN RAILS - Sample API</title>
235
<meta charset="utf-8" />
24-
<meta name="viewport" content="width=device-width, initial-scale=1"><!-- adds zooming for mobiles -->
25-
<link rel="shortcut icon" type="image/png" href="/or_logo.png"><!-- This icon appears in the page's tab and its bookmark. -->
26-
<link rel="stylesheet" type="text/css" href="/index.css"><!-- share styles with home page -->
27-
<link href="index.css" rel="stylesheet" type="text/css">
28-
<script src="index.js"></script>
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<title>Smooth Clock</title>
8+
<meta name="viewport" content="width=device-width, initial-scale=1">
9+
<style>
10+
html {
11+
box-sizing: border-box;
12+
}
13+
*, *:before, *:after {
14+
box-sizing: inherit;
15+
}
16+
.clock {
17+
background-color: #f9f9f9;
18+
border-radius: 50%;
19+
width: 100%;
20+
height: 100%;
21+
display: flex;
22+
position: relative;
23+
box-shadow: inset 0 0 20px gray;
24+
border: 10px solid black;
25+
}
26+
.clock__dial-hour {
27+
color: #4d4d4d;
28+
text-shadow: 1px 1px 4px;
29+
position: absolute;
30+
}
31+
.clock__dial-hour--main {
32+
color: black;
33+
font-size: 1.6em;
34+
font-weight: 500;
35+
}
36+
.clock__hand-pivot {
37+
box-shadow: 0 0 2px 2px red;
38+
border: 5px solid white;
39+
border-radius: 50%;
40+
height: 0px;
41+
width: 0px;
42+
position: absolute;
43+
}
44+
.clock__hours-hand {
45+
box-shadow: 1px 1px 1px 1px gray;
46+
border-radius: 40% 40% 20% 20%;
47+
position: absolute;
48+
border: 2px solid black;
49+
background-color: white;
50+
width: 8px;
51+
}
52+
.clock__minutes-hand {
53+
box-shadow: 1px 1px 1px 1px gray;
54+
position: absolute;
55+
border-radius: 40% 40% 20% 20%;
56+
background-color: white;
57+
border: 1px solid black;
58+
width: 4px;
59+
}
60+
.clock__seconds-hand {
61+
box-shadow: 1px 1px 1px 0px red;
62+
position: absolute;
63+
border-radius: 30%;
64+
background-color: red;
65+
width: 1px;
66+
}
67+
#container {
68+
padding: 10px;
69+
height: 500px;
70+
font-size: 30px;
71+
width: 500px;
72+
margin: auto;
73+
}
74+
</style>
2975
</head>
30-
31-
<body onload="setInterval (ApiTime, 500)">
32-
<div id=menu><a href="/">Back to Menu</a></div>
33-
<br>
34-
<h2>Open Rails Web Server - Simulation Time</h2>
35-
<h3>Seconds since midnight</h3>
36-
<div id="time"></div>
37-
<table>
38-
<tr>
39-
<td id="hours"></td><td>:</td>
40-
<td id="minutes"></td><td>:</td>
41-
<td id="seconds"></td><td>.</td>
42-
<td id="centiseconds"></td>
43-
</tr>
44-
</table>
76+
<body>
77+
<div id="container">
78+
<div class="clock">
79+
<div class="clock__hours-hand" id="hours-hand"></div>
80+
<div class="clock__minutes-hand" id="minutes-hand"></div>
81+
<div class="clock__seconds-hand" id="seconds-hand"></div>
82+
<span class="clock__hand-pivot" id="hand-pivot"></span>
83+
<span class="clock__dial-hour">1</span>
84+
<span class="clock__dial-hour">2</span>
85+
<span class="clock__dial-hour clock__dial-hour--main">3</span>
86+
<span class="clock__dial-hour">4</span>
87+
<span class="clock__dial-hour">5</span>
88+
<span class="clock__dial-hour clock__dial-hour--main">6</span>
89+
<span class="clock__dial-hour">7</span>
90+
<span class="clock__dial-hour">8</span>
91+
<span class="clock__dial-hour clock__dial-hour--main">9</span>
92+
<span class="clock__dial-hour">10</span>
93+
<span class="clock__dial-hour">11</span>
94+
<span class="clock__dial-hour clock__dial-hour--main">12</span>
95+
</div>
96+
</div>
4597
</body>
98+
<script>
99+
const getDims = (elm, removeBorder = true, removePadding = true) => {
100+
const elmStyles = window.getComputedStyle(elm)
101+
return {
102+
height: elm.offsetHeight +
103+
(removeBorder ? -parseInt(elmStyles.borderTopWidth, 10) - parseInt(elmStyles.borderBottomWidth, 10) : 0) +
104+
(removePadding ? -parseInt(elmStyles.paddingTop, 10) - parseInt(elmStyles.paddingBottom, 10) : 0),
105+
width: elm.offsetWidth +
106+
(removeBorder ? -parseInt(elmStyles.borderLeftWidth, 10) - parseInt(elmStyles.borderRightWidth, 10) : 0) +
107+
(removePadding ? -parseInt(elmStyles.paddingLeft, 10) - parseInt(elmStyles.paddingRight, 10) : 0)
108+
}
109+
}
110+
111+
const clockwiseRotate = (center, angle, point) => {
112+
const movex = point.x - center.x
113+
const movey = point.y - center.y
114+
115+
const s = Math.sin(angle * Math.PI / 180)
116+
const c = Math.cos(angle * Math.PI / 180)
117+
118+
const x = movex * c - movey * s
119+
const y = movex * s + movey * c
120+
121+
return {
122+
x: x + center.x,
123+
y: y + center.y
124+
}
125+
}
126+
127+
const clock = document.getElementsByClassName('clock')[0]
128+
const {height: boxH, width: boxW} = getDims(clock, false, false)
129+
const minv = Math.min(boxH, boxW)
130+
clock.style.height = clock.style.width = minv
131+
132+
const {height, width} = getDims(clock)
133+
let dialHours = document.getElementsByClassName('clock__dial-hour')
134+
let offsetFix = dialHours[11].offsetHeight / 10
135+
let refx = 0
136+
let refy = -height / 2 + dialHours[11].offsetHeight / 2
137+
const origin = {x: 0, y: 0}
138+
139+
for (let i = 1; i <= 12; ++i) {
140+
let newc = clockwiseRotate(origin, 30, {x: refx, y: refy})
141+
refx = Math.round(newc.x)
142+
refy = Math.round(newc.y)
143+
newc.x = Math.round(newc.x - dialHours[i - 1].offsetWidth / 2 + width / 2)
144+
newc.y = Math.round(newc.y - dialHours[i - 1].offsetHeight / 2 + height / 2 + offsetFix)
145+
dialHours[i - 1].style.top = newc.y + 'px'
146+
dialHours[i - 1].style.left = newc.x + 'px'
147+
}
148+
149+
const handPivot = document.getElementById('hand-pivot')
150+
const pivotBoxDims = getDims(handPivot, false, false)
151+
handPivot.style.top = height / 2 - pivotBoxDims.height / 2 + 'px'
152+
handPivot.style.left = width / 2 - pivotBoxDims.width / 2 + 'px'
153+
154+
const hoursHand = document.getElementById('hours-hand')
155+
const minutesHand = document.getElementById('minutes-hand')
156+
const secondsHand = document.getElementById('seconds-hand')
157+
const offByPivot = 0.05 * height
158+
159+
const hoursHandDims = getDims(hoursHand, false, false)
160+
hoursHand.style.top = 1.6 * dialHours[11].offsetHeight + 'px'
161+
hoursHand.style.left = width / 2 - hoursHandDims.width / 2 + 'px'
162+
hoursHand.style.height = (height / 2 - 1.6 * dialHours[11].offsetHeight + offByPivot) + 'px'
163+
hoursHand.style.transformOrigin = `${hoursHandDims.width / 2}px ${hoursHand.offsetHeight - offByPivot}px`
164+
165+
const minutesHandDims = getDims(minutesHand, false, false)
166+
minutesHand.style.top = 1.2 * dialHours[11].offsetHeight + 'px'
167+
minutesHand.style.left = width / 2 - minutesHandDims.width / 2 + 'px'
168+
minutesHand.style.height = (height / 2 - 1.2 * dialHours[11].offsetHeight + offByPivot) + 'px'
169+
minutesHand.style.transformOrigin = `${minutesHandDims.width / 2}px ${minutesHand.offsetHeight - offByPivot}px`
170+
171+
const secondsHandDims = getDims(minutesHand, false, false)
172+
secondsHand.style.top = dialHours[11].offsetHeight + 'px'
173+
secondsHand.style.left = width / 2 - secondsHandDims.width / 2 + 'px'
174+
secondsHand.style.height = (height / 2 - dialHours[11].offsetHeight + offByPivot) + 'px'
175+
secondsHand.style.transformOrigin = `${secondsHandDims.width / 2}px ${secondsHand.offsetHeight - offByPivot}px`
176+
177+
const dt = new Date()
178+
const secsElpased = dt.getSeconds()
179+
const minsElapsed = dt.getMinutes() + secsElpased / 60
180+
const hrsElapsed = dt.getHours() % 12 + minsElapsed / 60
181+
182+
const rotate = (elm, deg) => {
183+
elm.style.transform = `rotate(${deg}deg)`
184+
}
185+
const init = () => {
186+
let hrsRotn = hrsElapsed * 360 / 12
187+
let minsRotn = minsElapsed * 360 / 60
188+
let secsRotn = secsElpased * 360 / 60
189+
rotate(hoursHand, hrsRotn)
190+
rotate(minutesHand, minsRotn)
191+
rotate(secondsHand, secsRotn)
192+
setTimeout(() => (secondsHand.style.transition = 'transform 1s linear'), 0)
193+
setInterval(() => {
194+
// do %360
195+
hrsRotn += 360 / (3600 * 12)
196+
minsRotn += 360 / (60 * 60)
197+
secsRotn += 360 / 60
198+
rotate(hoursHand, hrsRotn)
199+
rotate(minutesHand, minsRotn)
200+
rotate(secondsHand, secsRotn)
201+
}, 1000)
202+
}
203+
init()
204+
205+
</script>
46206
</html>

Source/RunActivity/Viewer3D/WebServices/Web/Time/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
// 2. It doesn't hide some returning error codes
2323
// 3. We don't need the ability to chain promises that fetch() offers.
2424

25-
var hr = new XMLHttpRequest;
26-
var httpCodeSuccess = 200;
27-
var xmlHttpRequestCodeDone = 4;
25+
let hr = new XMLHttpRequest;
26+
let httpCodeSuccess = 200;
27+
let xmlHttpRequestCodeDone = 4;
2828

2929
function ApiTime() {
3030
// "/API/TIME" /API is a prefix hard-coded into the WebServer class

0 commit comments

Comments
 (0)