[Tuto] Modification de l'animation de chargement Jeedom parmi une sélection

Helloo,

Je vous propose un tuto pour pouvoir modifier l’animation d’attente de Jeedom.

googleBounce
appleRing

L’installation nécessite les étapes suivantes :

:one: Créer un virtuel avec une commande animation de type info / Autre et une commande action associée setAnimation de type action / Liste

  • Ajouter la liste suivante des animations disponibles au niveau de la commande action comme sur la capture :

appleRing|appleRing;googleBounce|googleBounce;spirale|spirale;feu|feu;plasma|plasma;glitch|glitch;aurora|aurora;dotsOrbit|dotsOrbit;energyBurst|energyBurst;rubberBall|rubberBall;liquidDrop|liquidDrop;neonPulse|neonPulse;galaxySwirl|galaxySwirl;vortexPulse|vortexPulse;vortexNova|vortexNova;floatingOrbs|floatingOrbs;impactBurst|impactBurst;neuralPath|neuralPath;equalizer|equalizer;cubeRotate|cubeRotate;blueSpinner|blueSpinner;jeedomLogo|jeedomLogo;ballsRotation|ballsRotation;jeedomHolo|jeedomHolo

:two: Sélectionner le menu Personnalisation avancée

:three: Editer et ajouter le code suivant dans le fichier custom.css

custom.css
/* ---------- Animation générique (exemple de spinner simple) ---------- */
#div_jeedomLoading[data-style="spirale"] {
  background-color: transparent;
}
#div_jeedomLoading[data-style="spirale"] .loadingSpinner {
  position: relative;
}
#div_jeedomLoading[data-style="spirale"] .loadingSpinner::before {
  content: "";
  position: absolute;
  border: 6px solid var(--al-info-color);
  border-top-color: transparent;
  border-radius: 50%;
  width: 100%;
  height: 100%;
  animation: spin 1s linear infinite;
}

/* ---------- Animation "googleBounce" ---------- */
#div_jeedomLoading[data-style="googleBounce"] {
  background-color: transparent;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  width: 100vw;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 9999;
}

#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner {
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
}

#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div {
  position: absolute;
  width: 20%;
  height: 20%;
  border-radius: 50%;
  background-color: var(--logo-primary-color);
  animation: bounce 1.5s infinite ease-in-out;
}

#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div:nth-child(1) {
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  animation-delay: 0s;
  background-color: #4285F4; /* bleu Google */
}
#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div:nth-child(2) {
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  animation-delay: 0.3s;
  background-color: #EA4335; /* rouge Google */
}
#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div:nth-child(3) {
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  animation-delay: 0.6s;
  background-color: #FBBC05; /* jaune Google */
}
#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div:nth-child(4) {
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  animation-delay: 0.9s;
  background-color: #34A853; /* vert Google */
}
#div_jeedomLoading[data-style="googleBounce"]  .loadingSpinner,
#div_jeedomLoading[data-style="googleBounce"]  .loadingSpinner::before,
#div_jeedomLoading[data-style="googleBounce"]  .loadingSpinner::after {
    border-top-color: transparent;
}
@keyframes bounce {
  0%, 100% {
    transform: scale(1);
    opacity: 0.7;
  }
  50% {
    transform: scale(1.5);
    opacity: 1;
  }
}


/* ---------- Animation "appleRing" ---------- */
#div_jeedomLoading[data-style="appleRing"] {
  background-color: transparent;
  position: absolute;
}

#div_jeedomLoading[data-style="appleRing"] .loadingSpinner {
  border: 3px solid rgba(255, 255, 255, 0.2);
  border-top-color: var(--logo-primary-color);
  border-radius: 50%;
  animation: appleSpin 1.2s linear infinite;
  box-shadow:
    0 0 8px var(--logo-primary-color),
    inset 0 0 10px rgba(255, 255, 255, 0.4);
}

#div_jeedomLoading[data-style="appleRing"] .loadingSpinner::before {
  content: "";
  position: absolute;
  top: -15%;
  left: -15%;
  width: 130%;
  height: 130%;
  border-radius: 50%;
  box-shadow:
    0 0 12px var(--logo-primary-color),
    0 0 30px rgba(255, 255, 255, 0.6);
  opacity: 0.6;
  animation: pulseGlow 2.4s ease-in-out infinite alternate;
  pointer-events: none;
}

@keyframes appleSpin {
  0% {
    transform: rotate(0deg);
    border-top-color: var(--logo-primary-color);
  }
  50% {
    border-top-color: rgba(255, 255, 255, 0.8);
  }
  100% {
    transform: rotate(360deg);
    border-top-color: var(--logo-primary-color);
  }
}

@keyframes pulseGlow {
  0% {
    opacity: 0.4;
    box-shadow:
      0 0 10px var(--logo-primary-color),
      0 0 20px rgba(255, 255, 255, 0.3);
  }
  100% {
    opacity: 0.8;
    box-shadow:
      0 0 25px var(--logo-primary-color),
      0 0 40px rgba(255, 255, 255, 0.6);
  }
}

/* ---------- Animation "energyBurst" (pulsation) ---------- */
#div_jeedomLoading[data-style="energyBurst"] {
  background-color: transparent;
  position: absolute;
}

#div_jeedomLoading[data-style="energyBurst"] .loadingSpinner {
  border-radius: 50%;
  position: relative;
  box-shadow:
    0 0 15px 5px var(--al-warning-color),
    inset 0 0 20px 8px var(--al-info-color);
  animation: pulseScale 2.5s ease-in-out infinite, spinLinear 3s linear infinite;
  background: radial-gradient(circle at center, var(--al-warning-color), transparent 70%);
  overflow: visible;
}

#div_jeedomLoading[data-style="energyBurst"] .loadingSpinner::before,
#div_jeedomLoading[data-style="energyBurst"] .loadingSpinner::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  width: 14vh;
  height: 14vh;
  transform: translate(-50%, -50%);
  box-shadow:
    0 -10px 10px var(--al-danger-color),
    10px 0 10px var(--al-danger-color),
    0 10px 10px var(--al-danger-color),
    -10px 0 10px var(--al-danger-color);
  animation: flicker 1.5s infinite alternate;
  filter: drop-shadow(0 0 8px var(--al-danger-color));
  opacity: 0.7;
  mix-blend-mode: screen;
}

#div_jeedomLoading[data-style="energyBurst"] .loadingSpinner::after {
  width: 16vh;
  height: 16vh;
  animation-delay: 0.75s;
  opacity: 0.4;
  filter: drop-shadow(0 0 12px var(--al-danger-color));
}

@keyframes pulseScale {
  0%, 100% {
    transform: scale(1);
    box-shadow:
      0 0 15px 5px var(--al-warning-color),
      inset 0 0 20px 8px var(--al-info-color);
  }
  50% {
    transform: scale(1.15);
    box-shadow:
      0 0 30px 10px var(--al-danger-color),
      inset 0 0 40px 12px var(--al-danger-color);
  }
}

@keyframes flicker {
  0% {
    opacity: 0.4;
    filter: drop-shadow(0 0 6px var(--al-danger-color));
  }
  100% {
    opacity: 1;
    filter: drop-shadow(0 0 14px var(--al-danger-color));
  }
}

/* ---------- Animation "feu" (pulsation) ---------- */
#div_jeedomLoading[data-style="feu"] {
  background-color: transparent;
}
#div_jeedomLoading[data-style="feu"] .loadingSpinner {
  border-radius: 50%;
  background: radial-gradient(circle, orange, red);
  animation: pulse 1s ease-in-out infinite, spinLinear 3s linear infinite;
}

/* ---------- Animation "plasma" (électrique) ---------- */
#div_jeedomLoading[data-style="plasma"] {
  background-color: transparent;
}
#div_jeedomLoading[data-style="plasma"] .loadingSpinner {
  position: relative;
}
#div_jeedomLoading[data-style="plasma"] .loadingSpinner::before {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  background: repeating-conic-gradient(#00f, #0ff, #00f 20%);
  border-radius: 50%;
  animation: plasma 2s linear infinite;
}

/* ---------- Animation "glitch" (techno glitch) ---------- */
#div_jeedomLoading[data-style="glitch"] .loadingSpinner {
  position: relative;
  top: 40%;
  left: 50%;
  transform: translateX(-50%);
  background-color: transparent;
  box-shadow:
    0 0 2px var(--logo-primary-color),
    inset 0 0 10px var(--logo-primary-color);
  animation: glitchGlow 2s infinite, spinLinear 3s linear infinite;
  overflow: hidden;
}
#div_jeedomLoading[data-style="glitch"] .loadingSpinner::before,
#div_jeedomLoading[data-style="glitch"] .loadingSpinner::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  border: 2px dashed var(--al-info-color);
  border-radius: 2px;
  opacity: 0.6;
  animation: circuitFlow 4s linear infinite;
  mix-blend-mode: lighten;
  filter: drop-shadow(0 0 5px var(--al-warning-color));
}
#div_jeedomLoading[data-style="glitch"] .loadingSpinner::after {
  animation-direction: reverse;
  opacity: 0.3;
  filter: drop-shadow(0 0 10px var(--al-success-color));
}


