V1.16.18 Modification des écrans

This commit is contained in:
2026-09-08 13:10:12 +00:00
parent 44be17d99b
commit 9d537a9b36
10 changed files with 398 additions and 65 deletions
+326 -62
View File
@@ -30,7 +30,36 @@
autre écran, mais ne devraient plus apparaître chez lui. Nouvelle image
1024×457 : toutes les coordonnées ci-dessous ont été remesurées sur
cette version (celles mesurées sur la précédente, 1280×650, ne
s'appliquent plus). */
s'appliquent plus).
8 septembre 2026 — passage à plusieurs fonds interchangeables (voir
réflexions stratégiques). Jean-Marc a fourni un jeu d'images séparant
enfin ce qui était jusqu'ici une seule photo plate (ecran_fond.jpg,
bureau + classeurs + micro + carnet + téléphone fondus ensemble) en
deux calques réutilisables :
- avant_plan_bureau.png : classeurs, micro, carnet, téléphone et
plateau du bureau, en PNG transparent (fond réellement transparent,
vérifié) — IDENTIQUE quel que soit l'écran affiché.
- fond_bureau_1.jpg / fond_bureau_2.jpg / fond_bureau_3.jpg : les 3
décors interchangeables (liège actuel, tasseaux gris pour l'écran
assistants, tableau blanc pour les futurs tableaux de bord),
affichés SEULS derrière l'avant-plan, sans classeurs dessus.
Toutes les images font 1024×457 comme l'ancienne photo — même logique
de "contain" ci-dessous, appliquée à l'avant-plan ET au conteneur des
fonds ensemble (voir #fonds-container/#avant-plan plus bas), pour que
les deux calques restent alignés au pixel près quelle que soit la
proportion d'écran.
L'avant-plan étant un nouveau visuel (classeurs redessinés, pas la même
photo), toutes les coordonnées de classeurs/micro/pastille ci-dessous
ont dû être entièrement remesurées dessus (mesure par analyse pixel,
même exigence que d'habitude) — un premier passage, à affiner comme
toujours une fois vu en conditions réelles chez Jean-Marc.
Navigation : 2 flèches posées sur le bureau à droite (voir
#fleche-precedente/#fleche-suivante), 3 fonds codés en dur (décision de
Jean-Marc), pas de mémorisation du fond choisi d'une session à l'autre
(toujours le fond 1 par défaut), sens du glissement lié à la flèche
pressée (le fond n+1 entre par la droite en poussant l'actuel vers la
gauche, et inversement). */
@font-face{
font-family:"Metro DF";
src:url('MetroDF.woff2') format('woff2'),url('MetroDF.ttf') format('truetype');
@@ -42,12 +71,65 @@
font-family:"Segoe UI","Arial",sans-serif;
}
body{
/* Couleur échantillonnée sur le mur de la photo, pour que les bandes
laissées par "contain" (si la proportion de l'écran diffère de celle
de l'image) se fondent avec la scène plutôt que de créer un bord net. */
background:#ad580d url('ecran_fond.jpg') center center / contain no-repeat;
/* Couleur neutre pour les bandes laissées par "contain" quand la
proportion de l'écran diffère de celle des images (1024×457) — plus
de couleur unique "sampled sur le mur" possible depuis le 8 septembre
2026, chaque fond ayant sa propre teinte de mur. */
background:#2b2b2b;
position:relative;
}
/* Conteneur des fonds interchangeables (8 septembre 2026) : positionné et
dimensionné exactement comme l'était l'image unique auparavant (même
calcul "contain" dans positionner(), voir plus bas), mais désormais un
élément réel plutôt qu'un simple background CSS du body — nécessaire
pour pouvoir faire glisser un fond hors champ pendant qu'un autre entre
(voir changerFond()). overflow:hidden empêche le fond en cours de
transition de déborder pendant son glissement. */
#fonds-container{
position:fixed;
overflow:hidden;
}
/* Un fond = une image plein cadre du conteneur (même ratio 1024×457 que
l'avant-plan, donc pas de letterbox interne : 100%/100% suffit, jamais
de déformation). position:absolute pour que l'ancien et le nouveau
fond puissent coexister le temps du glissement (voir changerFond()). */
.fond-slide{
position:absolute;
inset:0;
background-size:100% 100%;
background-position:center;
background-repeat:no-repeat;
}
/* Avant-plan (classeurs + micro + carnet + téléphone + plateau du bureau) :
identique quel que soit le fond affiché derrière, voir consigne de
Jean-Marc du 8 septembre 2026. Toujours positionné/dimensionné
exactement comme #fonds-container (même calcul dans positionner()),
jamais animé — pointer-events:none pour laisser passer le clic vers les
zones cliquables réelles (classeur-zone, micro-desk, etc.), positionnées
par-dessus au même titre qu'avant. */
#avant-plan{
position:fixed;
width:100%;height:100%;
pointer-events:none;
display:block;
}
/* Flèches de navigation entre fonds (8 septembre 2026) : posées sur le
bureau à droite, taille volontairement modeste ("pas trop grosses",
Jean-Marc) — ARROW_TAILLE_FRAC plus bas dans le script, à ajuster une
fois vu en conditions réelles ("ça va dépendre du rendu", Jean-Marc).
pointer-events déjà "auto" par défaut (bouton), pas besoin de le forcer. */
.fleche-nav{
position:fixed;
border:none;background:transparent;padding:0;margin:0;
cursor:pointer;
display:block;
}
.fleche-nav img{
width:100%;height:100%;display:block;
}
.fleche-nav:hover{
filter:brightness(1.15);
}
/* Étiquettes des 9 classeurs (7 septembre 2026 — évolution de l'essai à
un seul classeur "Contacts" du 2 septembre). Nouvelle photo fournie par
Jean-Marc, mêmes dimensions de référence (1024×457) et même bureau/mur/
@@ -329,9 +411,24 @@
visuellement proches. Pas de texte sur le post-it (choix explicite de
Jean-Marc) : le titre de la tâche n'apparaît qu'au survol (title natif),
le clic ne fait rien pour l'instant (voir journal — navigation vers
liste_todolist.html volontairement pas encore branchée). */
liste_todolist.html volontairement pas encore branchée).
Attachés au fond liège depuis le 8 septembre 2026 (retour de Jean-Marc :
"ils seront attachés au panneau de liège, ils partiront avec lui") : le
conteneur #postits-layer est déplacé (au sens JS, pas dupliqué) à
l'intérieur de la slide du fond liège (index 0) à chaque fois qu'elle
existe (voir creerFondSlide()/changerFond() dans le script) — les
post-its glissent donc avec ce fond précis pendant la transition, et
restent invisibles (hors DOM visible, simplement parqués dans une slide
retirée) tant qu'un autre fond est affiché. position:absolute (plus
fixed) car désormais positionnés par rapport à ce conteneur local, pas
par rapport à la fenêtre — voir positionner() (zoneLeft/zoneTop ne
rajoutent plus offX/offY). */
#postits-layer{
position:absolute;
inset:0;
}
.postit{
position:fixed;
position:absolute;
box-shadow:2px 4px 8px rgba(0,0,0,.35);
background:
linear-gradient(135deg, transparent 50%, rgba(0,0,0,.12) 50%, rgba(0,0,0,.12) 62%, transparent 62%) bottom right / 22% 22% no-repeat,
@@ -362,6 +459,13 @@
</head>
<body>
<!-- Fonds interchangeables + avant-plan fixe (8 septembre 2026, voir
commentaire d'en-tête). #fonds-container reste vide ici : rempli par
initialiserFonds() au chargement (1er fond) puis par changerFond() à
chaque clic sur une flèche. -->
<div id="fonds-container"></div>
<img id="avant-plan" src="avant_plan_bureau.png" alt="">
<!-- Les 9 zones cliquables + étiquettes de classeurs (7 septembre 2026) sont
créées par creerClasseurs() (voir script) à partir du tableau CLASSEURS,
sur le même principe que les post-its plus bas : éviter de dupliquer 9
@@ -393,6 +497,17 @@ Créé par Mevelia Solutions">
</div>
</div>
<!-- Flèches de navigation entre fonds (8 septembre 2026) : posées sur le
bureau à droite (consigne de Jean-Marc), après tous les autres éléments
fixes pour rester cliquables au-dessus de tout (ordre du document =
ordre d'empilement, aucun z-index explicite ailleurs sur cette page). -->
<button id="fleche-precedente" class="fleche-nav" type="button" title="Écran précédent">
<img src="fleche_precedente.png" alt="Écran précédent">
</button>
<button id="fleche-suivante" class="fleche-nav" type="button" title="Écran suivant">
<img src="fleche_suivante.png" alt="Écran suivant">
</button>
<script>
// Référence de l'image : 1024×457, inchangée en dimensions (voir
// ecran_fond.jpg — 3ᵉ version le 3 septembre 2026, Jean-Marc a raccourci
@@ -426,17 +541,31 @@ Créé par Mevelia Solutions">
// CLASSEURS_Y1/Y2 : rectangle vertical de la tranche visible, commun aux
// 9 classeurs (mesuré quasi identique sur chacun, 230-233 en haut et
// 409-411 en bas — la photo montre les 9 classeurs à la même hauteur).
const CLASSEURS_Y1 = 231, CLASSEURS_Y2 = 410;
// Remesuré le 8 septembre 2026 sur le nouvel avant-plan (avant_plan_bureau.png,
// classeurs redessinés — voir commentaire d'en-tête) : le bas passe de 410
// à 371 (ligne du bureau plus haute sur ce nouveau visuel, vérifiée sur
// toute la largeur de l'image — 100% des pixels opaques au-delà, contre
// 0% avant), et le haut de 231 à 236 (bas du petit "toit" incliné du
// classeur, mesuré par analyse pixel comme d'habitude).
// Remesuré une 2ᵉ fois le 8 septembre 2026 (soir) : Jean-Marc a recadré
// l'avant-plan (traces blanches sur le fond retirées, micro nettoyé), ce
// qui a décalé toute la composition d'environ 20px vers le bas — mêmes
// abscisses (vérifié par comparaison des silhouettes), toutes les
// ordonnées remesurées directement sur le nouveau fichier.
const CLASSEURS_Y1 = 257, CLASSEURS_Y2 = 393;
// Rectangle vertical utile de la partie blanche de l'étiquette (mesuré
// constant à 255-339 sur les 9 classeurs) : c'est cette hauteur, une fois
// convertie à l'écran, qui borne la largeur du texte tourné à -90°
// (voir calculerPoliceEtiquette() plus bas).
const ETIQ_LABEL_Y1 = 255, ETIQ_LABEL_Y2 = 339;
// constant à 249-333 sur les 9 classeurs du nouvel avant-plan, 8 septembre
// 2026) : c'est cette hauteur, une fois convertie à l'écran, qui borne la
// largeur du texte tourné à -90° (voir calculerPoliceEtiquette() plus bas).
// Remesuré le 8 septembre 2026 (soir), même recadrage que ci-dessus.
const ETIQ_LABEL_Y1 = 269, ETIQ_LABEL_Y2 = 353;
const ETIQ_CENTRE_Y_FRAC = ((ETIQ_LABEL_Y1 + ETIQ_LABEL_Y2) / 2) / IMG_H;
// Largeur utile de la partie blanche de l'étiquette (mesurée 22-25px selon
// le classeur, valeur basse retenue par sécurité — cette largeur borne
// l'ÉPAISSEUR du texte tourné, donc indirectement la taille de police
// maximale des libellés courts, voir calculerPoliceEtiquette() plus bas).
// Remesuré le 8 septembre 2026 sur le nouvel avant-plan (22-26px selon le
// classeur) : la même valeur basse (22) reste le bon choix par sécurité.
const ETIQ_LABEL_LARGEUR = 22;
// Marges de sécurité (10-6%) sur les deux contraintes ci-dessus. Plus
// resserrées que la précédente version (12%) : la taille de police n'est
@@ -488,56 +617,55 @@ Créé par Mevelia Solutions">
// fraction de IMG_W), au lieu de la double contrainte calculée par
// calculerPoliceEtiquette() — voir commentaire sur "Documents" ci-dessous
// pour le seul cas qui l'utilise pour l'instant.
// Remesuré intégralement le 8 septembre 2026 sur le nouvel avant-plan
// (avant_plan_bureau.png — 9 classeurs redessinés par Jean-Marc, mêmes
// libellés/ordre/href que la version précédente, seules les coordonnées
// changent). x1/x2 = limite de séparation entre classeurs (point le plus
// sombre mesuré dans l'intervalle entre deux étiquettes, pas juste le
// milieu géométrique — même principe que le 7 septembre). labelCx = centre
// du rectangle blanc de l'étiquette, mesuré indépendamment (les 9
// rectangles ne sont pas exactement centrés dans leur classeur).
const CLASSEURS = [
{id:'consignes', label:'Consignes', x1:44, x2:79.5, labelCx:57.2, href:null},
{id:'contacts', label:'Contacts', x1:79.5, x2:118, labelCx:96.6, href:'liste_contacts.html'},
{id:'catalogue', label:'Catalogue', x1:118, x2:155, labelCx:135.0, href:null},
// "Documentations" remplacé par "Documents" le 7 septembre 2026 (soir),
// à la demande de Jean-Marc (le libellé complet restait peu lisible même
// après le passage à measureText() : un mot de 14 lettres doit beaucoup
// rétrécir pour tenir dans la hauteur de l'étiquette). Police forcée
// (policeForceeFrac, voir ETIQ_POLICE_CAP_FRAC plus haut) plutôt que
// laissée au calcul automatique : "Documents" (9 lettres, comme
// "Consignes") tiendrait déjà largement dans la hauteur disponible même
// à la taille plafond commune aux libellés courts — autant l'aligner
// explicitement sur ce plafond pour garantir la même taille bien lisible
// que "Contacts"/"Catalogue"/"En cours"/"Factures", plutôt que de
// dépendre d'un calcul qui pourrait légèrement varier d'un libellé à
// l'autre. id conservé en interne à 'documentations' (cohérence avec
// l'historique de la photo/des mesures), seul le libellé affiché change.
{id:'documentations', label:'Documents', x1:155, x2:192.5, labelCx:173.9, href:null},
{id:'prospection', label:'Prospection', x1:192.5, x2:234, labelCx:212.6, href:null},
// "Communication" remplacé par "Réseaux" le 7 septembre 2026 (soir), à la
// demande de Jean-Marc : ce classeur regroupe la génération de posts
// Instagram et la veille concurrentielle sur les réseaux sociaux —
// "Réseaux" colle mieux à cet usage que le générique "Communication",
// en plus d'être bien plus court (donc bien plus lisible une fois
// tourné à -90°, voir calculerPoliceEtiquette()). id conservé en interne
// à 'communication' (cohérence avec l'historique de la photo/des
// mesures), seul le libellé affiché change.
{id:'communication', label:'Réseaux', x1:234, x2:274.5, labelCx:253.0, href:null},
{id:'en-cours', label:'En cours', x1:274.5, x2:312.5, labelCx:293.0, href:null},
{id:'factures', label:'Factures', x1:312.5, x2:352.5, labelCx:332.5, href:null},
{id:'journalier', label:'Journalier', x1:352.5, x2:395.5, labelCx:372.6, href:null},
{id:'consignes', label:'Consignes', x1:44, x2:83, labelCx:63.5, href:null},
{id:'contacts', label:'Contacts', x1:83, x2:120, labelCx:101.0, href:'liste_contacts.html'},
{id:'catalogue', label:'Catalogue', x1:120, x2:158, labelCx:138.5, href:null},
// "Documentations" (id interne conservé pour l'historique) reste affiché
// "Documents", police forcée sur le plafond commun — voir raisonnement
// inchangé du 7 septembre 2026 (toujours valable, indépendant de l'image).
{id:'documentations', label:'Documents', x1:158, x2:197, labelCx:177.0, href:null},
{id:'prospection', label:'Prospection', x1:197, x2:239, labelCx:216.0, href:null},
{id:'communication', label:'Réseaux', x1:239, x2:280, labelCx:259.0, href:null},
{id:'en-cours', label:'En cours', x1:280, x2:321, labelCx:300.5, href:null},
{id:'factures', label:'Factures', x1:321, x2:363, labelCx:341.5, href:null},
{id:'journalier', label:'Journalier', x1:363, x2:415, labelCx:383.5, href:null},
];
// Zone cliquable/survolable du micro, centre du rond noir de la grille
// (icône) et zone des post-its personnels : AUCUN changement le 7
// septembre 2026 — vérifié par comparaison pixel à pixel avec l'ancienne
// photo, identiques au-delà de x≈400 (voir commentaire CSS plus haut).
const MICRO_ZONE_X1 = 465, MICRO_ZONE_X2 = 543;
const MICRO_ZONE_Y1 = 249, MICRO_ZONE_Y2 = 419;
const ICONE_CENTRE_X = 512, ICONE_CENTRE_Y = 268;
// Zone cliquable/survolable du micro et centre de l'icône : remesurés le
// 8 septembre 2026 sur le nouvel avant-plan — micro d'un tout autre style
// (corps arrondi de studio, plus de petite grille ronde isolée en haut
// comme sur l'ancienne photo) : zone calée sur la silhouette entière
// (mesure directe des pixels non transparents), icône centrée sur le
// reflet du corps, repère visuel le plus naturel sur ce nouveau micro.
// Y1/Y2/icône remesurés le 8 septembre 2026 (soir), même recadrage
// (traces blanches/halo retirés autour du micro par Jean-Marc) — X
// inchangés (silhouette identique, seule la position verticale a bougé).
const MICRO_ZONE_X1 = 478, MICRO_ZONE_X2 = 549;
const MICRO_ZONE_Y1 = 271, MICRO_ZONE_Y2 = 393;
// X décalé légèrement à droite le 8 septembre 2026 (soir), retour de
// Jean-Marc — Y inchangé (remonté juste avant, jugé bon depuis).
const ICONE_CENTRE_X = 522, ICONE_CENTRE_Y = 288;
const ICONE_TAILLE_FRAC = 22 / IMG_W;
// Pastille "nombre de contacts" — sous le trou de préhension du classeur
// Contacts, à mi-chemin entre ce trou et le bas du classeur (retour de
// Jean-Marc le 7 septembre 2026 : la 1ʳᵉ mesure avait par erreur calé la
// pastille SUR le trou lui-même, pas en dessous). Trou de préhension
// repéré par sa forme ovale sombre, mesurée sur la nouvelle photo :
// x≈[89,107] (centre 98), y≈[360,374] (bas du trou 374). Milieu entre ce
// bas de trou (374) et le bas du classeur (CLASSEURS_Y2=410) : (374+410)/2
// = 392.
const PASTILLE_CONTACTS_CENTRE_X = 98, PASTILLE_CONTACTS_CENTRE_Y = 392;
// Pastille "nombre de contacts" — remesurée le 8 septembre 2026 sur le
// classeur Contacts du nouvel avant-plan (2ᵉ classeur, labelCx=101).
// Trou de préhension nettement plus bas et plus proche du bureau que sur
// l'ancienne photo (quasiment au ras de CLASSEURS_Y2=371, sans place pour
// la caler "en dessous" comme avant) : posée à la place juste au-dessus du
// trou, sous l'étiquette (ETIQ_LABEL_Y2=333) — premier essai, à revoir
// avec Jean-Marc après un rendu réel si trop proche du trou ou du texte.
// Y remesuré le 8 septembre 2026 (soir), même recadrage.
// Redescendue un peu le 8 septembre 2026 (soir), retour de Jean-Marc
// après 6ᵉ test réel (trop remontée la fois précédente) : 401 → 404.
const PASTILLE_CONTACTS_CENTRE_X = 101, PASTILLE_CONTACTS_CENTRE_Y = 404;
const PASTILLE_CONTACTS_DIAM_FRAC = 17 / IMG_W;
// Zone des post-its personnels (2 septembre 2026, premier affichage réel
@@ -552,14 +680,34 @@ Créé par Mevelia Solutions">
// 4 colonnes × 5 lignes = 20 cases, volontairement alignée sur
// CAPACITE_TABLEAU_PAR_UTILISATEUR (todolist.php) — à faire évoluer
// ensemble le jour où cette capacité changera.
// Y2 remesuré le 8 septembre 2026 (nouvel avant-plan, CLASSEURS_Y2=371 —
// voir plus haut) : même marge de sécurité qu'avant l'utilisant.
// Y2 remesuré le 8 septembre 2026 (soir), même recadrage (CLASSEURS_Y2
// passé à 393) — même marge de sécurité qu'avant l'utilisant.
const ZONE_POSTITS_X1 = 717, ZONE_POSTITS_X2 = 1024;
const ZONE_POSTITS_Y1 = 6, ZONE_POSTITS_Y2 = 395;
const ZONE_POSTITS_Y1 = 6, ZONE_POSTITS_Y2 = 378;
const GRILLE_POSTITS_COLONNES = 4, GRILLE_POSTITS_LIGNES = 5;
// Taille d'un post-it : ~60% de la plus petite dimension de case, pour
// laisser de la marge au jitter sans jamais déborder sur la case voisine
// (voir positionnerPostits()).
const POSTIT_RATIO_CASE = 0.6;
// -------- Flèches de navigation entre fonds (8 septembre 2026) --------
// Posées sur le bureau à droite (consigne de Jean-Marc), dans la zone
// vide du plateau au-delà du carnet/téléphone (x>668). Taille volontairement
// modeste ("pas trop grosses") — premier réglage, Jean-Marc a prévenu que
// la taille définitive "va dépendre du rendu" réel chez lui.
// Retouché le 8 septembre 2026 (soir), retour de Jean-Marc après premier
// test réel : remontées (trop près du bas), rapprochées l'une de l'autre,
// et collées plus à droite.
// Réduite d'environ 30% le 8 septembre 2026 (soir), retour de Jean-Marc
// après second test réel (34 → 24).
const FLECHE_TAILLE_FRAC = 24 / IMG_W;
// Flèche précédente réécartée un peu le 8 septembre 2026 (soir), retour
// de Jean-Marc après 4ᵉ test réel ("trop proches l'une de l'autre").
const FLECHE_PRECEDENTE_CENTRE_X = 962, FLECHE_CENTRE_Y = 410;
const FLECHE_SUIVANTE_CENTRE_X = 998;
/**
* Petit générateur pseudo-aléatoire déterministe (0..1), à partir d'un
* entier (TDL_Incr) — pour que le jitter (rotation/décalage) d'un post-it
@@ -665,6 +813,35 @@ Créé par Mevelia Solutions">
offX = 0; offY = (vh - dispH) / 2;
}
// Fonds interchangeables + avant-plan (8 septembre 2026) : occupent
// exactement le même rectangle "contain" que l'ancienne image unique,
// pour rester alignés au pixel près avec les classeurs/micro/pastille/
// post-its positionnés plus bas dans cette même fonction.
const fondsContainer = document.getElementById('fonds-container');
fondsContainer.style.left = offX + 'px';
fondsContainer.style.top = offY + 'px';
fondsContainer.style.width = dispW + 'px';
fondsContainer.style.height = dispH + 'px';
const avantPlan = document.getElementById('avant-plan');
avantPlan.style.left = offX + 'px';
avantPlan.style.top = offY + 'px';
avantPlan.style.width = dispW + 'px';
avantPlan.style.height = dispH + 'px';
// Flèches de navigation entre fonds (voir FLECHE_* plus haut).
const flecheTaille = FLECHE_TAILLE_FRAC * dispW;
const flechePrecedente = document.getElementById('fleche-precedente');
flechePrecedente.style.left = (offX + (FLECHE_PRECEDENTE_CENTRE_X / IMG_W) * dispW - flecheTaille / 2) + 'px';
flechePrecedente.style.top = (offY + (FLECHE_CENTRE_Y / IMG_H) * dispH - flecheTaille / 2) + 'px';
flechePrecedente.style.width = flecheTaille + 'px';
flechePrecedente.style.height = flecheTaille + 'px';
const flecheSuivante = document.getElementById('fleche-suivante');
flecheSuivante.style.left = (offX + (FLECHE_SUIVANTE_CENTRE_X / IMG_W) * dispW - flecheTaille / 2) + 'px';
flecheSuivante.style.top = (offY + (FLECHE_CENTRE_Y / IMG_H) * dispH - flecheTaille / 2) + 'px';
flecheSuivante.style.width = flecheTaille + 'px';
flecheSuivante.style.height = flecheTaille + 'px';
// Les 9 classeurs (zone cliquable + étiquette tournée, voir
// creerClasseurs() et calculerPoliceEtiquette() plus haut).
CLASSEURS.forEach(function (c) {
@@ -717,13 +894,18 @@ Créé par Mevelia Solutions">
// rechargement à l'autre. Le jitter reste borné à l'intérieur de la
// case (marge × 0.8, jamais 1) pour ne jamais déborder sur la case
// voisine — c'est ce qui garantit l'absence d'empilement.
// zoneLeft/zoneTop : plus de offX/offY depuis le 8 septembre 2026 — les
// post-its sont désormais positionnés à l'intérieur de #postits-layer,
// lui-même dans la slide du fond liège (inset:0 sur les deux), donc déjà
// calé sur le rectangle "contain" par la structure DOM elle-même (voir
// commentaire CSS #postits-layer plus haut).
const zoneW = ((ZONE_POSTITS_X2 - ZONE_POSTITS_X1) / IMG_W) * dispW;
const zoneH = ((ZONE_POSTITS_Y2 - ZONE_POSTITS_Y1) / IMG_H) * dispH;
const caseW = zoneW / GRILLE_POSTITS_COLONNES;
const caseH = zoneH / GRILLE_POSTITS_LIGNES;
const postitTaille = Math.min(caseW, caseH) * POSTIT_RATIO_CASE;
const zoneLeft = offX + (ZONE_POSTITS_X1 / IMG_W) * dispW;
const zoneTop = offY + (ZONE_POSTITS_Y1 / IMG_H) * dispH;
const zoneLeft = (ZONE_POSTITS_X1 / IMG_W) * dispW;
const zoneTop = (ZONE_POSTITS_Y1 / IMG_H) * dispH;
const margeX = (caseW - postitTaille) / 2 * 0.8;
const margeY = (caseH - postitTaille) / 2 * 0.8;
document.querySelectorAll('.postit').forEach(function (postit) {
@@ -742,6 +924,86 @@ Créé par Mevelia Solutions">
postit.style.transform = 'rotate(' + rotation.toFixed(1) + 'deg)';
});
}
// -------- Fonds interchangeables (8 septembre 2026) --------
// 3 fonds codés en dur (décision de Jean-Marc, pas de liste extensible
// pour l'instant) : liège actuel, tasseaux gris (futur écran assistants,
// présentation pas encore décidée), tableau blanc (futurs tableaux de
// bord). Toujours fondIndex=0 au chargement, aucune mémorisation d'une
// session à l'autre (décision explicite de Jean-Marc).
const FONDS = ['fond_bureau_1.jpg', 'fond_bureau_2.jpg', 'fond_bureau_3.jpg'];
let fondActuel = 0;
let glissementEnCours = false;
const DUREE_GLISSEMENT_MS = 450;
// Conteneur des post-its personnels, attaché au fond liège (index 0) —
// voir commentaire CSS #postits-layer plus haut. Créé une seule fois, vide
// au départ (chargerMesPostits() le remplit plus bas, de façon asynchrone,
// qu'il soit affiché ou parqué à ce moment-là — sans incidence puisque
// positionner() peut être appelée sans risque sur un élément hors DOM
// visible). Une variable JS, jamais document.getElementById() : l'élément
// reste valable même temporairement détaché du document (parqué dans une
// ancienne slide retirée), ce que getElementById ne retrouverait pas de la
// même façon si la recherche se faisait après un tel retrait.
const couchePostits = document.createElement('div');
couchePostits.id = 'postits-layer';
function creerFondSlide(index) {
const slide = document.createElement('div');
slide.className = 'fond-slide';
slide.style.backgroundImage = "url('" + FONDS[index] + "')";
// Le fond liège (index 0) embarque la couche des post-its : un simple
// appendChild déplace le noeud existant (le retire au passage de son
// ancien parent, s'il en avait un) — pas de duplication, pas de perte du
// contenu déjà chargé par chargerMesPostits().
if (index === 0) {
slide.appendChild(couchePostits);
}
return slide;
}
// Affiche le tout premier fond au chargement, sans transition.
function initialiserFonds() {
const conteneur = document.getElementById('fonds-container');
conteneur.appendChild(creerFondSlide(fondActuel));
}
// direction : +1 (flèche "suivant", le fond n+1 entre par la droite en
// poussant l'actuel vers la gauche) ou -1 (flèche "précédent", l'inverse)
// — sens du glissement lié à la flèche pressée, consigne explicite de
// Jean-Marc. Boucle sur les 3 fonds (n+1 après le 3ᵉ revient au 1er).
function changerFond(direction) {
if (glissementEnCours) return;
glissementEnCours = true;
const conteneur = document.getElementById('fonds-container');
const ancienneSlide = conteneur.querySelector('.fond-slide');
const nouvelIndex = (fondActuel + direction + FONDS.length) % FONDS.length;
const nouvelleSlide = creerFondSlide(nouvelIndex);
// Position de départ de la nouvelle slide (hors champ, côté d'où elle
// doit entrer), posée sans transition avant d'être ajoutée au DOM.
nouvelleSlide.style.transform = 'translateX(' + (direction > 0 ? '100%' : '-100%') + ')';
conteneur.appendChild(nouvelleSlide);
// Forcer un reflow avant d'activer la transition, sinon le navigateur
// regroupe la position de départ et la position d'arrivée en une seule
// étape (pas de glissement visible).
void nouvelleSlide.offsetWidth;
nouvelleSlide.style.transition = 'transform ' + DUREE_GLISSEMENT_MS + 'ms ease';
ancienneSlide.style.transition = 'transform ' + DUREE_GLISSEMENT_MS + 'ms ease';
requestAnimationFrame(function () {
nouvelleSlide.style.transform = 'translateX(0)';
ancienneSlide.style.transform = 'translateX(' + (direction > 0 ? '-100%' : '100%') + ')';
});
ancienneSlide.addEventListener('transitionend', function fin() {
ancienneSlide.removeEventListener('transitionend', fin);
ancienneSlide.remove();
glissementEnCours = false;
});
fondActuel = nouvelIndex;
}
document.getElementById('fleche-precedente').addEventListener('click', function () { changerFond(-1); });
document.getElementById('fleche-suivante').addEventListener('click', function () { changerFond(1); });
initialiserFonds();
creerClasseurs();
window.addEventListener('resize', positionner);
positionner();
@@ -876,7 +1138,9 @@ Créé par Mevelia Solutions">
pastille.className = 'pastille-urgence-postit ' + (tache.TDL_Groupe === 0 ? 'rouge' : 'orange');
postit.appendChild(pastille);
document.body.appendChild(postit);
// Attaché à couchePostits (fond liège), pas à document.body depuis
// le 8 septembre 2026 — voir commentaire sur couchePostits plus haut.
couchePostits.appendChild(postit);
});
positionner(); // place les post-its qui viennent d'être créés