Bandeaux avec scroll, drapeaux et noms ok

This commit is contained in:
2026-08-20 08:29:28 +00:00
parent 89d84021f3
commit 5a67aa6e9c
3 changed files with 94 additions and 39 deletions
+1
View File
@@ -12,6 +12,7 @@
display: flex; display: flex;
width: max-content; width: max-content;
animation: scroll linear infinite; animation: scroll linear infinite;
will-change: transform;
} }
.animate-ticker:hover { .animate-ticker:hover {
+60 -11
View File
@@ -80,25 +80,74 @@
> >
<!-- 3 Bandeaux empilés --> <!-- 3 Bandeaux empilés -->
<div <div
class="flex flex-col h-24 divide-y divide-slate-800/60 overflow-hidden bg-slate-900/80" class="flex flex-col h-24 divide-y divide-slate-800/60 bg-slate-900/80"
> >
<!-- Bandeau CAC40 --> <!-- Bandeau CAC40 -->
<div class="flex-1 overflow-hidden relative flex items-center"> <div class="flex-1 relative overflow-hidden flex items-center">
<div id="ticker-cac40" class="animate-ticker text-xs font-mono"></div> <!-- Étiquette fixe à gauche (Largeur fixe forcée) -->
<div
class="absolute left-0 top-0 h-full bg-slate-900 border-r border-slate-700/80 flex items-center px-4 space-x-3 z-20 shadow-lg"
style="width: 150px"
>
<span class="text-xl">🇫🇷</span>
<span class="font-bold text-xs text-white tracking-wider"
>CAC40</span
>
</div>
<!-- Zone de défilement (Padding gauche égal à la largeur de l'étiquette) -->
<div
class="w-full h-full flex items-center overflow-hidden"
style="padding-left: 150px"
>
<div
id="ticker-cac40"
class="animate-ticker text-xs font-mono"
></div>
</div>
</div> </div>
<!-- Bandeau IBEX35 --> <!-- Bandeau IBEX35 -->
<div class="flex-1 overflow-hidden relative flex items-center"> <div class="flex-1 relative overflow-hidden flex items-center">
<div <div
id="ticker-ibex35" class="absolute left-0 top-0 h-full bg-slate-900 border-r border-slate-700/80 flex items-center px-4 space-x-3 z-20 shadow-lg"
class="animate-ticker text-xs font-mono" style="width: 150px"
></div> >
<span class="text-xl">🇪🇸</span>
<span class="font-bold text-xs text-white tracking-wider"
>IBEX35</span
>
</div>
<div
class="w-full h-full flex items-center overflow-hidden"
style="padding-left: 150px"
>
<div
id="ticker-ibex35"
class="animate-ticker text-xs font-mono"
></div>
</div>
</div> </div>
<!-- Bandeau DOWJONES --> <!-- Bandeau DOWJONES -->
<div class="flex-1 overflow-hidden relative flex items-center"> <div class="flex-1 relative overflow-hidden flex items-center">
<div <div
id="ticker-dowjones" class="absolute left-0 top-0 h-full bg-slate-900 border-r border-slate-700/80 flex items-center px-4 space-x-3 z-20 shadow-lg"
class="animate-ticker text-xs font-mono" style="width: 150px"
></div> >
<span class="text-xl">🇺🇸</span>
<span class="font-bold text-xs text-white tracking-wider"
>DOWJONES</span
>
</div>
<div
class="w-full h-full flex items-center overflow-hidden"
style="padding-left: 150px"
>
<div
id="ticker-dowjones"
class="animate-ticker text-xs font-mono"
></div>
</div>
</div> </div>
</div> </div>
+33 -28
View File
@@ -2,13 +2,15 @@
let indicesData = []; let indicesData = [];
function chargerDonnees() { function chargerDonnees() {
// Appel de l'API située dans le dossier php/
fetch("./php/api_indices.php") fetch("./php/api_indices.php")
.then((response) => response.json()) .then((response) => response.json())
.then((result) => { .then((result) => {
if (result.status === "success") { if (result.status === "success") {
// Stockage dans le tableau global JS
indicesData = result.data; indicesData = result.data;
// Mise à jour de l'affichage // Mise à jour de tous les affichages
afficherSyntheseCartes(); afficherSyntheseCartes();
afficherTableauDetails(); afficherTableauDetails();
alimenterBandeauxTicker(); alimenterBandeauxTicker();
@@ -29,9 +31,11 @@ function afficherSyntheseCartes() {
const container = document.getElementById("cards-container"); const container = document.getElementById("cards-container");
container.innerHTML = ""; container.innerHTML = "";
// Trouver les indices uniques présents dans le tableau
const indicesUniques = [...new Set(indicesData.map((item) => item.indice))]; const indicesUniques = [...new Set(indicesData.map((item) => item.indice))];
indicesUniques.forEach((nomIndice) => { indicesUniques.forEach((nomIndice) => {
// Récupère le premier élément (le plus récent) pour cet indice
const dernier = indicesData.find((item) => item.indice === nomIndice); const dernier = indicesData.find((item) => item.indice === nomIndice);
if (!dernier) return; if (!dernier) return;
@@ -88,7 +92,6 @@ function afficherTableauDetails() {
} }
function alimenterBandeauxTicker() { function alimenterBandeauxTicker() {
// Filtrer et trier par ordre alphabétique sur le champ 'nom' (ou 'indice' si 'nom' est vide)
const preparerDonneesTicker = (nomIndice) => { const preparerDonneesTicker = (nomIndice) => {
let liste = indicesData.filter((item) => item.indice === nomIndice); let liste = indicesData.filter((item) => item.indice === nomIndice);
@@ -109,43 +112,45 @@ function alimenterBandeauxTicker() {
function remplirUnBandeau(elementId, donneesTriees) { function remplirUnBandeau(elementId, donneesTriees) {
const container = document.getElementById(elementId); const container = document.getElementById(elementId);
if (!container) return; if (!container) {
console.error("Élément introuvable :", elementId);
return;
}
if (donneesTriees.length === 0) { if (donneesTriees.length === 0) {
container.innerHTML = `<span class="px-4 text-slate-500">Aucune donnée disponible</span>`; container.innerHTML = `<span class="px-4 text-slate-500">Aucune donnée disponible</span>`;
return; return;
} }
let htmlContent = ""; let blocs = "";
donneesTriees.forEach((item) => {
const isPositive = parseFloat(item.variation_pct) >= 0;
const colorClass = isPositive ? "text-emerald-400" : "text-rose-400";
const sign = isPositive ? "+" : "";
const nomAffichage = item.nom || item.indice;
const coursFormate = parseFloat(item.cours).toLocaleString("fr-FR");
const variationFormatee = parseFloat(item.variation_pct).toFixed(2);
// On génère une séquence d'éléments blocs += `
const genererBlocs = () => { <div class="inline-flex items-center px-6 space-x-3 border-r border-slate-800/80 whitespace-nowrap">
let blocs = ""; <span class="font-bold text-white">${nomAffichage}</span>
donneesTriees.forEach((item) => { <span class="text-slate-300">${coursFormate}</span>
const isPositive = parseFloat(item.variation_pct) >= 0; <span class="${colorClass} font-semibold">${sign}${variationFormatee}%</span>
const colorClass = isPositive ? "text-emerald-400" : "text-rose-400"; </div>
const sign = isPositive ? "+" : ""; `;
const nomAffichage = item.nom || item.indice; });
const coursFormate = parseFloat(item.cours).toLocaleString("fr-FR");
const variationFormatee = parseFloat(item.variation_pct).toFixed(2);
blocs += ` // Duplication du contenu pour la boucle infinie fluide
<div class="inline-flex items-center px-6 space-x-3 border-r border-slate-800/80"> container.innerHTML = blocs + blocs;
<span class="font-bold text-white">${nomAffichage}</span>
<span class="text-slate-300">${coursFormate}</span>
<span class="${colorClass} font-semibold">${sign}${variationFormatee}%</span>
</div>
`;
});
return blocs;
};
// On duplique le contenu pour assurer un effet de défilement infini fluide sans saccade // Vitesse uniforme et lente
htmlContent = genererBlocs() + genererBlocs(); const dureeParElement = 6;
container.innerHTML = htmlContent; const dureeTotale = Math.max(30, donneesTriees.length * dureeParElement);
container.style.animationDuration = `${dureeTotale}s`;
} }
// Lancer au chargement initial // Lancer le chargement des données au démarrage de la page
chargerDonnees(); chargerDonnees();
// Rafraîchir automatiquement toutes les 60 secondes // Rafraîchir automatiquement toutes les 60 secondes