/* ---------- Animation "aurora" (aura lumineuse) ---------- */
#div_jeedomLoading[data-style="aurora"] {
  background-color: rgba(10, 10, 10, 0.85);
}
#div_jeedomLoading[data-style="aurora"] .loadingSpinner {
  position: relative;
  top: 40%;
  left: 50%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(circle at center, rgba(255, 255, 255, 0.1), transparent 70%);
  box-shadow: 0 0 40px rgba(255, 255, 255, 0.2);
  animation: rotatePulse 6s linear infinite;
  overflow: visible;
}
#div_jeedomLoading[data-style="aurora"] .loadingSpinner::before,
#div_jeedomLoading[data-style="aurora"] .loadingSpinner::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: conic-gradient(from 0deg, var(--logo-primary-color), var(--al-warning-color), var(--logo-primary-color));
  animation: auroraSpin 3s ease-in-out infinite alternate;
  opacity: 0.4;
  filter: blur(8px);
  mix-blend-mode: screen;
}
#div_jeedomLoading[data-style="aurora"] .loadingSpinner::after {
  animation-delay: 1.5s;
  opacity: 0.2;
  filter: blur(12px);
}

/* ---------- Animation "dotsOrbit" (points en orbite) ---------- */
#div_jeedomLoading[data-style="dotsOrbit"] {
  background-color: transparent;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner {
  position: relative;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div {
  position: absolute;
  width: 20%;
  height: 20%;
  background: var(--al-info-color);
  border-radius: 50%;
  opacity: 0.3;
  animation: dotFade 1.2s linear infinite;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(1) {
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  animation-delay: 0s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(2) {
  top: 20%;
  right: 0;
  animation-delay: 0.15s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(3) {
  bottom: 20%;
  right: 0;
  animation-delay: 0.3s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(4) {
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  animation-delay: 0.45s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(5) {
  bottom: 20%;
  left: 0;
  animation-delay: 0.6s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(6) {
  top: 20%;
  left: 0;
  animation-delay: 0.75s;
}

/* ---------- Keyframes ---------- */
@keyframes spin {
  0% { transform: rotate(0); }
  100% { transform: rotate(360deg); }
}
@keyframes pulse {
  0% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.2); opacity: 0.5; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes plasma {
  0% { transform: rotate(0deg) scale(1); }
  50% { transform: rotate(180deg) scale(1.1); }
  100% { transform: rotate(360deg) scale(1); }
}
@keyframes glitchGlow {
  0%, 100% {
    box-shadow:
      0 0 2px var(--logo-primary-color),
      inset 0 0 10px var(--logo-primary-color);
  }
  50% {
    box-shadow:
      0 0 15px var(--al-danger-color),
      inset 0 0 20px var(--al-danger-color);
  }
}
@keyframes spinLinear {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
@keyframes circuitFlow {
  0% {
    transform: rotate(0deg) scale(1);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}
@keyframes rotatePulse {
  0% {
    transform: translateX(-50%) rotate(0deg) scale(0.95);
  }
  50% {
    transform: translateX(-50%) rotate(180deg) scale(1.05);
  }
  100% {
    transform: translateX(-50%) rotate(360deg) scale(0.95);
  }
}
@keyframes auroraSpin {
  0% {
    transform: rotate(0deg) scale(1);
  }
  100% {
    transform: rotate(360deg) scale(1.2);
  }
}
@keyframes dotFade {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 1; }
}

/* Animation rubberBall */
.loadingSpinner.rubberBall {
  width: 60px;
  height: 60px;
  margin: 40px auto;
  position: absolute!important;
}

.loadingSpinner.rubberBall::before {
  content: '';
  width: 60px;
  height: 60px;
  background: radial-gradient(circle at 30% 30%, #ff6b6b, #ff1e1e);
  border-radius: 50%;
  position: absolute;
  bottom: 0;
  animation: rubberBounce 1s infinite ease-in-out;
}

@keyframes rubberBounce {
  0%, 100% {
    transform: translateY(0) scaleX(1) scaleY(1);
  }
  30% {
    transform: translateY(-80px) scaleX(1.1) scaleY(0.9);
  }
  50% {
    transform: translateY(0) scaleX(0.9) scaleY(1.1);
  }
  70% {
    transform: translateY(-40px) scaleX(1.05) scaleY(0.95);
  }
}

/* Animation LiquidDrop */
.loadingSpinner.liquidDrop {
  --width: 80px;
  --height: 80px;
  margin: 40px auto!important;
  --position: relative!important;
  position: absolute!important;
}

.loadingSpinner.liquidDrop div {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, #00c9ff, #92fe9d);
  animation: liquidMorph 2s infinite ease-in-out;
  filter: blur(1px);
}

@keyframes liquidMorph {
  0%, 100% {
    border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
    transform: rotate(0deg);
  }
  50% {
    border-radius: 40% 60% 70% 30% / 50% 60% 30% 70%;
    transform: rotate(180deg);
  }
}

/* Animation NeonPulse */
.loadingSpinner.neonPulse {
  border-radius: 50%;
  border: 6px solid #0ff;
  box-shadow:
    0 0 10px #0ff,
    0 0 20px #0ff,
    0 0 30px #0ff,
    0 0 40px #0ff;
  animation: neonGlow 1.5s ease-in-out infinite alternate;
}

@keyframes neonGlow {
  0% {
    box-shadow:
      0 0 5px #0ff,
      0 0 10px #0ff,
      0 0 15px #0ff,
      0 0 20px #0ff;
    transform: scale(1);
  }
  100% {
    box-shadow:
      0 0 20px #0ff,
      0 0 40px #0ff,
      0 0 60px #0ff,
      0 0 80px #0ff;
    transform: scale(1.1);
  }
}

/* Animation GalaxySwirl */
.loadingSpinner.galaxySwirl {
  position: absolute!important;
  margin: 40px auto;
  border-radius: 50%;
  overflow: hidden;
}

.loadingSpinner.galaxySwirl .star {
  position: absolute;
  width: 6px;
  height: 6px;
  background: #fff;
  border-radius: 50%;
  animation: orbit 3s linear infinite;
  box-shadow: 0 0 6px #0ff;
}

@keyframes orbit {
  0% {
    transform: rotate(0deg) translateX(40px) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: rotate(360deg) translateX(40px) rotate(-360deg);
    opacity: 0;
  }
}

/* Animation VortexPulse */
.loadingSpinner.vortexPulse {
  position: fixed!important;
  width: 100px!important;
  height: 100px!important;
  border-radius: 50%;
  background: conic-gradient(from 0deg, #0ff, #00f, #0ff);
  animation: spin 2s linear infinite, pulseGlow 1.5s ease-in-out infinite;
  box-shadow: 0 0 20px rgba(0, 255, 255, 0.7);
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@keyframes pulseGlow {
  0%, 100% {
    box-shadow: 0 0 20px rgba(0, 255, 255, 0.7);
    transform: scale(1);
  }
  50% {
    box-shadow: 0 0 50px rgba(0, 255, 255, 1);
    transform: scale(1.1);
  }
}

.loadingSpinner.floatingOrbs {
  position: absolute!important;
  width: 160px!important;
  height: 160px!important;
  margin: 40px auto;
  background: transparent;
}

.floatingOrbs .orb {
  position: absolute;
  border-radius: 50%;
  opacity: 0.6;
  background: radial-gradient(circle at 30% 30%, #00ffff, #0088ff);
  animation: floatBlob 6s ease-in-out infinite;
  mix-blend-mode: screen;
  filter: blur(6px);
}

.floatingOrbs .orb:nth-child(1) {
  width: 60px;
  height: 60px;
  top: 20%;
  left: 10%;
  animation-delay: 0s;
}

.floatingOrbs .orb:nth-child(2) {
  width: 50px;
  height: 50px;
  top: 50%;
  left: 50%;
  animation-delay: 1.5s;
}

.floatingOrbs .orb:nth-child(3) {
  width: 70px;
  height: 70px;
  top: 30%;
  left: 60%;
  animation-delay: 3s;
}

@keyframes floatBlob {
  0%, 100% {
    transform: translateY(0px) translateX(0px) scale(1);
  }
  50% {
    transform: translateY(-20px) translateX(10px) scale(1.1);
  }
}

@keyframes impactBurst {
  0% {
    transform: scale(0.2);
    opacity: 1;
  }
  70% {
    transform: scale(1.5);
    opacity: 0.5;
  }
  100% {
    transform: scale(2.2);
    opacity: 0;
  }
}

.loadingSpinner.impactBurst {
  position: relative;
  width: 100px;
  height: 100px;
}

.impactBurst .burst-circle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 30px;
  height: 30px;
  background: radial-gradient(circle, #ff6ec4, #7873f5);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  animation: impactBurst 0.8s ease-out forwards;
}

/* Animation neuralPath */
@keyframes neuralPathLine {
  0% {
    stroke-dashoffset: 100;
    stroke: #000;
  }
  40% {
    stroke: #00f5ff;
  }
  100% {
    stroke-dashoffset: 0;
    stroke: #7a00ff;
  }
}

.loadingSpinner.neuralPath {
  width: 120px;
  height: 120px;
}

.neuralPath svg path {
  fill: none;
  stroke: #7a00ff;
  stroke-width: 2;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: neuralPathLine 1.5s ease-out forwards;
}

/* Equalizer animation */
.loadingSpinner[data-style="equalizer"] {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0; left: 0;
  background: transparent;
  z-index: 99999;
}

.loadingSpinner[data-style="equalizer"] div {
  width: 6px;
  height: 20px;
  background-color: var(--logo-primary-color, #00f);
  animation: equalizerPulse 1s infinite ease-in-out;
}

.loadingSpinner[data-style="equalizer"] div:nth-child(1) {
  animation-delay: 0s;
}
.loadingSpinner[data-style="equalizer"] div:nth-child(2) {
  animation-delay: 0.1s;
}
.loadingSpinner[data-style="equalizer"] div:nth-child(3) {
  animation-delay: 0.2s;
}
.loadingSpinner[data-style="equalizer"] div:nth-child(4) {
  animation-delay: 0.3s;
}
.loadingSpinner[data-style="equalizer"] div:nth-child(5) {
  animation-delay: 0.4s;
}

@keyframes equalizerPulse {
  0%, 100% {
    transform: scaleY(0.4);
  }
  50% {
    transform: scaleY(1.2);
  }
}

/* Cube Rotate animation */
.loadingSpinner[data-style="cubeRotate"] {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0; left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  z-index: 99999;
  perspective: 800px;
}

.loadingSpinner[data-style="cubeRotate"] div {
  width: 40px;
  height: 40px;
  background-color: var(--logo-primary-color, #00f);
  animation: cubeRotateAnim 1.2s infinite linear;
  transform-style: preserve-3d;
}

@keyframes cubeRotateAnim {
  0% {
    transform: rotateX(0deg) rotateY(0deg);
  }
  50% {
    transform: rotateX(180deg) rotateY(0deg);
  }
  100% {
    transform: rotateX(180deg) rotateY(180deg);
  }
}

/* Animation jeedomLogo */
#div_jeedomLoading[data-style="jeedomLogo"] .loadingSpinner {
  position: relative;
  left: calc(50% - 102px);
  border-radius: 16px;
  width: 205px;
  height: 90px;
  padding: 4px;
  background: rgba(255, 255, 255, 0.4);
  border-top: unset; 
  -webkit-animation: unset;
  animation: unset;
}
#div_jeedomLoading[data-style="jeedomLogo"] .loadingSpinner::before {
  content: "";
  position: absolute;
  border-radius: 16px;
  width: 82px;
  height: 82px;
  left: 0;
  background: #FFF;
  background: var(--logo-primary-color);
  background: no-repeat center / 100% url(../../core/img/jeedom_home_Light.png);
  -webkit-animation: push_loadingSpinner1 1s infinite ease-in-out;
  animation: push_loadingSpinnerJeedomLogo 1s infinite ease-in-out;
  border-top-color: unset;
  top: unset;
  bottom: unset;
  right: unset;
  border: unset;
}
#div_jeedomLoading[data-style="jeedomLogo"] .loadingSpinner::after {
  content: none;
}
@keyframes push_loadingSpinnerJeedomLogo {
  50% {
    left: 120px;
  }
}

/* Animation blueSpinner */
#div_jeedomLoading[data-style="blueSpinner"] .loadingSpinner {
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  border: solid 30px;
  border-radius: 5em;
  border-color: #0099ff transparent #0099ff transparent;
  animation: spin 1s linear infinite;
}
#div_jeedomLoading[data-style="blueSpinner"] .loadingSpinner::before {
 content: none;
}
#div_jeedomLoading[data-style="blueSpinner"] .loadingSpinner::after {
  content: none;
}

/* Animation ballsRotation */
#div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner {
  -webkit-animation: loading3rotate 1s infinite;
  animation: loading3rotate 1s infinite;
  height: 50px;
  width: 50px;
  border: none;
  border-radius: 0;
}
#div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner::before {
  -webkit-animation: loading3ball1 1s infinite;
  animation: loading3ball1 1s infinite;
  background-color: #cb2025;
  box-shadow: 30px 0 0 #f8b334;
  margin-bottom: 10px; 
}
#div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner::after {
  -webkit-animation: loading3ball2 1s infinite;
  animation: loading3ball2 1s infinite;
  background-color: #00a096;
  box-shadow: 30px 0 0 #97bf0d;
}
#div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner:before, #div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner:after {
  border-radius: 50%;
  content: '';
  display: block;
  height: 20px;
  width: 20px;
  position: relative;
  top: unset;
  bottom: unset;
  left: unset;
  right: unset;
  border: none;
}
@keyframes loading3rotate {
  0% {
    -webkit-transform: rotate(0deg) scale(0.8);
    -moz-transform: rotate(0deg) scale(0.8);
  }
  50% {
    -webkit-transform: rotate(360deg) scale(1.2);
    -moz-transform: rotate(360deg) scale(1.2);
  }
  100% {
    -webkit-transform: rotate(720deg) scale(0.8);
    -moz-transform: rotate(720deg) scale(0.8);
  }
}
@keyframes loading3ball1 {
  0% { box-shadow: 30px 0 0 #f8b334; }
  50% {
    box-shadow: 0 0 0 #f8b334; margin-bottom: 0;
    -webkit-transform: translate(15px, 15px);
    -moz-transform: translate(15px, 15px);
  }
  100% {
    box-shadow: 30px 0 0 #f8b334;
    margin-bottom: 10px;
  }
}
@keyframes loading3ball2 {
  0% { box-shadow: 30px 0 0 #97bf0d; }
  50% {
    box-shadow: 0 0 0 #97bf0d; margin-top: -20px;
    -webkit-transform: translate(15px, 15px);
    -moz-transform: translate(15px, 15px);
  }
  100% {
    box-shadow: 30px 0 0 #97bf0d;
    margin-top: 0;
  }
}

/* Animation jeedomHolo */
#div_jeedomLoading[data-style="jeedomHolo"] .loadingSpinner {
  position: absolute;
  --width: 80px;
  --height: 80px;
  margin: 40px auto;
  background-image: url('../../core/img/jeedom_home_Light.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  animation: jeedomHoloSpin 3s infinite linear;
  transform-style: preserve-3d;
  border-top-color: transparent;
}
#div_jeedomLoading[data-style="jeedomHolo"] .loadingSpinner::before {
 content: none;
}
#div_jeedomLoading[data-style="jeedomHolo"] .loadingSpinner::after {
  content: none;
}
@keyframes jeedomHoloSpin {
  0% {
    transform: rotateY(0deg) scale(1);
    --filter: drop-shadow(0 0 4px #00ff99);
    opacity: 1;
  }
  50% {
    transform: rotateY(180deg) scale(1.1);
    --filter: drop-shadow(0 0 10px #00ff99);
    opacity: 0.7;
  }
  100% {
    transform: rotateY(360deg) scale(1);
    --filter: drop-shadow(0 0 4px #00ff99);
    opacity: 1;
  }
}

:four: Editer et ajouter le code suivant dans le fichier custom.js

custom.js
/* Gestion de l'animation d'attente de Jeedom */
/*

  - Première installation
  	- [custom.js] Préciser l'identifiant de la commande info de l'animation : const cmdId = 38087; // ID virtuel animation
  
  - Pour ajouter une animation d'attente à la liste :
    - [virtuel de sélection de l'animation] Ajouter le nom de l'animation dans la liste de la commande action
    - [custom.css] Ajouter le css lié à l'animation dans custom.css
    - [custom.js] Déclarer le nom de l'animation dans availableStyles
    - [custom.js] (facultatif) Déclarer le template html si nécessaire : const nomAnimationHTML = `XXX`;
    
*/

(function () {
  const cmdId = 38087; // ID virtuel animation
  const displayTimeout = 3000; // ms d'affichage animation avec showLoadingAnimation
	
  // Liste des styles supportés
  const availableStyles = [
    'spirale',
    'googleBounce',
    'dotsOrbit',
    'appleRing',
    'energyBurst',
    'feu',
    'plasma',
    'glitch',
    'aurora',
    'rubberBall',
    'liquidDrop',
    'neonPulse',
    'galaxySwirl',
    'vortexPulse',
    'vortexNova',
    'floatingOrbs',
    'impactBurst',
    'neuralPath',
    'equalizer',
    'cubeRotate',
    'blueSpinner',
    'jeedomLogo',
    'ballsRotation',
    'jeedomHolo'
  ];
  
  // Animation par défaut si animation sélectionnée non trouvée
  const defaultStyle = 'spirale';
  
  const animationTemplates = {
    genericLoading: `<div class="loadingSpinner"></div>`,
    googleBounce: `
      <div class="loadingSpinner">
        <div></div><div></div><div></div><div></div>
      </div>`,
    dotsOrbitHTML: `
      <div class="loadingSpinner">
        <div></div><div></div><div></div><div></div><div></div><div></div>
      </div>`,
    rubberBall: `<div class="loadingSpinner rubberBall"></div>`,
    liquidDrop: `<div class="loadingSpinner liquidDrop"><div></div></div>`,
    neonPulse: `<div class="loadingSpinner neonPulse"></div>`,
    galaxySwirl: `
      <div class="loadingSpinner galaxySwirl">
        <div class="star" style="animation-delay: 0s;"></div>
        <div class="star" style="animation-delay: 0.3s;"></div>
        <div class="star" style="animation-delay: 0.6s;"></div>
        <div class="star" style="animation-delay: 0.9s;"></div>
        <div class="star" style="animation-delay: 1.2s;"></div>
        <div class="star" style="animation-delay: 1.5s;"></div>
      </div>`,
    vortexPulse: `
      <div class="loadingSpinner vortexPulse"></div>`,
    vortexNova: `
      <div class="loadingSpinner vortexNova">
        <div class="particle"></div>
        <div class="particle"></div>
        <div class="particle"></div>
        <div class="particle"></div>
      </div>`,
    floatingOrbs: `
      <div class="loadingSpinner floatingOrbs">
        <div class="orb"></div>
        <div class="orb"></div>
        <div class="orb"></div>
      </div>`,
    impactBurst: `
      <div class="loadingSpinner impactBurst">
        <div class="burst-circle"></div>
      </div>`,
    neuralPath: `
      <div class="loadingSpinner neuralPath">
        <svg viewBox="0 0 120 120">
          <path d="M10,60 C20,20 100,100 110,60" />
          <path d="M20,80 C40,40 80,80 100,40" />
          <path d="M30,90 C60,20 70,100 90,30" />
        </svg>
      </div>`,
    equalizer: `
      <div class="loadingSpinner" data-style="equalizer">
        <div></div><div></div><div></div><div></div><div></div>
      </div>`,
    cubeRotate: `
      <div class="loadingSpinner" data-style="cubeRotate">
        <div></div>
      </div>`,
  }
  
  function setInnerHTML(el, html) {
    el.innerHTML = html;
    return el;
  }

  function setAnimationStyle(style) {
    const div = document.getElementById('div_jeedomLoading');
    if (!div) return console.warn('#div_jeedomLoading non trouvée');

    style = style.trim();
    div.setAttribute('data-style', style);

    const html = animationTemplates[style];
    const className = '.' + style;

    if (!html) {
      div.innerHTML = animationTemplates['genericLoading'];
      return;
    }

    // Vérifie si l'animation demandée est déjà en place
    const existing = div.querySelector(className);
    if (!existing) {
      div.innerHTML = html;
      console.log("Animation chargement définie sur :", style);
    }
  }

  window.setAnimationStyle = setAnimationStyle;

  var overrideTimeout = null;

  window.showLoadingAnimation = function (style) {
    console.log('showLoadingAnimation..');
    const divLoading = document.getElementById('div_jeedomLoading');
    if (divLoading) divLoading.style.display = 'block';

    if (style && availableStyles.includes(style)) {
      setAnimationStyle(style);

      // Restaurer ensuite le style réel depuis le virtuel
      if (overrideTimeout) clearTimeout(overrideTimeout);
      overrideTimeout = setTimeout(() => {
        jeedom.cmd.execute({
          id: cmdId,
          success: function (valeur) {
            const newStyle = availableStyles.includes(valeur.trim()) ? valeur.trim() : defaultStyle;
            setAnimationStyle(newStyle);
          },
          error: function () {
            setAnimationStyle(defaultStyle);
          }
        });
      }, displayTimeout);
    } else {
      // Appel sans argument : on lit la valeur actuelle du virtuel
      jeedom.cmd.execute({
        id: cmdId,
        success: function (valeur) {
          const newStyle = availableStyles.includes(valeur.trim()) ? valeur.trim() : defaultStyle;
          setAnimationStyle(newStyle);
        },
        error: function () {
          setAnimationStyle(defaultStyle);
        }
      });
    }
  };

  
  window.hideLoadingAnimation = function () {
  	const divLoading = document.getElementById('div_jeedomLoading');
    if (divLoading) divLoading.style.display = 'none';
    console.log('Animation chargement masquée');
  };

  // Liste les styles disponibles
  window.getAvailableStyles = function () {
    return [...availableStyles];
  };

  // Partie Jeedom : récupération et écoute du virtuel
  if (typeof jeedom !== 'undefined' && jeedom.cmd) {
    jeedom.cmd.execute({
      id: cmdId,
      success: function (valeur) {
        showLoadingAnimation(valeur);
      },
    });

    if (typeof jeedom.cmd.update !== 'object') {
      jeedom.cmd.update = {};
    }
    jeedom.cmd.update[cmdId] = function (_options) {
      if (_options && _options.display_value) {
        //showLoadingAnimation(_options.display_value);
        setAnimationStyle(_options.display_value);
      }
    };
  } else {
    console.warn('Objet jeedom.cmd non disponible');
  }
})();

Modifier la 2eme ligne avec l’ID de votre commande info animation du virtuel créé précédemment.

const cmdId = 38087; // ID virtuel animation

:five: Il suffit ensuite de sélectionner l’animation depuis la liste du virtuel :arrow_right: L’animation d’attente Jeedom sera alors celle sélectionnée pour toute la navigation Jeedom.

:information_source: Il est possible de tester une animation à tout moment depuis le debugger du navigateur (Touche F12) avec la commande suivante depuis la console de debug avec la fonction showLoadingAnimation('nomDeLAnimation') :
image

10 « J'aime »

Hello @noodom ,

Merci pour ce partage de code.

Voici mon retour :

JS

le jeedom.cmd.update[cmdId] ne marche qu’une seule fois, car une fois qu’on change de pièce (via loadPage) le core supprime tout les cmd.update (jeedom.cmd.resetUpdateFunction):

C’est qu’un détail car un refresh de la page est suffisant.

CSS

Sur les animations appleRing (L97) et energyBurst (L158), la position relative affecte l’emplacement de celles-ci (montent et descendent en fonction du chargement des tuiles sur le dashboard), et on perd la transparence, j’ai donc commenté les position: relative; des animations.

Divers

Dans la liste que tu partage, il y a cubeRotate|cubeRotate, mais n’existe pas dans le css et availableStyles

Question

Sur certaines animations, le visu du loading par défaut du core est toujours visible, est-ce voulu ? Exemple sur vortexPulse :

image


J’avais aussi partagé des animations, mais sans aller jusqu’a changer celle-ci via une commande :wink:

https://phpvarious.github.io/documentation/widget/fr_FR/customcss4_4/#Supprime%20l’animation%20(loading)%20lors%20du%20chargement%20d’une%20page%20%3A

1 « J'aime »

Merci pour ton retour, toujours constructif ! :slight_smile:

Tu peux détailler le scénario car je ne reproduis pas : l’animation est bien conservée dans mes différents tests (rapides) de navigation.
Et sinon, l’animation est prise en compte automatiquement après la sélection sans refresh, même sur un onglet ouvert à côté.

OK, j’avais passé en revue les animations pour corriger ce problème. Ces 2 animations sont passées au travers :slight_smile: J’ai mis absolute comme sur les autres, à voir si le retirer suffit (pas testé).

En effet, il avait disparu : je l’ai remis et j’en ai profité pour en ajouter du coup.

Alors, oui, c’est volontaire car je trouvais que ça manquait d’animation sur certains. Mais non, ce n’est pas définitif car j’ai pas d’avis arrêté. A voir par la suite pour en retirer ou pas (voire ajouter une commande pour le mettre en option). J’avais aussi pensé à des commandes pour le choix des couleurs de ces animations d’origine.

Du coup, je me suis permis de les ajouter dans la liste si ça ne t’embête pas :wink:

J’avais aussi prévu une animation avec le logo Jeedom, c’est chose faite avec une nouvelle animation : jeedomHolo !

jeedomHolo

Sinon, j’en ai profité pour revoir le code (mise à jour dispos dans premier post avant mise sous Github) et améliorer la possibilité d’ajouter ses propres animations :

  • [virtuel de sélection de l’animation] Ajouter le nom de l’animation dans la liste de la commande action
  • [custom.css] Ajouter le css lié à l’animation dans custom.css
  • [custom.js] Déclarer le nom de l’animation dans availableStyles
  • [custom.js] (facultatif) Déclarer le template html si nécessaire : const nomAnimationHTML = XXX;

Merci !

Deb 11 - 4.4.19

Je part de 2 onglets (fenêtres) différents :

  • 1 onglet (A) ou j’ai le virtuel de sélection (sélection = appleRing).
  • 1 onglet (B) sur ma page par défaut du dashboard. (click logo Jeedom).

Avant tout, j’ai ajouter un console.log('jeedom.cmd.update[' + cmdId + ']') dans la fonction pour debug.

Je refresh les 2 onglets pour partir d’un log vierge.

Dans l’onglet (B), J’ai bien le log showLoadingAnimation.. qui confirme bien l’initialisation de code.
Dans l’onglet (A) je change la selection → googleBounce.
L’onglet B → log = Animation chargement définie sur : googleBounce ainsi que mon jeedom.cmd.update
Donc jusqu’ici tout est OK, et je confirme que l’animation est bien celle attendue.
Maintenant dans mon onglet (B), je change de page vers Santé par exemple.
Dans l’onglet (A) je change la selection → spirale.

Dans l’onglet B → rien, pas de log et l’animation n’a pas été remplacée.


Comme indiqué dans mon message précédent, lors de la navigation entre page le core utilise la fonction loadPage, dans celle-ci est fait un jeedom.cmd.resetUpdateFunction() qui vient reset tous les cmd.update.


Ca marche, c’était juste pour confirmer que c’était pas un oubli :+1:

Tu as bien fait, même si il ne sont pas d’aussi bonne qualité que les tiens :wink:

ça va trop loin, cette histoire :fireworks: :sweat_smile:

custom.css
/* ---------- Animation générique (exemple de spinner simple) ---------- */
#div_jeedomLoading[data-style="spirale"] {
  background-color: transparent;
}
#div_jeedomLoading[data-style="spirale"] .loadingSpinner {
  position: relative;
}
#div_jeedomLoading[data-style="spirale"] .loadingSpinner::before {
  content: "";
  position: absolute;
  border: 6px solid var(--al-info-color);
  border-top-color: transparent;
  border-radius: 50%;
  width: 100%;
  height: 100%;
  animation: spin 1s linear infinite;
}

/* ---------- Animation "googleBounce" ---------- */
#div_jeedomLoading[data-style="googleBounce"] {
  background-color: transparent;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  width: 100vw;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 9999;
}

#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner {
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
}

#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div {
  position: absolute;
  width: 20%;
  height: 20%;
  border-radius: 50%;
  background-color: var(--logo-primary-color);
  animation: bounce 1.5s infinite ease-in-out;
}

#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div:nth-child(1) {
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  animation-delay: 0s;
  background-color: #4285F4; /* bleu Google */
}
#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div:nth-child(2) {
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  animation-delay: 0.3s;
  background-color: #EA4335; /* rouge Google */
}
#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div:nth-child(3) {
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  animation-delay: 0.6s;
  background-color: #FBBC05; /* jaune Google */
}
#div_jeedomLoading[data-style="googleBounce"] .loadingSpinner div:nth-child(4) {
  top: 50%;
  left: 0;
  transform: translateY(-50%);
  animation-delay: 0.9s;
  background-color: #34A853; /* vert Google */
}
#div_jeedomLoading[data-style="googleBounce"]  .loadingSpinner,
#div_jeedomLoading[data-style="googleBounce"]  .loadingSpinner::before,
#div_jeedomLoading[data-style="googleBounce"]  .loadingSpinner::after {
    border-top-color: transparent;
}
@keyframes bounce {
  0%, 100% {
    transform: scale(1);
    opacity: 0.7;
  }
  50% {
    transform: scale(1.5);
    opacity: 1;
  }
}


