| 1 | <template id="stats-template"> |
| 2 | <div |
| 3 | data-composition-id="stats" |
| 4 | data-width="1920" |
| 5 | data-height="1080" |
| 6 | data-duration="__VIDEO_DURATION__" |
| 7 | > |
| 8 | <div id="stats-container"> |
| 9 | <!-- Moment 1: 47% NEED MOTION GRAPHICS --> |
| 10 | <div id="moment-1" class="moment" style="opacity: 0; transform: scale(0) rotate(8deg)"> |
| 11 | <div class="sticker-stack"> |
| 12 | <div class="sticker-bg blue-bg"></div> |
| 13 | <div class="sticker-content white-bg blue-border"> |
| 14 | <div class="stat-number blue-text">47%</div> |
| 15 | <div class="stat-label blue-text">NEED MOTION GRAPHICS</div> |
| 16 | </div> |
| 17 | </div> |
| 18 | <!-- Decorative shapes --> |
| 19 | <div |
| 20 | class="shape circle pink-bg" |
| 21 | style="top: -40px; left: -40px; width: 80px; height: 80px" |
| 22 | ></div> |
| 23 | <div |
| 24 | class="shape pill lime-bg" |
| 25 | style="bottom: -30px; right: -50px; width: 120px; height: 40px; transform: rotate(-15deg)" |
| 26 | ></div> |
| 27 | </div> |
| 28 | |
| 29 | <!-- Moment 2: 62% STRUGGLE WITH STATIC CONTENT --> |
| 30 | <div id="moment-2" class="moment" style="opacity: 0; transform: scale(0) rotate(-5deg)"> |
| 31 | <div class="sticker-stack"> |
| 32 | <div class="sticker-bg white-bg"></div> |
| 33 | <div class="sticker-content blue-bg white-border"> |
| 34 | <div class="stat-number white-text">62%</div> |
| 35 | <div class="stat-label white-text">STRUGGLE WITH STATIC CONTENT</div> |
| 36 | </div> |
| 37 | </div> |
| 38 | <!-- Decorative shapes --> |
| 39 | <div |
| 40 | class="shape blob yellow-bg" |
| 41 | style=" |
| 42 | top: -50px; |
| 43 | right: -30px; |
| 44 | width: 100px; |
| 45 | height: 100px; |
| 46 | border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%; |
| 47 | " |
| 48 | ></div> |
| 49 | <div |
| 50 | class="shape circle pink-bg" |
| 51 | style="bottom: -20px; left: -40px; width: 60px; height: 60px" |
| 52 | ></div> |
| 53 | </div> |
| 54 | |
| 55 | <!-- Moment 3: 75% LACK EDITING SKILLS --> |
| 56 | <div id="moment-3" class="moment" style="opacity: 0; transform: scale(0) rotate(3deg)"> |
| 57 | <div class="sticker-stack"> |
| 58 | <div class="sticker-bg pink-bg"></div> |
| 59 | <div class="sticker-content white-bg pink-border"> |
| 60 | <div class="stat-number pink-text">75%</div> |
| 61 | <div class="stat-label pink-text">LACK EDITING SKILLS</div> |
| 62 | </div> |
| 63 | </div> |
| 64 | <!-- Decorative shapes --> |
| 65 | <div |
| 66 | class="shape pill blue-bg" |
| 67 | style=" |
| 68 | top: -30px; |
| 69 | left: 50%; |
| 70 | transform: translateX(-50%) rotate(5deg); |
| 71 | width: 150px; |
| 72 | height: 45px; |
| 73 | " |
| 74 | ></div> |
| 75 | <div |
| 76 | class="shape circle yellow-bg" |
| 77 | style="bottom: -40px; right: -20px; width: 90px; height: 90px" |
| 78 | ></div> |
| 79 | </div> |
| 80 | </div> |
| 81 | |
| 82 | <style> |
| 83 | [data-composition-id="stats"] { |
| 84 | width: 1920px; |
| 85 | height: 1080px; |
| 86 | position: relative; |
| 87 | font-family: "Nunito", sans-serif; |
| 88 | overflow: hidden; |
| 89 | } |
| 90 | |
| 91 | [data-composition-id="stats"] #stats-container { |
| 92 | width: 100%; |
| 93 | height: 100%; |
| 94 | position: relative; |
| 95 | } |
| 96 | |
| 97 | [data-composition-id="stats"] .moment { |
| 98 | position: absolute; |
| 99 | display: flex; |
| 100 | flex-direction: column; |
| 101 | align-items: center; |
| 102 | justify-content: center; |
| 103 | padding: 40px; |
| 104 | z-index: 100; |
| 105 | } |
| 106 | |
| 107 | /* Layout Positions */ |
| 108 | [data-composition-id="stats"] #moment-1 { |
| 109 | top: 200px; |
| 110 | right: 150px; /* Right side when A-roll is Left */ |
| 111 | width: 600px; |
| 112 | } |
| 113 | |
| 114 | [data-composition-id="stats"] #moment-2 { |
| 115 | top: 250px; |
| 116 | left: 100px; /* Left side when A-roll is Right */ |
| 117 | width: 700px; |
| 118 | } |
| 119 | |
| 120 | [data-composition-id="stats"] #moment-3 { |
| 121 | bottom: 100px; /* Below A-roll when centered */ |
| 122 | left: 50%; |
| 123 | transform: translateX(-50%); |
| 124 | width: 800px; |
| 125 | } |
| 126 | |
| 127 | /* Sticker Stack Effect */ |
| 128 | [data-composition-id="stats"] .sticker-stack { |
| 129 | position: relative; |
| 130 | width: 100%; |
| 131 | padding: 40px; |
| 132 | filter: drop-shadow(0 15px 0 rgba(0, 87, 255, 0.2)); |
| 133 | } |
| 134 | |
| 135 | [data-composition-id="stats"] .sticker-bg { |
| 136 | position: absolute; |
| 137 | top: 0; |
| 138 | left: 0; |
| 139 | width: 100%; |
| 140 | height: 100%; |
| 141 | border-radius: 40px; |
| 142 | z-index: -1; |
| 143 | transform: rotate(-2deg); |
| 144 | } |
| 145 | |
| 146 | [data-composition-id="stats"] .sticker-content { |
| 147 | position: relative; |
| 148 | padding: 40px; |
| 149 | border-radius: 35px; |
| 150 | border: 8px solid currentColor; |
| 151 | display: flex; |
| 152 | flex-direction: column; |
| 153 | align-items: center; |
| 154 | text-align: center; |
| 155 | } |
| 156 | |
| 157 | /* Colors */ |
| 158 | [data-composition-id="stats"] .blue-bg { |
| 159 | background-color: #0057ff; |
| 160 | } |
| 161 | [data-composition-id="stats"] .pink-bg { |
| 162 | background-color: #ff2d8a; |
| 163 | } |
| 164 | [data-composition-id="stats"] .lime-bg { |
| 165 | background-color: #7fff00; |
| 166 | } |
| 167 | [data-composition-id="stats"] .yellow-bg { |
| 168 | background-color: #ffe500; |
| 169 | } |
| 170 | [data-composition-id="stats"] .white-bg { |
| 171 | background-color: #ffffff; |
| 172 | } |
| 173 | |
| 174 | [data-composition-id="stats"] .blue-text { |
| 175 | color: #0057ff; |
| 176 | } |
| 177 | [data-composition-id="stats"] .white-text { |
| 178 | color: #ffffff; |
| 179 | } |
| 180 | [data-composition-id="stats"] .pink-text { |
| 181 | color: #ff2d8a; |
| 182 | } |
| 183 | |
| 184 | [data-composition-id="stats"] .blue-border { |
| 185 | border-color: #0057ff; |
| 186 | } |
| 187 | [data-composition-id="stats"] .white-border { |
| 188 | border-color: #ffffff; |
| 189 | } |
| 190 | [data-composition-id="stats"] .pink-border { |
| 191 | border-color: #ff2d8a; |
| 192 | } |
| 193 | |
| 194 | /* Typography */ |
| 195 | [data-composition-id="stats"] .stat-number { |
| 196 | font-size: 180px; |
| 197 | font-weight: 900; |
| 198 | line-height: 1; |
| 199 | margin-bottom: 10px; |
| 200 | } |
| 201 | |
| 202 | [data-composition-id="stats"] .stat-label { |
| 203 | font-size: 48px; |
| 204 | font-weight: 900; |
| 205 | line-height: 1.1; |
| 206 | max-width: 500px; |
| 207 | } |
| 208 | |
| 209 | /* Shapes */ |
| 210 | [data-composition-id="stats"] .shape { |
| 211 | position: absolute; |
| 212 | z-index: -2; |
| 213 | border-radius: 50%; |
| 214 | } |
| 215 | [data-composition-id="stats"] .pill { |
| 216 | border-radius: 100px; |
| 217 | } |
| 218 | </style> |
| 219 | |
| 220 | <script> |
| 221 | (function () { |
| 222 | const TRANSCRIPT = [ |
| 223 | { text: "We", start: 0.119, end: 0.259 }, |
| 224 | { text: "asked", start: 0.319, end: 0.479 }, |
| 225 | { text: "what", start: 0.519, end: 0.659 }, |
| 226 | { text: "you", start: 0.699, end: 0.819 }, |
| 227 | { text: "needed.", start: 0.859, end: 1.819 }, |
| 228 | { text: "Forty-seven", start: 1.839, end: 2.299 }, |
| 229 | { text: "percent", start: 2.399, end: 2.679 }, |
| 230 | { text: "of", start: 2.7, end: 2.799 }, |
| 231 | { text: "you", start: 2.839, end: 2.939 }, |
| 232 | { text: "said", start: 3.039, end: 3.179 }, |
| 233 | { text: "motion", start: 3.24, end: 3.559 }, |
| 234 | { text: "graphics.", start: 3.579, end: 4.639 }, |
| 235 | { text: "Sixty-two", start: 4.659, end: 5.179 }, |
| 236 | { text: "percent", start: 5.299, end: 5.759 }, |
| 237 | { text: "said", start: 5.859, end: 5.98 }, |
| 238 | { text: "static", start: 6.099, end: 6.399 }, |
| 239 | { text: "content", start: 6.46, end: 6.879 }, |
| 240 | { text: "was", start: 6.92, end: 7.079 }, |
| 241 | { text: "costing", start: 7.099, end: 7.48 }, |
| 242 | { text: "you", start: 7.5, end: 7.579 }, |
| 243 | { text: "attention,", start: 7.679, end: 8.659 }, |
| 244 | { text: "and", start: 8.699, end: 8.86 }, |
| 245 | { text: "three", start: 8.88, end: 9.06 }, |
| 246 | { text: "out", start: 9.079, end: 9.18 }, |
| 247 | { text: "of", start: 9.199, end: 9.34 }, |
| 248 | { text: "four", start: 9.38, end: 9.799 }, |
| 249 | { text: "said", start: 9.84, end: 10.0 }, |
| 250 | { text: "you", start: 10.019, end: 10.159 }, |
| 251 | { text: "know", start: 10.179, end: 10.36 }, |
| 252 | { text: "the", start: 10.38, end: 10.479 }, |
| 253 | { text: "look", start: 10.52, end: 10.699 }, |
| 254 | { text: "you", start: 10.739, end: 10.859 }, |
| 255 | { text: "want", start: 10.98, end: 11.34 }, |
| 256 | { text: "but", start: 11.359, end: 11.52 }, |
| 257 | { text: "don't", start: 11.56, end: 11.779 }, |
| 258 | { text: "have", start: 11.819, end: 11.94 }, |
| 259 | { text: "the", start: 11.96, end: 12.06 }, |
| 260 | { text: "editing", start: 12.079, end: 12.4 }, |
| 261 | { text: "skills", start: 12.52, end: 12.86 }, |
| 262 | { text: "to", start: 12.88, end: 13.0 }, |
| 263 | { text: "get", start: 13.019, end: 13.18 }, |
| 264 | { text: "there.", start: 13.22, end: 14.22 }, |
| 265 | { text: "So", start: 14.239, end: 14.399 }, |
| 266 | { text: "we", start: 14.42, end: 14.52 }, |
| 267 | { text: "built", start: 14.619, end: 14.88 }, |
| 268 | { text: "Hyperframes", start: 15.079, end: 15.42 }, |
| 269 | ]; |
| 270 | const tl = gsap.timeline({ paused: true }); |
| 271 | |
| 272 | // Helper to find word timing |
| 273 | function getWordTime(wordText) { |
| 274 | const word = TRANSCRIPT.find((w) => |
| 275 | w.text |
| 276 | .toLowerCase() |
| 277 | .replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "") |
| 278 | .startsWith(wordText.toLowerCase()), |
| 279 | ); |
| 280 | return word ? word.start : null; |
| 281 | } |
| 282 | |
| 283 | // Timings from transcript |
| 284 | const t1 = getWordTime("Forty-seven") || 1.839; |
| 285 | const t2 = getWordTime("Sixty-two") || 4.659; |
| 286 | const t3 = getWordTime("three") || 8.88; |
| 287 | |
| 288 | // Moment 1 Animation (approx 5s) |
| 289 | tl.to( |
| 290 | "#moment-1", |
| 291 | { |
| 292 | opacity: 1, |
| 293 | scale: 1, |
| 294 | duration: 0.8, |
| 295 | ease: "elastic.out(1, 0.6)", |
| 296 | onStart: () => gsap.set("#moment-1", { transformOrigin: "center center" }), |
| 297 | }, |
| 298 | t1, |
| 299 | ); |
| 300 | |
| 301 | // Moment 1 Exit (before Moment 2) |
| 302 | tl.to( |
| 303 | "#moment-1", |
| 304 | { |
| 305 | opacity: 0, |
| 306 | scale: 0.5, |
| 307 | duration: 0.3, |
| 308 | ease: "back.in(1.7)", |
| 309 | }, |
| 310 | t2 - 0.4, |
| 311 | ); |
| 312 | |
| 313 | // Moment 2 Animation (approx 9s) |
| 314 | tl.to( |
| 315 | "#moment-2", |
| 316 | { |
| 317 | opacity: 1, |
| 318 | scale: 1, |
| 319 | duration: 0.8, |
| 320 | ease: "elastic.out(1, 0.6)", |
| 321 | onStart: () => gsap.set("#moment-2", { transformOrigin: "center center" }), |
| 322 | }, |
| 323 | t2, |
| 324 | ); |
| 325 | |
| 326 | // Moment 2 Exit (before Moment 3) |
| 327 | tl.to( |
| 328 | "#moment-2", |
| 329 | { |
| 330 | opacity: 0, |
| 331 | scale: 0.5, |
| 332 | duration: 0.3, |
| 333 | ease: "back.in(1.7)", |
| 334 | }, |
| 335 | t3 - 0.4, |
| 336 | ); |
| 337 | |
| 338 | // Moment 3 Animation (approx 13s) |
| 339 | tl.to( |
| 340 | "#moment-3", |
| 341 | { |
| 342 | opacity: 1, |
| 343 | scale: 1, |
| 344 | duration: 0.8, |
| 345 | ease: "elastic.out(1, 0.6)", |
| 346 | onStart: () => gsap.set("#moment-3", { transformOrigin: "center center" }), |
| 347 | }, |
| 348 | t3, |
| 349 | ); |
| 350 | |
| 351 | // Moment 3 Exit: 3 words before 'Hyperframes' |
| 352 | // 'Editor' is at 15.079. 3 words before is 'So' at 14.239. |
| 353 | tl.to( |
| 354 | "#moment-3", |
| 355 | { |
| 356 | opacity: 0, |
| 357 | scale: 0.5, |
| 358 | duration: 0.3, |
| 359 | ease: "back.in(1.7)", |
| 360 | }, |
| 361 | 14.239, |
| 362 | ); |
| 363 | |
| 364 | // Ambient Motion (Finite) |
| 365 | const totalDuration = 16.04; |
| 366 | gsap.utils.toArray(".shape").forEach((shape, i) => { |
| 367 | const stepDuration = 2 + i * 0.2; |
| 368 | const steps = Math.ceil(totalDuration / stepDuration); |
| 369 | for (let s = 0; s < steps; s++) { |
| 370 | tl.to( |
| 371 | shape, |
| 372 | { |
| 373 | y: s % 2 === 0 ? 15 : -15, |
| 374 | rotation: s % 2 === 0 ? 5 : -5, |
| 375 | duration: stepDuration, |
| 376 | ease: "sine.inOut", |
| 377 | }, |
| 378 | s * stepDuration, |
| 379 | ); |
| 380 | } |
| 381 | }); |
| 382 | |
| 383 | window.__timelines = window.__timelines || {}; |
| 384 | window.__timelines["stats"] = tl; |
| 385 | })(); |
| 386 | </script> |
| 387 | </div> |
| 388 | </template> |
| 389 |