diff --git a/server/src/wled_controller/static/css/base.css b/server/src/wled_controller/static/css/base.css index 43e936f..6f86db6 100644 --- a/server/src/wled_controller/static/css/base.css +++ b/server/src/wled_controller/static/css/base.css @@ -83,6 +83,89 @@ body.modal-open { width: 100%; } +/* ── Ambient animated background ── */ +#bg-anim-layer { + display: none; + position: fixed; + inset: 0; + z-index: -1; + pointer-events: none; + overflow: hidden; + background: var(--bg-color); +} + +[data-bg-anim="on"] #bg-anim-layer { + display: block; +} + +[data-bg-anim="on"] body { + background: transparent; +} + +#bg-anim-layer .bg-blob { + position: absolute; + border-radius: 50%; + filter: blur(80px); + will-change: transform; +} + +#bg-anim-layer .bg-blob-a { + width: 600px; + height: 400px; + top: 10%; + left: 10%; + background: var(--bg-anim-a); + animation: blobA 20s ease-in-out infinite alternate; +} + +#bg-anim-layer .bg-blob-b { + width: 500px; + height: 500px; + top: 40%; + right: 5%; + background: var(--bg-anim-b); + animation: blobB 25s ease-in-out infinite alternate; +} + +#bg-anim-layer .bg-blob-c { + width: 450px; + height: 550px; + bottom: 5%; + left: 30%; + background: var(--bg-anim-c); + animation: blobC 22s ease-in-out infinite alternate; +} + +[data-theme="dark"] { + --bg-anim-a: rgba(76, 175, 80, 0.10); + --bg-anim-b: rgba(33, 150, 243, 0.08); + --bg-anim-c: rgba(156, 39, 176, 0.07); +} + +[data-theme="light"] { + --bg-anim-a: rgba(76, 175, 80, 0.10); + --bg-anim-b: rgba(33, 150, 243, 0.08); + --bg-anim-c: rgba(156, 39, 176, 0.07); +} + +@keyframes blobA { + 0% { transform: translate(0, 0) scale(1); } + 50% { transform: translate(15vw, 10vh) scale(1.15); } + 100% { transform: translate(-5vw, 20vh) scale(0.9); } +} + +@keyframes blobB { + 0% { transform: translate(0, 0) scale(1); } + 50% { transform: translate(-20vw, -10vh) scale(1.1); } + 100% { transform: translate(5vw, 15vh) scale(0.95); } +} + +@keyframes blobC { + 0% { transform: translate(0, 0) scale(1); } + 50% { transform: translate(10vw, -15vh) scale(1.2); } + 100% { transform: translate(-10vw, -5vh) scale(0.85); } +} + .container { padding: 20px; } diff --git a/server/src/wled_controller/static/locales/en.json b/server/src/wled_controller/static/locales/en.json index 39cfa4e..55e2b29 100644 --- a/server/src/wled_controller/static/locales/en.json +++ b/server/src/wled_controller/static/locales/en.json @@ -5,6 +5,7 @@ "app.connection_lost": "Server unreachable", "app.connection_retrying": "Attempting to reconnect…", "theme.toggle": "Toggle theme", + "bg.anim.toggle": "Toggle ambient background", "accent.title": "Accent color", "accent.custom": "Custom", "accent.reset": "Reset", diff --git a/server/src/wled_controller/static/locales/ru.json b/server/src/wled_controller/static/locales/ru.json index 3357cba..8b3ae62 100644 --- a/server/src/wled_controller/static/locales/ru.json +++ b/server/src/wled_controller/static/locales/ru.json @@ -5,6 +5,7 @@ "app.connection_lost": "Сервер недоступен", "app.connection_retrying": "Попытка переподключения…", "theme.toggle": "Переключить тему", + "bg.anim.toggle": "Анимированный фон", "accent.title": "Цвет акцента", "accent.custom": "Свой", "accent.reset": "Сброс", diff --git a/server/src/wled_controller/static/locales/zh.json b/server/src/wled_controller/static/locales/zh.json index 4cef763..ff1ac91 100644 --- a/server/src/wled_controller/static/locales/zh.json +++ b/server/src/wled_controller/static/locales/zh.json @@ -5,6 +5,7 @@ "app.connection_lost": "服务器不可达", "app.connection_retrying": "正在尝试重新连接…", "theme.toggle": "切换主题", + "bg.anim.toggle": "切换动态背景", "accent.title": "主题色", "accent.custom": "自定义", "accent.reset": "重置", diff --git a/server/src/wled_controller/templates/index.html b/server/src/wled_controller/templates/index.html index d900ab3..55bea7b 100644 --- a/server/src/wled_controller/templates/index.html +++ b/server/src/wled_controller/templates/index.html @@ -29,6 +29,11 @@ +
+
+
+
+