/* ---------- Animation "appleRing" ---------- */
#div_jeedomLoading[data-style="appleRing"] {
  background-color: transparent;
  position: absolute;
}

#div_jeedomLoading[data-style="appleRing"] .loadingSpinner {
  border: 3px solid rgba(255, 255, 255, 0.2);
  border-top-color: var(--logo-primary-color);
  border-radius: 50%;
  animation: appleSpin 1.2s linear infinite;
  box-shadow:
    0 0 8px var(--logo-primary-color),
    inset 0 0 10px rgba(255, 255, 255, 0.4);
}

#div_jeedomLoading[data-style="appleRing"] .loadingSpinner::before {
  content: "";
  position: absolute;
  top: -15%;
  left: -15%;
  width: 130%;
  height: 130%;
  border-radius: 50%;
  box-shadow:
    0 0 12px var(--logo-primary-color),
    0 0 30px rgba(255, 255, 255, 0.6);
  opacity: 0.6;
  animation: pulseGlow 2.4s ease-in-out infinite alternate;
  pointer-events: none;
}

@keyframes appleSpin {
  0% {
    transform: rotate(0deg);
    border-top-color: var(--logo-primary-color);
  }
  50% {
    border-top-color: rgba(255, 255, 255, 0.8);
  }
  100% {
    transform: rotate(360deg);
    border-top-color: var(--logo-primary-color);
  }
}

