Merge pull request #39 from ok2/codex/fix-alignment-of-hands-and-markers
Improve analog clock alignment
This commit is contained in:
commit
a39c7216b3
80
clock.js
80
clock.js
@ -9,7 +9,40 @@
|
||||
toCobiets
|
||||
} = window.Cobie;
|
||||
|
||||
// CoBiE helpers pulled from cobie.js
|
||||
function getMarkerOffset(width) {
|
||||
const points = [
|
||||
{ width: 1024, value: 2 },
|
||||
{ width: 450, value: 1.3 },
|
||||
{ width: 200, value: 0.8 }
|
||||
];
|
||||
|
||||
// Sort points by width descending for easier handling
|
||||
points.sort((a, b) => b.width - a.width);
|
||||
|
||||
for (let i = 0; i < points.length - 1; i++) {
|
||||
const p1 = points[i];
|
||||
const p2 = points[i + 1];
|
||||
if (width <= p1.width && width >= p2.width) {
|
||||
// Linear interpolation
|
||||
const t = (width - p2.width) / (p1.width - p2.width);
|
||||
return p2.value + t * (p1.value - p2.value);
|
||||
}
|
||||
}
|
||||
|
||||
// Extrapolation for width > max known
|
||||
if (width > points[0].width) {
|
||||
const p1 = points[0];
|
||||
const p2 = points[1];
|
||||
const slope = (p1.value - p2.value) / (p1.width - p2.width);
|
||||
return p1.value + slope * (width - p1.width);
|
||||
}
|
||||
|
||||
// Extrapolation for width < min known
|
||||
const p1 = points[points.length - 2];
|
||||
const p2 = points[points.length - 1];
|
||||
const slope = (p2.value - p1.value) / (p2.width - p1.width);
|
||||
return p2.value + slope * (width - p2.width);
|
||||
}
|
||||
|
||||
function placeMarkers() {
|
||||
const clock = document.getElementById('clock');
|
||||
@ -40,38 +73,39 @@
|
||||
ticks = clock.querySelectorAll('.tick');
|
||||
}
|
||||
|
||||
// Position markers based on the current clock size
|
||||
// Move markers slightly inward and tweak the center position so
|
||||
// the ring of ticks lines up perfectly with the border.
|
||||
const borderOffset = clock.offsetWidth > 300 ? 45 : 26;
|
||||
const centerAdjust = { x: -3, y: -2 };
|
||||
const markerRadius = clock.offsetWidth / 2 - borderOffset;
|
||||
// Unified radius based on the actual clock size
|
||||
const rect = clock.getBoundingClientRect();
|
||||
const baseRadius = rect.width / 2;
|
||||
|
||||
// Tick lengths relative to the clock radius
|
||||
const lenBig = baseRadius * 0.12;
|
||||
const lenMid = baseRadius * 0.08;
|
||||
const lenSmall = baseRadius * 0.05;
|
||||
|
||||
const outerR = baseRadius - 2; // just inside the border
|
||||
|
||||
// Distance from center for the marker digits so they sit just inside big ticks
|
||||
const markerSize = markers[0] ? markers[0].offsetWidth : 0;
|
||||
const markerRadius = outerR - lenBig - markerSize * getMarkerOffset(rect.width);
|
||||
|
||||
markers.forEach((m, i) => {
|
||||
const angle = (i / 16) * 2 * Math.PI;
|
||||
const x = markerRadius * Math.sin(angle);
|
||||
const y = -markerRadius * Math.cos(angle);
|
||||
m.style.left = `${clock.offsetWidth / 2 + x + centerAdjust.x}px`;
|
||||
m.style.top = `${clock.offsetHeight / 2 + y + centerAdjust.y}px`;
|
||||
m.style.left = '50%';
|
||||
m.style.top = '50%';
|
||||
m.style.transform =
|
||||
`translate(-50%, -50%) rotate(${angle}rad) translate(0, -${markerRadius}px) rotate(${-angle}rad)`;
|
||||
});
|
||||
|
||||
// Tick lengths based on the marker radius
|
||||
const lenBig = markerRadius * 0.12;
|
||||
const lenMid = markerRadius * 0.08;
|
||||
const lenSmall = markerRadius * 0.05;
|
||||
|
||||
ticks.forEach((t, i) => {
|
||||
let len = lenSmall;
|
||||
if (t.classList.contains('big')) len = lenBig;
|
||||
else if (t.classList.contains('mid')) len = lenMid;
|
||||
const outerR = clock.offsetWidth / 2 - 2;
|
||||
const innerR = outerR - len;
|
||||
const angle = (i / 256) * 2 * Math.PI;
|
||||
const x = innerR * Math.sin(angle);
|
||||
const y = -innerR * Math.cos(angle);
|
||||
const angle = ((i + 1) / 256) * 2 * Math.PI;
|
||||
t.style.height = `${len}px`;
|
||||
t.style.left = `${clock.offsetWidth / 2 + x - t.offsetWidth / 2 + centerAdjust.x}px`;
|
||||
t.style.top = `${clock.offsetHeight / 2 + y + centerAdjust.y}px`;
|
||||
t.style.transform = `rotate(${angle}rad)`;
|
||||
t.style.left = '50%';
|
||||
t.style.top = '50%';
|
||||
t.style.transform = `translate(-50%, 0) rotate(${angle}rad) translate(0, -${innerR}px)`;
|
||||
if (clock.offsetWidth < 200 && !t.classList.contains('big') && !t.classList.contains('mid')) {
|
||||
t.style.display = 'none';
|
||||
} else {
|
||||
|
||||
@ -414,11 +414,11 @@
|
||||
|
||||
.clock-label {
|
||||
position: absolute;
|
||||
bottom: 23%;
|
||||
bottom: 30%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-family: 'Great Vibes', cursive;
|
||||
font-size: calc(var(--clock-size) * 0.08);
|
||||
font-size: calc(var(--clock-size) * 0.06);
|
||||
color: #ffaaff;
|
||||
text-shadow: 0 0 6px rgba(255, 0, 255, 0.6);
|
||||
pointer-events: none;
|
||||
@ -445,7 +445,7 @@ body.fullscreen-clock .clock-label {
|
||||
border-radius: 0;
|
||||
text-shadow: 0 0 6px rgba(0, 255, 255, 0.9), 0 0 12px rgba(0, 255, 255, 0.7);
|
||||
box-shadow: none;
|
||||
transform: translate(-50%, -50%);
|
||||
transform-origin: center;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user