Bandeaux avec scroll, drapeaux et noms ok
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user