@keyframes pulseGlow {
  0% {
    opacity: 0.4;
    box-shadow:
      0 0 10px var(--logo-primary-color),
      0 0 20px rgba(255, 255, 255, 0.3);
  }
  100% {
    opacity: 0.8;
    box-shadow:
      0 0 25px var(--logo-primary-color),
      0 0 40px rgba(255, 255, 255, 0.6);
  }
}

/* ---------- Animation "energyBurst" (pulsation) ---------- */
#div_jeedomLoading[data-style="energyBurst"] {
  background-color: transparent;
  position: absolute;
}

#div_jeedomLoading[data-style="energyBurst"] .loadingSpinner {
  border-radius: 50%;
  position: relative;
  box-shadow:
    0 0 15px 5px var(--al-warning-color),
    inset 0 0 20px 8px var(--al-info-color);
  animation: pulseScale 2.5s ease-in-out infinite, spinLinear 3s linear infinite;
  background: radial-gradient(circle at center, var(--al-warning-color), transparent 70%);
  overflow: visible;
}

#div_jeedomLoading[data-style="energyBurst"] .loadingSpinner::before,
#div_jeedomLoading[data-style="energyBurst"] .loadingSpinner::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  width: 14vh;
  height: 14vh;
  transform: translate(-50%, -50%);
  box-shadow:
    0 -10px 10px var(--al-danger-color),
    10px 0 10px var(--al-danger-color),
    0 10px 10px var(--al-danger-color),
    -10px 0 10px var(--al-danger-color);
  animation: flicker 1.5s infinite alternate;
  filter: drop-shadow(0 0 8px var(--al-danger-color));
  opacity: 0.7;
  mix-blend-mode: screen;
}

