From fc401ce35e9d3323de96b959d24693defc07de48 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Wed, 11 Mar 2026 15:17:00 +0100 Subject: [PATCH] loading animation --- docs/.vuepress/components/RoadmapProgress.vue | 138 +++++++++++++++++- 1 file changed, 130 insertions(+), 8 deletions(-) diff --git a/docs/.vuepress/components/RoadmapProgress.vue b/docs/.vuepress/components/RoadmapProgress.vue index a9f5063..cd12019 100644 --- a/docs/.vuepress/components/RoadmapProgress.vue +++ b/docs/.vuepress/components/RoadmapProgress.vue @@ -1,5 +1,5 @@ @@ -268,7 +277,7 @@ const connectorStyle = (index) => { min-height: 80px; } -/* === Verbindungslinie zwischen Stationen === */ +/* === Verbindungslinie === */ .roadmap-connector { position: absolute; left: 12px; @@ -277,6 +286,7 @@ const connectorStyle = (index) => { bottom: -28px; width: 3px; z-index: 1; + background: var(--conn-color, linear-gradient(to bottom, var(--conn-from), var(--conn-to))); } /* === Marker === */ @@ -397,6 +407,97 @@ strong.roadmap-content-title { text-decoration: underline; } +/* ========================================== + Animation: Punkte poppen auf, Linie zieht + ========================================== */ + +/* Vor der Animation: alles unsichtbar */ +.roadmap-station .roadmap-marker, +.roadmap-station .roadmap-content { + opacity: 0; + transform: scale(0.5); +} + +.roadmap-station .roadmap-connector { + transform: translateX(-50%) scaleY(0); + transform-origin: top center; +} + +/* Nach mounted: Animation starten */ +/* Timing pro Station: Marker poppt auf, Linie zieht, nächster Marker poppt */ +/* Station i: marker bei 0.3 + i*0.5s, connector bei 0.3 + i*0.5 + 0.15s */ + +.roadmap--animated .roadmap-station .roadmap-marker { + animation: markerPop 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards, + markerGlow 0.5s ease calc(0.3s + var(--i) * 0.5s) forwards; + animation-delay: calc(0.3s + var(--i) * 0.5s); +} + +/* Content fliegt mit dem Marker ein */ +.roadmap--animated .roadmap-station .roadmap-content { + animation: contentFadeIn 0.4s ease forwards; + animation-delay: calc(0.3s + var(--i) * 0.5s); +} + +/* Linie zieht sich nach unten */ +.roadmap--animated .roadmap-station .roadmap-connector { + animation: lineGrow 0.4s ease forwards; + animation-delay: calc(0.45s + var(--i) * 0.5s); +} + +@keyframes markerPop { + 0% { + opacity: 0; + transform: scale(0); + } + 60% { + opacity: 1; + transform: scale(1.3); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes markerGlow { + 0% { + box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.6); + } + 50% { + box-shadow: 0 0 16px 6px rgba(255, 255, 255, 0.4); + } + 100% { + box-shadow: none; + } +} + +@keyframes contentFadeIn { + 0% { + opacity: 0; + transform: translateX(-10px) scale(0.95); + } + 100% { + opacity: 1; + transform: translateX(0) scale(1); + } +} + +@keyframes lineGrow { + 0% { + transform: translateX(-50%) scaleY(0); + opacity: 0.5; + } + 100% { + transform: translateX(-50%) scaleY(1); + opacity: 1; + } +} + +/* Nach Animation: in-progress-Marker behält seinen box-shadow */ +.roadmap--animated .roadmap-marker--in-progress { + box-shadow: 0 0 0 5px rgba(99, 102, 241, 0.2); +} /* === Responsive === */ @media (max-width: 600px) { @@ -411,9 +512,30 @@ strong.roadmap-content-title { strong.roadmap-content-title { font-size: 1.05em; } +} - .roadmap-station--in-progress .roadmap-content { - padding-left: 4px; +/* Reduced motion: keine Animation */ +@media (prefers-reduced-motion: reduce) { + .roadmap-station .roadmap-marker, + .roadmap-station .roadmap-content { + opacity: 1; + transform: none; + } + + .roadmap-station .roadmap-connector { + transform: translateX(-50%) scaleY(1); + } + + .roadmap--animated .roadmap-station .roadmap-marker, + .roadmap--animated .roadmap-station .roadmap-content, + .roadmap--animated .roadmap-station .roadmap-connector { + animation: none; + opacity: 1; + transform: none; + } + + .roadmap--animated .roadmap-station .roadmap-connector { + transform: translateX(-50%); } }