[Archived] Archived WIP of vielle.dev

Add proper animations to popped balloons

- Balloons pop, cables and posts fall, and then balloons regrow and posts and cables rise
- focused balloons bounce/pulse
- cables change colours in night mode

Changed files
+102 -23
src
components
+102 -23
src/components/blog/Balloon.astro
··· 51 51 const maxtime = Number(el.dataset["maxTime"] ?? "0"); 52 52 53 53 el.addEventListener("click", () => { 54 + const cableParent = el.parentElement; 54 55 const postParent = el.parentElement?.parentElement; 56 + if (!cableParent) throw new Error("No parent 1 level up!!!"); 55 57 if (!postParent) throw new Error("No parent 2 levels up!!!"); 56 58 console.log("clicked! popping", el, "with post", postParent); 57 59 58 60 el.blur(); 59 61 60 - el.animate( 61 - [ 62 + Promise.all([ 63 + el.animate( 64 + { opacity: [1, 0] }, 65 + { 66 + duration: 100, 67 + fill: "forwards", 68 + } 69 + ).finished, 70 + 71 + cableParent.animate( 72 + [ 73 + {}, 74 + { 75 + height: 0, 76 + top: 0, 77 + }, 78 + ], 79 + { 80 + duration: 500, 81 + fill: "forwards", 82 + } 83 + ), 84 + 85 + postParent.animate( 86 + [ 87 + {}, 88 + { 89 + top: "calc(var(--x-offset-0) + 50rem)", 90 + }, 91 + ], 62 92 { 63 - opacity: 1, 93 + duration: 1000, 94 + easing: "ease-in-out", 95 + } 96 + ).finished, 97 + ]).then(() => { 98 + const duration = (mintime + Math.random() * (maxtime - mintime)) * 1000; 99 + 100 + el.animate( 101 + { 102 + opacity: [0, 1], 103 + scale: [0, 1], 104 + offset: [0, 1], 64 105 }, 65 106 { 66 - opacity: 0, 67 - }, 107 + duration, 108 + fill: "forwards", 109 + // easing: "ease-in", 110 + } 111 + ); 112 + 113 + cableParent.animate( 114 + [ 115 + { 116 + height: 0, 117 + top: 0, 118 + }, 119 + { 120 + height: "var(--length)", 121 + top: "calc(-1 * var(--length))", 122 + }, 123 + ], 68 124 { 69 - duration: 500, 70 - }, 71 - ], 72 - {} 73 - ).finished.then(() => 74 - el.animate( 125 + duration, 126 + fill: "forwards", 127 + } 128 + ); 129 + 130 + postParent.animate( 75 131 [ 76 - { opacity: 0, scale: 0 }, 77 - { opacity: 1, offset: 0.001 }, 78 - { scale: 1 }, 132 + { 133 + top: "calc(var(--x-offset-0) + 50rem)", 134 + }, 135 + {}, 79 136 ], 80 137 { 81 - duration: (mintime + Math.random() * (maxtime - mintime)) * 1000, 82 - easing: "ease-out", 138 + duration, 139 + fill: "forwards", 140 + easing: "ease-in", 83 141 } 84 - ) 85 - ); 142 + ); 143 + }); 86 144 }); 87 145 }); 88 146 </script> ··· 164 222 } 165 223 } 166 224 225 + @keyframes bouncing { 226 + from, 227 + to { 228 + scale: 1 1; 229 + } 230 + 50% { 231 + scale: 1.05 1.1; 232 + } 233 + } 234 + 167 235 .cable { 168 236 position: absolute; 169 237 170 238 width: 0.5rem; 171 239 height: var(--length); 240 + border-radius: 0.25rem; 172 241 background: black; 242 + 243 + [data-time="night"] + * & { 244 + background: #404040; 245 + } 173 246 174 247 /* .5rem accounts for border (z-index doesn't work) */ 175 248 z-index: -99; ··· 204 277 animation: infinite var(--timing) linear inv-tilt; 205 278 } 206 279 207 - transition: scale 0.2s; 208 - 209 280 &:focus { 210 - outline: none; 211 - scale: 1.1; 281 + @media (prefers-reduced-motion: no-preference) { 282 + outline: none; 283 + animation: 284 + infinite var(--timing) linear inv-tilt, 285 + infinite 2s cubic-bezier(0.8, -0.4, 0.469, 1.692) bouncing; 286 + } 212 287 } 213 288 } 214 289 ··· 222 297 translate: -50%; 223 298 z-index: 1; 224 299 300 + border-radius: 0.25rem; 225 301 background-color: black; 226 - border-radius: 0.25rem; 302 + 303 + [data-time="night"] + * & { 304 + background: #404040; 305 + } 227 306 } 228 307 229 308 .tie {