#div_jeedomLoading[data-style="energyBurst"] .loadingSpinner::after {
  width: 16vh;
  height: 16vh;
  animation-delay: 0.75s;
  opacity: 0.4;
  filter: drop-shadow(0 0 12px var(--al-danger-color));
}

@keyframes pulseScale {
  0%, 100% {
    transform: scale(1);
    box-shadow:
      0 0 15px 5px var(--al-warning-color),
      inset 0 0 20px 8px var(--al-info-color);
  }
  50% {
    transform: scale(1.15);
    box-shadow:
      0 0 30px 10px var(--al-danger-color),
      inset 0 0 40px 12px var(--al-danger-color);
  }
}

@keyframes flicker {
  0% {
    opacity: 0.4;
    filter: drop-shadow(0 0 6px var(--al-danger-color));
  }
  100% {
    opacity: 1;
    filter: drop-shadow(0 0 14px var(--al-danger-color));
  }
}

/* ---------- Animation "feu" (pulsation) ---------- */
#div_jeedomLoading[data-style="feu"] {
  background-color: transparent;
}
#div_jeedomLoading[data-style="feu"] .loadingSpinner {
  border-radius: 50%;
  background: radial-gradient(circle, orange, red);
  animation: pulse 1s ease-in-out infinite, spinLinear 3s linear infinite;
}

/* ---------- Animation "plasma" (électrique) ---------- */
#div_jeedomLoading[data-style="plasma"] {
  background-color: transparent;
}
#div_jeedomLoading[data-style="plasma"] .loadingSpinner {
  position: relative;
}
#div_jeedomLoading[data-style="plasma"] .loadingSpinner::before {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  background: repeating-conic-gradient(#00f, #0ff, #00f 20%);
  border-radius: 50%;
  animation: plasma 2s linear infinite;
}

