88 lines
1.8 KiB
Svelte
88 lines
1.8 KiB
Svelte
<script lang="ts">
|
|
import { onMount } from 'svelte';
|
|
|
|
interface Props {
|
|
dureeMs?: number; // fenêtre du bonus temps (60 s)
|
|
actif?: boolean;
|
|
}
|
|
|
|
let { dureeMs = 60000, actif = true }: Props = $props();
|
|
|
|
let ecoule = $state(0);
|
|
let intervalle: ReturnType<typeof setInterval> | null = null;
|
|
const depart = Date.now();
|
|
|
|
// Fraction restante, de 1 (plein) à 0 (vide) — informatif, jamais anxiogène.
|
|
let fraction = $derived(Math.max(0, 1 - ecoule / dureeMs));
|
|
let termine = $derived(ecoule >= dureeMs);
|
|
|
|
const R = 15.5;
|
|
const C = 2 * Math.PI * R;
|
|
|
|
/** Temps écoulé en ms (pour le bonus côté /api/guess). */
|
|
export function tempsMs(): number {
|
|
return Date.now() - depart;
|
|
}
|
|
|
|
onMount(() => {
|
|
if (actif) {
|
|
intervalle = setInterval(() => {
|
|
ecoule = Date.now() - depart;
|
|
if (ecoule >= dureeMs && intervalle) {
|
|
clearInterval(intervalle);
|
|
intervalle = null;
|
|
}
|
|
}, 250);
|
|
}
|
|
return () => {
|
|
if (intervalle) clearInterval(intervalle);
|
|
};
|
|
});
|
|
</script>
|
|
|
|
<div class="timer" class:termine role="timer" aria-label="Minuteur" title="Minuteur">
|
|
<svg viewBox="0 0 36 36" aria-hidden="true">
|
|
<circle class="fond" cx="18" cy="18" r={R} />
|
|
<circle
|
|
class="reste"
|
|
cx="18"
|
|
cy="18"
|
|
r={R}
|
|
stroke-dasharray={C}
|
|
stroke-dashoffset={C * (1 - fraction)}
|
|
transform="rotate(-90 18 18)"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
|
|
<style>
|
|
.timer {
|
|
width: 40px;
|
|
height: 40px;
|
|
}
|
|
|
|
svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: block;
|
|
}
|
|
|
|
.fond {
|
|
fill: rgba(255, 253, 248, 0.85);
|
|
stroke: var(--oki-sable-fonce);
|
|
stroke-width: 3;
|
|
}
|
|
|
|
.reste {
|
|
fill: none;
|
|
stroke: var(--oki-vert-clair); /* couleur douce, calm technology */
|
|
stroke-width: 3;
|
|
stroke-linecap: round;
|
|
transition: stroke-dashoffset 0.25s linear;
|
|
}
|
|
|
|
.termine .reste {
|
|
stroke: var(--oki-sable-fonce);
|
|
}
|
|
</style>
|