Horloge suisse en JS V1.0
This commit is contained in:
+280
@@ -0,0 +1,280 @@
|
||||
class SwissClock {
|
||||
constructor(elementId, useUTC = false) {
|
||||
this.element = document.getElementById(elementId);
|
||||
this.useUTC = useUTC;
|
||||
|
||||
if (!this.element) {
|
||||
console.error(`SwissClock : élément "${elementId}" introuvable.`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.createClock();
|
||||
this.update();
|
||||
}
|
||||
|
||||
createClock() {
|
||||
this.element.innerHTML = "";
|
||||
|
||||
// SVG
|
||||
this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
|
||||
this.svg.setAttribute("viewBox", "0 0 100 100");
|
||||
this.svg.setAttribute("width", "100%");
|
||||
this.svg.setAttribute("height", "100%");
|
||||
this.svg.setAttribute("aria-label", "Horloge suisse");
|
||||
|
||||
// Style global
|
||||
this.svg.style.display = "block";
|
||||
this.svg.style.overflow = "visible";
|
||||
|
||||
// Groupe principal
|
||||
this.clockGroup = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"g",
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// CADRAN
|
||||
// ------------------------------------------------------------
|
||||
|
||||
const face = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"circle",
|
||||
);
|
||||
|
||||
face.setAttribute("cx", "50");
|
||||
face.setAttribute("cy", "50");
|
||||
face.setAttribute("r", "47");
|
||||
face.setAttribute("fill", "#ffffff");
|
||||
|
||||
this.clockGroup.appendChild(face);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// INDEX / MINUTES
|
||||
// ------------------------------------------------------------
|
||||
|
||||
for (let i = 0; i < 60; i++) {
|
||||
const angle = ((i * 6 - 90) * Math.PI) / 180;
|
||||
|
||||
const isHour = i % 5 === 0;
|
||||
|
||||
const outerRadius = 44;
|
||||
const innerRadius = isHour ? 36 : 41;
|
||||
|
||||
const x1 = 50 + Math.cos(angle) * innerRadius;
|
||||
const y1 = 50 + Math.sin(angle) * innerRadius;
|
||||
|
||||
const x2 = 50 + Math.cos(angle) * outerRadius;
|
||||
const y2 = 50 + Math.sin(angle) * outerRadius;
|
||||
|
||||
const tick = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"line",
|
||||
);
|
||||
|
||||
tick.setAttribute("x1", x1);
|
||||
tick.setAttribute("y1", y1);
|
||||
tick.setAttribute("x2", x2);
|
||||
tick.setAttribute("y2", y2);
|
||||
|
||||
tick.setAttribute("stroke", "#111111");
|
||||
tick.setAttribute("stroke-width", isHour ? "2.2" : "0.8");
|
||||
|
||||
tick.setAttribute("stroke-linecap", isHour ? "square" : "round");
|
||||
|
||||
this.clockGroup.appendChild(tick);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// AIGUILLE DES HEURES
|
||||
// ------------------------------------------------------------
|
||||
|
||||
this.hourHand = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"line",
|
||||
);
|
||||
|
||||
this.hourHand.setAttribute("x1", "50");
|
||||
this.hourHand.setAttribute("y1", "52");
|
||||
this.hourHand.setAttribute("x2", "50");
|
||||
this.hourHand.setAttribute("y2", "25");
|
||||
|
||||
this.hourHand.setAttribute("stroke", "#111111");
|
||||
this.hourHand.setAttribute("stroke-width", "5");
|
||||
this.hourHand.setAttribute("stroke-linecap", "round");
|
||||
|
||||
this.clockGroup.appendChild(this.hourHand);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// AIGUILLE DES MINUTES
|
||||
// ------------------------------------------------------------
|
||||
|
||||
this.minuteHand = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"line",
|
||||
);
|
||||
|
||||
this.minuteHand.setAttribute("x1", "50");
|
||||
this.minuteHand.setAttribute("y1", "53");
|
||||
this.minuteHand.setAttribute("x2", "50");
|
||||
this.minuteHand.setAttribute("y2", "15");
|
||||
|
||||
this.minuteHand.setAttribute("stroke", "#111111");
|
||||
this.minuteHand.setAttribute("stroke-width", "3.5");
|
||||
this.minuteHand.setAttribute("stroke-linecap", "round");
|
||||
|
||||
this.clockGroup.appendChild(this.minuteHand);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// TROTTEUSE ROUGE
|
||||
// ------------------------------------------------------------
|
||||
|
||||
this.secondHand = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"line",
|
||||
);
|
||||
|
||||
this.secondHand.setAttribute("x1", "50");
|
||||
this.secondHand.setAttribute("y1", "55");
|
||||
this.secondHand.setAttribute("x2", "50");
|
||||
this.secondHand.setAttribute("y2", "10");
|
||||
|
||||
this.secondHand.setAttribute("stroke", "#e30613");
|
||||
this.secondHand.setAttribute("stroke-width", "1.5");
|
||||
this.secondHand.setAttribute("stroke-linecap", "round");
|
||||
|
||||
this.clockGroup.appendChild(this.secondHand);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// CONTREPOIDS DE LA TROTTEUSE
|
||||
// ------------------------------------------------------------
|
||||
|
||||
this.secondCounterweight = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"line",
|
||||
);
|
||||
|
||||
this.secondCounterweight.setAttribute("x1", "50");
|
||||
this.secondCounterweight.setAttribute("y1", "48");
|
||||
this.secondCounterweight.setAttribute("x2", "50");
|
||||
this.secondCounterweight.setAttribute("y2", "61");
|
||||
|
||||
this.secondCounterweight.setAttribute("stroke", "#e30613");
|
||||
this.secondCounterweight.setAttribute("stroke-width", "2");
|
||||
this.secondCounterweight.setAttribute("stroke-linecap", "round");
|
||||
|
||||
this.clockGroup.appendChild(this.secondCounterweight);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// CENTRE
|
||||
// ------------------------------------------------------------
|
||||
|
||||
const centerOuter = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"circle",
|
||||
);
|
||||
|
||||
centerOuter.setAttribute("cx", "50");
|
||||
centerOuter.setAttribute("cy", "50");
|
||||
centerOuter.setAttribute("r", "3");
|
||||
centerOuter.setAttribute("fill", "#111111");
|
||||
|
||||
this.clockGroup.appendChild(centerOuter);
|
||||
|
||||
const centerInner = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"circle",
|
||||
);
|
||||
|
||||
centerInner.setAttribute("cx", "50");
|
||||
centerInner.setAttribute("cy", "50");
|
||||
centerInner.setAttribute("r", "1.3");
|
||||
centerInner.setAttribute("fill", "#e30613");
|
||||
|
||||
this.clockGroup.appendChild(centerInner);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// BORDURE
|
||||
// ------------------------------------------------------------
|
||||
|
||||
const border = document.createElementNS(
|
||||
"http://www.w3.org/2000/svg",
|
||||
"circle",
|
||||
);
|
||||
|
||||
border.setAttribute("cx", "50");
|
||||
border.setAttribute("cy", "50");
|
||||
border.setAttribute("r", "47");
|
||||
|
||||
border.setAttribute("fill", "none");
|
||||
border.setAttribute("stroke", "#111111");
|
||||
border.setAttribute("stroke-width", "1.5");
|
||||
|
||||
this.clockGroup.appendChild(border);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// AJOUT AU SVG
|
||||
// ------------------------------------------------------------
|
||||
|
||||
this.svg.appendChild(this.clockGroup);
|
||||
this.element.appendChild(this.svg);
|
||||
}
|
||||
|
||||
getTime() {
|
||||
const now = new Date();
|
||||
|
||||
if (this.useUTC) {
|
||||
return {
|
||||
hours: now.getUTCHours(),
|
||||
minutes: now.getUTCMinutes(),
|
||||
seconds: now.getUTCSeconds(),
|
||||
milliseconds: now.getUTCMilliseconds(),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
hours: now.getHours(),
|
||||
minutes: now.getMinutes(),
|
||||
seconds: now.getSeconds(),
|
||||
milliseconds: now.getMilliseconds(),
|
||||
};
|
||||
}
|
||||
|
||||
update() {
|
||||
const time = this.getTime();
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// ANGLES
|
||||
// ------------------------------------------------------------
|
||||
|
||||
// Heure
|
||||
const hourAngle = (time.hours % 12) * 30 + time.minutes * 0.5;
|
||||
|
||||
// Minute
|
||||
const minuteAngle = time.minutes * 6 + time.seconds * 0.1;
|
||||
|
||||
// Seconde
|
||||
const secondAngle = time.seconds * 6;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// ROTATION DES AIGUILLES
|
||||
// ------------------------------------------------------------
|
||||
|
||||
this.hourHand.setAttribute("transform", `rotate(${hourAngle} 50 50)`);
|
||||
|
||||
this.minuteHand.setAttribute("transform", `rotate(${minuteAngle} 50 50)`);
|
||||
|
||||
this.secondHand.setAttribute("transform", `rotate(${secondAngle} 50 50)`);
|
||||
|
||||
this.secondCounterweight.setAttribute(
|
||||
"transform",
|
||||
`rotate(${secondAngle} 50 50)`,
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// PROCHAIN RAF
|
||||
// ------------------------------------------------------------
|
||||
|
||||
requestAnimationFrame(() => this.update());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user