/* ---------- Animation "glitch" (techno glitch) ---------- */
#div_jeedomLoading[data-style="glitch"] .loadingSpinner {
  position: relative;
  top: 40%;
  left: 50%;
  transform: translateX(-50%);
  background-color: transparent;
  box-shadow:
    0 0 2px var(--logo-primary-color),
    inset 0 0 10px var(--logo-primary-color);
  animation: glitchGlow 2s infinite, spinLinear 3s linear infinite;
  overflow: hidden;
}
#div_jeedomLoading[data-style="glitch"] .loadingSpinner::before,
#div_jeedomLoading[data-style="glitch"] .loadingSpinner::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  border: 2px dashed var(--al-info-color);
  border-radius: 2px;
  opacity: 0.6;
  animation: circuitFlow 4s linear infinite;
  mix-blend-mode: lighten;
  filter: drop-shadow(0 0 5px var(--al-warning-color));
}
#div_jeedomLoading[data-style="glitch"] .loadingSpinner::after {
  animation-direction: reverse;
  opacity: 0.3;
  filter: drop-shadow(0 0 10px var(--al-success-color));
}


/* ---------- Animation "aurora" (aura lumineuse) ---------- */
#div_jeedomLoading[data-style="aurora"] {
  background-color: rgba(10, 10, 10, 0.85);
}
#div_jeedomLoading[data-style="aurora"] .loadingSpinner {
  position: relative;
  top: 40%;
  left: 50%;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(circle at center, rgba(255, 255, 255, 0.1), transparent 70%);
  box-shadow: 0 0 40px rgba(255, 255, 255, 0.2);
  animation: rotatePulse 6s linear infinite;
  overflow: visible;
}
#div_jeedomLoading[data-style="aurora"] .loadingSpinner::before,
#div_jeedomLoading[data-style="aurora"] .loadingSpinner::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: conic-gradient(from 0deg, var(--logo-primary-color), var(--al-warning-color), var(--logo-primary-color));
  animation: auroraSpin 3s ease-in-out infinite alternate;
  opacity: 0.4;
  filter: blur(8px);
  mix-blend-mode: screen;
}
#div_jeedomLoading[data-style="aurora"] .loadingSpinner::after {
  animation-delay: 1.5s;
  opacity: 0.2;
  filter: blur(12px);
}

/* ---------- Animation "dotsOrbit" (points en orbite) ---------- */
#div_jeedomLoading[data-style="dotsOrbit"] {
  background-color: transparent;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner {
  position: relative;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div {
  position: absolute;
  width: 20%;
  height: 20%;
  background: var(--al-info-color);
  border-radius: 50%;
  opacity: 0.3;
  animation: dotFade 1.2s linear infinite;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(1) {
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  animation-delay: 0s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(2) {
  top: 20%;
  right: 0;
  animation-delay: 0.15s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(3) {
  bottom: 20%;
  right: 0;
  animation-delay: 0.3s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(4) {
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  animation-delay: 0.45s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(5) {
  bottom: 20%;
  left: 0;
  animation-delay: 0.6s;
}
#div_jeedomLoading[data-style="dotsOrbit"] .loadingSpinner div:nth-child(6) {
  top: 20%;
  left: 0;
  animation-delay: 0.75s;
}

/* ---------- Keyframes ---------- */
@keyframes spin {
  0% { transform: rotate(0); }
  100% { transform: rotate(360deg); }
}
@keyframes pulse {
  0% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.2); opacity: 0.5; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes plasma {
  0% { transform: rotate(0deg) scale(1); }
  50% { transform: rotate(180deg) scale(1.1); }
  100% { transform: rotate(360deg) scale(1); }
}
@keyframes glitchGlow {
  0%, 100% {
    box-shadow:
      0 0 2px var(--logo-primary-color),
      inset 0 0 10px var(--logo-primary-color);
  }
  50% {
    box-shadow:
      0 0 15px var(--al-danger-color),
      inset 0 0 20px var(--al-danger-color);
  }
}
@keyframes spinLinear {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
@keyframes circuitFlow {
  0% {
    transform: rotate(0deg) scale(1);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}
@keyframes rotatePulse {
  0% {
    transform: translateX(-50%) rotate(0deg) scale(0.95);
  }
  50% {
    transform: translateX(-50%) rotate(180deg) scale(1.05);
  }
  100% {
    transform: translateX(-50%) rotate(360deg) scale(0.95);
  }
}
@keyframes auroraSpin {
  0% {
    transform: rotate(0deg) scale(1);
  }
  100% {
    transform: rotate(360deg) scale(1.2);
  }
}
@keyframes dotFade {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 1; }
}

/* Animation rubberBall */
.loadingSpinner.rubberBall {
  width: 60px;
  height: 60px;
  margin: 40px auto;
  position: absolute!important;
}

.loadingSpinner.rubberBall::before {
  content: '';
  width: 60px;
  height: 60px;
  background: radial-gradient(circle at 30% 30%, #ff6b6b, #ff1e1e);
  border-radius: 50%;
  position: absolute;
  bottom: 0;
  animation: rubberBounce 1s infinite ease-in-out;
}

@keyframes rubberBounce {
  0%, 100% {
    transform: translateY(0) scaleX(1) scaleY(1);
  }
  30% {
    transform: translateY(-80px) scaleX(1.1) scaleY(0.9);
  }
  50% {
    transform: translateY(0) scaleX(0.9) scaleY(1.1);
  }
  70% {
    transform: translateY(-40px) scaleX(1.05) scaleY(0.95);
  }
}

/* Animation LiquidDrop */
.loadingSpinner.liquidDrop {
  --width: 80px;
  --height: 80px;
  margin: 40px auto!important;
  --position: relative!important;
  position: absolute!important;
}

.loadingSpinner.liquidDrop div {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, #00c9ff, #92fe9d);
  animation: liquidMorph 2s infinite ease-in-out;
  filter: blur(1px);
}

@keyframes liquidMorph {
  0%, 100% {
    border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%;
    transform: rotate(0deg);
  }
  50% {
    border-radius: 40% 60% 70% 30% / 50% 60% 30% 70%;
    transform: rotate(180deg);
  }
}

/* Animation NeonPulse */
.loadingSpinner.neonPulse {
  border-radius: 50%;
  border: 6px solid #0ff;
  box-shadow:
    0 0 10px #0ff,
    0 0 20px #0ff,
    0 0 30px #0ff,
    0 0 40px #0ff;
  animation: neonGlow 1.5s ease-in-out infinite alternate;
}

@keyframes neonGlow {
  0% {
    box-shadow:
      0 0 5px #0ff,
      0 0 10px #0ff,
      0 0 15px #0ff,
      0 0 20px #0ff;
    transform: scale(1);
  }
  100% {
    box-shadow:
      0 0 20px #0ff,
      0 0 40px #0ff,
      0 0 60px #0ff,
      0 0 80px #0ff;
    transform: scale(1.1);
  }
}

/* Animation GalaxySwirl */
.loadingSpinner.galaxySwirl {
  position: absolute!important;
  margin: 40px auto;
  border-radius: 50%;
  overflow: hidden;
}

.loadingSpinner.galaxySwirl .star {
  position: absolute;
  width: 6px;
  height: 6px;
  background: #fff;
  border-radius: 50%;
  animation: orbit 3s linear infinite;
  box-shadow: 0 0 6px #0ff;
}

@keyframes orbit {
  0% {
    transform: rotate(0deg) translateX(40px) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: rotate(360deg) translateX(40px) rotate(-360deg);
    opacity: 0;
  }
}

/* Animation VortexPulse */
.loadingSpinner.vortexPulse {
  position: fixed!important;
  width: 100px!important;
  height: 100px!important;
  border-radius: 50%;
  background: conic-gradient(from 0deg, #0ff, #00f, #0ff);
  animation: spin 2s linear infinite, pulseGlow 1.5s ease-in-out infinite;
  box-shadow: 0 0 20px rgba(0, 255, 255, 0.7);
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@keyframes pulseGlow {
  0%, 100% {
    box-shadow: 0 0 20px rgba(0, 255, 255, 0.7);
    transform: scale(1);
  }
  50% {
    box-shadow: 0 0 50px rgba(0, 255, 255, 1);
    transform: scale(1.1);
  }
}

.loadingSpinner.floatingOrbs {
  position: absolute!important;
  width: 160px!important;
  height: 160px!important;
  margin: 40px auto;
  background: transparent;
}

.floatingOrbs .orb {
  position: absolute;
  border-radius: 50%;
  opacity: 0.6;
  background: radial-gradient(circle at 30% 30%, #00ffff, #0088ff);
  animation: floatBlob 6s ease-in-out infinite;
  mix-blend-mode: screen;
  filter: blur(6px);
}

.floatingOrbs .orb:nth-child(1) {
  width: 60px;
  height: 60px;
  top: 20%;
  left: 10%;
  animation-delay: 0s;
}

.floatingOrbs .orb:nth-child(2) {
  width: 50px;
  height: 50px;
  top: 50%;
  left: 50%;
  animation-delay: 1.5s;
}

.floatingOrbs .orb:nth-child(3) {
  width: 70px;
  height: 70px;
  top: 30%;
  left: 60%;
  animation-delay: 3s;
}

@keyframes floatBlob {
  0%, 100% {
    transform: translateY(0px) translateX(0px) scale(1);
  }
  50% {
    transform: translateY(-20px) translateX(10px) scale(1.1);
  }
}

@keyframes impactBurst {
  0% {
    transform: scale(0.2);
    opacity: 1;
  }
  70% {
    transform: scale(1.5);
    opacity: 0.5;
  }
  100% {
    transform: scale(2.2);
    opacity: 0;
  }
}

.loadingSpinner.impactBurst {
  position: relative;
  width: 100px;
  height: 100px;
}

.impactBurst .burst-circle {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 30px;
  height: 30px;
  background: radial-gradient(circle, #ff6ec4, #7873f5);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  animation: impactBurst 0.8s ease-out forwards;
}

/* Animation neuralPath */
@keyframes neuralPathLine {
  0% {
    stroke-dashoffset: 100;
    stroke: #000;
  }
  40% {
    stroke: #00f5ff;
  }
  100% {
    stroke-dashoffset: 0;
    stroke: #7a00ff;
  }
}

.loadingSpinner.neuralPath {
  width: 120px;
  height: 120px;
}

.neuralPath svg path {
  fill: none;
  stroke: #7a00ff;
  stroke-width: 2;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  animation: neuralPathLine 1.5s ease-out forwards;
}

/* Equalizer animation */
.loadingSpinner[data-style="equalizer"] {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0; left: 0;
  background: transparent;
  z-index: 99999;
}

.loadingSpinner[data-style="equalizer"] div {
  width: 6px;
  height: 20px;
  background-color: var(--logo-primary-color, #00f);
  animation: equalizerPulse 1s infinite ease-in-out;
}

.loadingSpinner[data-style="equalizer"] div:nth-child(1) {
  animation-delay: 0s;
}
.loadingSpinner[data-style="equalizer"] div:nth-child(2) {
  animation-delay: 0.1s;
}
.loadingSpinner[data-style="equalizer"] div:nth-child(3) {
  animation-delay: 0.2s;
}
.loadingSpinner[data-style="equalizer"] div:nth-child(4) {
  animation-delay: 0.3s;
}
.loadingSpinner[data-style="equalizer"] div:nth-child(5) {
  animation-delay: 0.4s;
}

@keyframes equalizerPulse {
  0%, 100% {
    transform: scaleY(0.4);
  }
  50% {
    transform: scaleY(1.2);
  }
}

/* Cube Rotate animation */
.loadingSpinner[data-style="cubeRotate"] {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0; left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  z-index: 99999;
  perspective: 800px;
}

.loadingSpinner[data-style="cubeRotate"] div {
  width: 40px;
  height: 40px;
  background-color: var(--logo-primary-color, #00f);
  animation: cubeRotateAnim 1.2s infinite linear;
  transform-style: preserve-3d;
}

@keyframes cubeRotateAnim {
  0% {
    transform: rotateX(0deg) rotateY(0deg);
  }
  50% {
    transform: rotateX(180deg) rotateY(0deg);
  }
  100% {
    transform: rotateX(180deg) rotateY(180deg);
  }
}

/* Animation jeedomLogo */
#div_jeedomLoading[data-style="jeedomLogo"] .loadingSpinner {
  position: relative;
  left: calc(50% - 102px);
  border-radius: 16px;
  width: 205px;
  height: 90px;
  padding: 4px;
  background: rgba(255, 255, 255, 0.4);
  border-top: unset; 
  -webkit-animation: unset;
  animation: unset;
}
#div_jeedomLoading[data-style="jeedomLogo"] .loadingSpinner::before {
  content: "";
  position: absolute;
  border-radius: 16px;
  width: 82px;
  height: 82px;
  left: 0;
  background: #FFF;
  background: var(--logo-primary-color);
  background: no-repeat center / 100% url(../../core/img/jeedom_home_Light.png);
  -webkit-animation: push_loadingSpinner1 1s infinite ease-in-out;
  animation: push_loadingSpinnerJeedomLogo 1s infinite ease-in-out;
  border-top-color: unset;
  top: unset;
  bottom: unset;
  right: unset;
  border: unset;
}
#div_jeedomLoading[data-style="jeedomLogo"] .loadingSpinner::after {
  content: none;
}
@keyframes push_loadingSpinnerJeedomLogo {
  50% {
    left: 120px;
  }
}

/* Animation blueSpinner */
#div_jeedomLoading[data-style="blueSpinner"] .loadingSpinner {
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  border: solid 30px;
  border-radius: 5em;
  border-color: #0099ff transparent #0099ff transparent;
  animation: spin 1s linear infinite;
}
#div_jeedomLoading[data-style="blueSpinner"] .loadingSpinner::before {
 content: none;
}
#div_jeedomLoading[data-style="blueSpinner"] .loadingSpinner::after {
  content: none;
}

/* Animation ballsRotation */
#div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner {
  -webkit-animation: loading3rotate 1s infinite;
  animation: loading3rotate 1s infinite;
  height: 50px;
  width: 50px;
  border: none;
  border-radius: 0;
}
#div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner::before {
  -webkit-animation: loading3ball1 1s infinite;
  animation: loading3ball1 1s infinite;
  background-color: #cb2025;
  box-shadow: 30px 0 0 #f8b334;
  margin-bottom: 10px; 
}
#div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner::after {
  -webkit-animation: loading3ball2 1s infinite;
  animation: loading3ball2 1s infinite;
  background-color: #00a096;
  box-shadow: 30px 0 0 #97bf0d;
}
#div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner:before, #div_jeedomLoading[data-style="ballsRotation"] .loadingSpinner:after {
  border-radius: 50%;
  content: '';
  display: block;
  height: 20px;
  width: 20px;
  position: relative;
  top: unset;
  bottom: unset;
  left: unset;
  right: unset;
  border: none;
}
@keyframes loading3rotate {
  0% {
    -webkit-transform: rotate(0deg) scale(0.8);
    -moz-transform: rotate(0deg) scale(0.8);
  }
  50% {
    -webkit-transform: rotate(360deg) scale(1.2);
    -moz-transform: rotate(360deg) scale(1.2);
  }
  100% {
    -webkit-transform: rotate(720deg) scale(0.8);
    -moz-transform: rotate(720deg) scale(0.8);
  }
}
@keyframes loading3ball1 {
  0% { box-shadow: 30px 0 0 #f8b334; }
  50% {
    box-shadow: 0 0 0 #f8b334; margin-bottom: 0;
    -webkit-transform: translate(15px, 15px);
    -moz-transform: translate(15px, 15px);
  }
  100% {
    box-shadow: 30px 0 0 #f8b334;
    margin-bottom: 10px;
  }
}
@keyframes loading3ball2 {
  0% { box-shadow: 30px 0 0 #97bf0d; }
  50% {
    box-shadow: 0 0 0 #97bf0d; margin-top: -20px;
    -webkit-transform: translate(15px, 15px);
    -moz-transform: translate(15px, 15px);
  }
  100% {
    box-shadow: 30px 0 0 #97bf0d;
    margin-top: 0;
  }
}

/* Animation jeedomHolo */
#div_jeedomLoading[data-style="jeedomHolo"] .loadingSpinner {
  position: absolute;
  --width: 80px;
  --height: 80px;
  margin: 40px auto;
  background-image: url('../../core/img/jeedom_home_Light.png');
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  animation: jeedomHoloSpin 3s infinite linear;
  transform-style: preserve-3d;
  border-top-color: transparent;
}
#div_jeedomLoading[data-style="jeedomHolo"] .loadingSpinner::before {
 content: none;
}
#div_jeedomLoading[data-style="jeedomHolo"] .loadingSpinner::after {
  content: none;
}
@keyframes jeedomHoloSpin {
  0% {
    transform: rotateY(0deg) scale(1);
    --filter: drop-shadow(0 0 4px #00ff99);
    opacity: 1;
  }
  50% {
    transform: rotateY(180deg) scale(1.1);
    --filter: drop-shadow(0 0 10px #00ff99);
    opacity: 0.7;
  }
  100% {
    transform: rotateY(360deg) scale(1);
    --filter: drop-shadow(0 0 4px #00ff99);
    opacity: 1;
  }
}

/* Animation fireworks */
#div_jeedomLoading[data-style="fireworks"] .loadingSpinner {
  position: absolute;
  inset: 0;
  opacity:0.7;
  backdrop-filter: blur(1px);
  z-index: 9999;
  animation: unset;
  border-top-color: transparent;
}
#div_jeedomLoading[data-style="fireworks"] .loadingSpinner::before {
 content: none;
}
#div_jeedomLoading[data-style="fireworks"] .loadingSpinner::after {
  content: none;
}
#fireworksCanvas
  display: block;
  width: 100%;
  height: 100%;
}
custom.js
(function () {
  const cmdId = 38087; // ID du virtuel animation
  const displayTimeout = 3000;

  const availableStyles = [
    'spirale', 'googleBounce', 'dotsOrbit', 'appleRing',
    'energyBurst', 'feu', 'plasma', 'glitch', 'aurora',
    'rubberBall', 'liquidDrop', 'neonPulse', 'galaxySwirl',
    'vortexPulse', 'vortexNova', 'floatingOrbs', 'impactBurst',
    'neuralPath', 'equalizer', 'cubeRotate', 'blueSpinner',
    'jeedomLogo', 'ballsRotation', 'jeedomHolo', 'fireworks'
  ];

  const defaultStyle = 'spirale';

  const animationTemplates = {
    genericLoading: `<div class="loadingSpinner"></div>`,
    googleBounce: `
      <div class="loadingSpinner googleBounce">
        <div></div><div></div><div></div><div></div>
      </div>`,
    dotsOrbit: `
      <div class="loadingSpinner dotsOrbit">
        <div></div><div></div><div></div><div></div><div></div><div></div>
      </div>`,
    rubberBall: `<div class="loadingSpinner rubberBall"></div>`,
    liquidDrop: `<div class="loadingSpinner liquidDrop"><div></div></div>`,
    neonPulse: `<div class="loadingSpinner neonPulse"></div>`,
    galaxySwirl: `
      <div class="loadingSpinner galaxySwirl">
        <div class="star" style="animation-delay: 0s;"></div>
        <div class="star" style="animation-delay: 0.3s;"></div>
        <div class="star" style="animation-delay: 0.6s;"></div>
        <div class="star" style="animation-delay: 0.9s;"></div>
        <div class="star" style="animation-delay: 1.2s;"></div>
        <div class="star" style="animation-delay: 1.5s;"></div>
      </div>`,
    vortexPulse: `<div class="loadingSpinner vortexPulse"></div>`,
    vortexNova: `
      <div class="loadingSpinner vortexNova">
        <div class="particle"></div>
        <div class="particle"></div>
        <div class="particle"></div>
        <div class="particle"></div>
      </div>`,
    floatingOrbs: `
      <div class="loadingSpinner floatingOrbs">
        <div class="orb"></div>
        <div class="orb"></div>
        <div class="orb"></div>
      </div>`,
    impactBurst: `
      <div class="loadingSpinner impactBurst">
        <div class="burst-circle"></div>
      </div>`,
    neuralPath: `
      <div class="loadingSpinner neuralPath">
        <svg viewBox="0 0 120 120">
          <path d="M10,60 C20,20 100,100 110,60" />
          <path d="M20,80 C40,40 80,80 100,40" />
          <path d="M30,90 C60,20 70,100 90,30" />
        </svg>
      </div>`,
    equalizer: `
      <div class="loadingSpinner equalizer">
        <div></div><div></div><div></div><div></div><div></div>
      </div>`,
    cubeRotate: `
      <div class="loadingSpinner cubeRotate">
        <div></div>
      </div>`,
    fireworks: `
      <div class="loadingSpinner fireworks">
        <canvas id="fireworksCanvas"></canvas>
      </div>`
  };

  function setAnimationStyle(style) {
    const div = document.getElementById('div_jeedomLoading');
    if (!div) return console.warn('#div_jeedomLoading non trouvée');

    style = style.trim();
    div.setAttribute('data-style', style);

    const html = animationTemplates[style] || animationTemplates['genericLoading'];
    div.innerHTML = html;

    if (style === 'fireworks') {
      initFireworksCanvas();
    }

    console.log("Animation chargement définie sur :", style);
  }

  function initFireworksCanvas() {
    const canvas = document.getElementById("fireworksCanvas");
    if (!canvas) return;
    
    const ctx = canvas.getContext("2d");
    let particles = [];

    function resize() {
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
    }
    resize();
    window.addEventListener("resize", resize);

    function hexToRgb(hex) {
      const bigint = parseInt(hex.slice(1), 16);
      return [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255].join(",");
    }

    function createFirework() {
      const x = Math.random() * canvas.width;
      const y = Math.random() * canvas.height / 2;
      const colors = ['#ff4c4c', '#ffd700', '#4cffd0', '#3c7cff', '#ff3cc2', '#fff13c'];
      const color = colors[Math.floor(Math.random() * colors.length)];
      const count = 30 + Math.random() * 20;

      for (let i = 0; i < count; i++) {
        const angle = Math.random() * 2 * Math.PI;
        const speed = Math.random() * 4 + 1;
        particles.push({
          x,
          y,
          radius: Math.random() * 2 + 1,
          color,
          vx: Math.cos(angle) * speed,
          vy: Math.sin(angle) * speed,
          alpha: 1,
          decay: Math.random() * 0.02 + 0.01
        });
      }
    }

    function animate() {
      ctx.fillStyle = "rgba(0, 0, 0, 0.4)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      particles = particles.filter(p => {
        p.x += p.vx;
        p.y += p.vy;
        p.alpha -= p.decay;
        return p.alpha > 0;
      });

      for (const p of particles) {
        ctx.beginPath();
        ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI);
        ctx.fillStyle = `rgba(${hexToRgb(p.color)},${p.alpha})`;
        ctx.fill();
      }

      requestAnimationFrame(animate);
    }

    setInterval(createFirework, 700);
    animate();
  }

  window.setAnimationStyle = setAnimationStyle;

  let overrideTimeout = null;

  window.showLoadingAnimation = function (style) {
    const divLoading = document.getElementById('div_jeedomLoading');
    if (divLoading) divLoading.style.display = 'block';

    if (style && availableStyles.includes(style)) {
      setAnimationStyle(style);

      if (overrideTimeout) clearTimeout(overrideTimeout);
      overrideTimeout = setTimeout(() => {
        jeedom.cmd.execute({
          id: cmdId,
          success: function (val) {
            const newStyle = availableStyles.includes(val.trim()) ? val.trim() : defaultStyle;
            setAnimationStyle(newStyle);
          },
          error: function () {
            setAnimationStyle(defaultStyle);
          }
        });
      }, displayTimeout);
    } else {
      jeedom.cmd.execute({
        id: cmdId,
        success: function (val) {
          const newStyle = availableStyles.includes(val.trim()) ? val.trim() : defaultStyle;
          setAnimationStyle(newStyle);
        },
        error: function () {
          setAnimationStyle(defaultStyle);
        }
      });
    }
  };

  window.hideLoadingAnimation = function () {
    const divLoading = document.getElementById('div_jeedomLoading');
    if (divLoading) divLoading.style.display = 'none';
  };

  window.getAvailableStyles = function () {
    return [...availableStyles];
  };

  if (typeof jeedom !== 'undefined' && jeedom.cmd) {
    jeedom.cmd.execute({
      id: cmdId,
      success: function (val) {
        showLoadingAnimation(val);
      }
    });

    if (typeof jeedom.cmd.update !== 'object') {
      jeedom.cmd.update = {};
    }

    jeedom.cmd.update[cmdId] = function (_options) {
      if (_options && _options.display_value) {
        showLoadingAnimation(_options.display_value);
      }
    };
  } else {
    console.warn('Objet jeedom.cmd non disponible');
  }
})();

fireworks

Ajouter fireworks dans la liste du virtuel :
appleRing|appleRing;googleBounce|googleBounce;spirale|spirale;feu|feu;plasma|plasma;glitch|glitch;aurora|aurora;dotsOrbit|dotsOrbit;energyBurst|energyBurst;rubberBall|rubberBall;liquidDrop|liquidDrop;neonPulse|neonPulse;galaxySwirl|galaxySwirl;vortexPulse|vortexPulse;vortexNova|vortexNova;floatingOrbs|floatingOrbs;impactBurst|impactBurst;neuralPath|neuralPath;equalizer|equalizer;cubeRotate|cubeRotate;blueSpinner|blueSpinner;jeedomLogo|jeedomLogo;ballsRotation|ballsRotation;jeedomHolo|jeedomHolo;fireworks|fireworks

2 « J'aime »