返回 html-video
scene2-4-canvas.html
根目录 / templates / frame-product-promo / compositions / scene2-4-canvas.html
1 <template id="scene2-4-canvas-template">
2 <div
3 data-composition-id="scene2-4-canvas"
4 data-width="1920"
5 data-height="1080"
6 data-duration="12.5"
7 >
8 <div class="canvas">
9 <div class="dot-grid"></div>
10
11 <!-- Web Frame -->
12 <div class="web-frame">
13 <div class="ui-content">
14 <div class="nav-bar">
15 <div class="nav-logo"></div>
16 <div class="nav-links">
17 <div class="nav-link"></div>
18 <div class="nav-link"></div>
19 <div class="nav-link"></div>
20 </div>
21 </div>
22 <div class="hero-section">
23 <h1 class="hero-heading">Design without limits</h1>
24 <div class="subtitle-lines">
25 <div class="subtitle-line"></div>
26 <div class="subtitle-line"></div>
27 </div>
28 <div class="cta-button">Get Started</div>
29 </div>
30 </div>
31 <!-- Dimension Labels -->
32 <div class="dimension-label width-label">1440</div>
33 <div class="dimension-label height-label">900</div>
34 <!-- Selection Handles (Engineer) -->
35 <div class="selection-handles">
36 <div class="handle tl"></div>
37 <div class="handle tr"></div>
38 <div class="handle bl"></div>
39 <div class="handle br"></div>
40 </div>
41 </div>
42
43 <!-- Assets Panel -->
44 <div class="assets-panel">
45 <div class="panel-header">Assets</div>
46 <div class="asset-list">
47 <div class="asset-item">
48 <span class="asset-icon">◆</span>
49 <span class="asset-text">Button/Primary</span>
50 </div>
51 <div class="asset-item">
52 <span class="asset-icon">◆</span>
53 <span class="asset-text">Card/Product</span>
54 </div>
55 <div class="asset-item">
56 <span class="asset-icon">◆</span>
57 <span class="asset-text">Nav/Header</span>
58 </div>
59 </div>
60 </div>
61
62 <!-- Draggable Component (Scene 4) -->
63 <div class="dragged-card">
64 <div class="card-content"></div>
65 </div>
66
67 <!-- Stamped Cards (Scene 4) -->
68 <div class="stamped-cards">
69 <div class="stamped-card card-1"></div>
70 <div class="stamped-card card-2"></div>
71 <div class="stamped-card card-3"></div>
72 </div>
73
74 <!-- Comment Pin & Bubble -->
75 <div class="comment-container">
76 <div class="comment-pin">
77 <div class="checkmark">✓</div>
78 </div>
79 <div class="comment-bubble">
80 <div class="comment-text"></div>
81 </div>
82 </div>
83
84 <!-- Cursors -->
85 <div class="cursor designer-cursor">
86 <svg width="24" height="24" viewBox="0 0 24 24">
87 <path d="M0 0 L 16 16 L 9.5 16 L 6.5 23 L 6.5 16 L 0 16 Z" fill="white" stroke="black" />
88 </svg>
89 <div class="cursor-label">Designer</div>
90 </div>
91 <div class="cursor engineer-cursor">
92 <svg width="24" height="24" viewBox="0 0 24 24">
93 <path d="M0 0 L 16 16 L 9.5 16 L 6.5 23 L 6.5 16 L 0 16 Z" fill="white" stroke="black" />
94 </svg>
95 <div class="cursor-label">Engineer</div>
96 </div>
97 <div class="cursor pm-cursor">
98 <svg width="24" height="24" viewBox="0 0 24 24">
99 <path d="M0 0 L 16 16 L 9.5 16 L 6.5 23 L 6.5 16 L 0 16 Z" fill="white" stroke="black" />
100 </svg>
101 <div class="cursor-label">PM</div>
102 </div>
103 </div>
104
105 <style>
106 [data-composition-id="scene2-4-canvas"] {
107 background-color: #1e1e1e;
108 font-family: "Inter", sans-serif;
109 color: white;
110 overflow: hidden;
111 }
112
113 .canvas {
114 width: 100%;
115 height: 100%;
116 position: relative;
117 }
118
119 .dot-grid {
120 position: absolute;
121 top: 0;
122 left: 0;
123 width: 100%;
124 height: 100%;
125 background-image: radial-gradient(#2c2c2c 1px, transparent 1px);
126 background-size: 24px 24px;
127 }
128
129 .web-frame {
130 position: absolute;
131 top: 50%;
132 left: 50%;
133 width: 1440px;
134 height: 900px;
135 background: white;
136 border: 1px solid rgba(255, 255, 255, 0.2);
137 box-shadow: 0 20px 50px rgba(0, 0, 0, 0.3);
138 overflow: hidden;
139 opacity: 0;
140 }
141
142 .ui-content {
143 width: 100%;
144 height: 100%;
145 background: white;
146 display: flex;
147 flex-direction: column;
148 opacity: 0;
149 }
150
151 .nav-bar {
152 height: 80px;
153 padding: 0 60px;
154 display: flex;
155 align-items: center;
156 justify-content: space-between;
157 border-bottom: 1px solid #e6e6e6;
158 }
159
160 .nav-logo {
161 width: 40px;
162 height: 40px;
163 background: #a259ff;
164 border-radius: 8px;
165 opacity: 0.8;
166 }
167
168 .nav-links {
169 display: flex;
170 gap: 32px;
171 }
172
173 .nav-link {
174 width: 80px;
175 height: 12px;
176 background: #cccccc;
177 border-radius: 6px;
178 }
179
180 .hero-section {
181 flex: 1;
182 display: flex;
183 flex-direction: column;
184 align-items: center;
185 justify-content: center;
186 padding-bottom: 100px;
187 transition: transform 0.8s cubic-bezier(0.34, 1.56, 0.64, 1);
188 }
189
190 .hero-heading {
191 font-size: 84px;
192 font-weight: 800;
193 color: #1e1e1e;
194 margin-bottom: 24px;
195 opacity: 0;
196 letter-spacing: -0.02em;
197 transform-origin: center;
198 }
199
200 .subtitle-lines {
201 display: flex;
202 flex-direction: column;
203 align-items: center;
204 gap: 12px;
205 margin-bottom: 48px;
206 transform-origin: center;
207 }
208
209 .subtitle-line {
210 width: 400px;
211 height: 16px;
212 background: #e6e6e6;
213 border-radius: 8px;
214 opacity: 0;
215 }
216
217 .cta-button {
218 padding: 20px 48px;
219 background: #0acf83;
220 color: white;
221 font-size: 24px;
222 font-weight: 600;
223 border-radius: 12px;
224 opacity: 0;
225 position: relative;
226 transform-origin: center;
227 }
228
229 .dimension-label {
230 position: absolute;
231 background: #1abcfe;
232 color: white;
233 padding: 4px 8px;
234 font-size: 14px;
235 font-weight: 600;
236 border-radius: 4px;
237 }
238
239 .width-label {
240 top: -30px;
241 left: 50%;
242 }
243
244 .height-label {
245 right: -45px;
246 top: 50%;
247 }
248
249 .selection-handles {
250 position: absolute;
251 top: 0;
252 left: 0;
253 width: 100%;
254 height: 100%;
255 pointer-events: none;
256 opacity: 0;
257 }
258
259 .handle {
260 position: absolute;
261 width: 12px;
262 height: 12px;
263 background: white;
264 border: 2px solid #1abcfe;
265 border-radius: 2px;
266 }
267
268 .handle.tl {
269 top: -6px;
270 left: -6px;
271 }
272 .handle.tr {
273 top: -6px;
274 right: -6px;
275 }
276 .handle.bl {
277 bottom: -6px;
278 left: -6px;
279 }
280 .handle.br {
281 bottom: -6px;
282 right: -6px;
283 }
284
285 .assets-panel {
286 position: absolute;
287 top: 0;
288 left: 0;
289 width: 320px;
290 height: 100%;
291 background: rgba(44, 44, 44, 0.9);
292 backdrop-filter: blur(12px);
293 -webkit-backdrop-filter: blur(12px);
294 border-right: 1px solid rgba(255, 255, 255, 0.1);
295 padding: 24px;
296 z-index: 10;
297 box-shadow: 4px 0 24px rgba(0, 0, 0, 0.2);
298 }
299
300 .panel-header {
301 font-size: 18px;
302 font-weight: 600;
303 margin-bottom: 32px;
304 color: #aaa;
305 }
306
307 .asset-item {
308 display: flex;
309 align-items: center;
310 gap: 12px;
311 padding: 12px;
312 border-radius: 8px;
313 margin-bottom: 8px;
314 background: rgba(255, 255, 255, 0.05);
315 }
316
317 .asset-icon {
318 color: #a259ff;
319 font-size: 18px;
320 }
321
322 .asset-text {
323 font-size: 14px;
324 color: #eee;
325 }
326
327 .dragged-card {
328 position: absolute;
329 width: 300px;
330 height: 200px;
331 background: white;
332 border-radius: 12px;
333 box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
334 opacity: 0;
335 transform: scale(0.9);
336 z-index: 20;
337 pointer-events: none;
338 }
339
340 .card-content {
341 width: 100%;
342 height: 100%;
343 background: linear-gradient(45deg, #f0f0f0, #fff);
344 border-radius: 12px;
345 }
346
347 .stamped-cards {
348 position: absolute;
349 top: 50%;
350 left: 50%;
351 transform: translate(-50%, -50%);
352 width: 1440px;
353 height: 900px;
354 pointer-events: none;
355 display: flex;
356 justify-content: center;
357 align-items: center;
358 gap: 40px;
359 }
360
361 .stamped-card {
362 position: relative;
363 width: 300px;
364 height: 200px;
365 background: white;
366 border-radius: 12px;
367 box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
368 opacity: 0;
369 transform: translateY(50px);
370 }
371
372 .card-1,
373 .card-2,
374 .card-3 {
375 top: auto;
376 left: auto;
377 }
378
379 .comment-container {
380 position: absolute;
381 top: 420px;
382 left: 960px;
383 z-index: 30;
384 opacity: 0;
385 }
386
387 .comment-pin {
388 width: 32px;
389 height: 32px;
390 background: #f24e1e;
391 border-radius: 16px 16px 16px 0;
392 display: flex;
393 align-items: center;
394 justify-content: center;
395 box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
396 transform-origin: bottom left;
397 }
398
399 .checkmark {
400 color: white;
401 font-size: 18px;
402 font-weight: bold;
403 transform: scale(0);
404 }
405
406 .comment-bubble {
407 position: absolute;
408 left: 40px;
409 top: -20px;
410 background: white;
411 padding: 12px 16px;
412 border-radius: 12px;
413 color: #1e1e1e;
414 font-size: 14px;
415 font-weight: 500;
416 white-space: nowrap;
417 box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
418 opacity: 0;
419 }
420
421 .cursor {
422 position: absolute;
423 display: flex;
424 flex-direction: column;
425 align-items: flex-start;
426 z-index: 100;
427 pointer-events: none;
428 }
429
430 .cursor-label {
431 padding: 4px 8px;
432 font-size: 12px;
433 font-weight: 600;
434 color: white;
435 border-radius: 0 4px 4px 4px;
436 margin-top: -4px;
437 margin-left: 12px;
438 box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
439 }
440
441 .designer-cursor .cursor-label {
442 background: #a259ff;
443 }
444 .engineer-cursor .cursor-label {
445 background: #1abcfe;
446 }
447 .pm-cursor .cursor-label {
448 background: #f24e1e;
449 }
450 </style>
451
452 <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
453 <script>
454 (function () {
455 const tl = gsap.timeline({ paused: true });
456
457 // Organic Cursor Ease
458 const cursorEase = "back.out(1.2)";
459
460 gsap.set(".web-frame", { xPercent: -50, yPercent: -50, scale: 0 });
461 gsap.set(".width-label", { xPercent: -50, scale: 0 });
462 gsap.set(".height-label", { yPercent: -50, rotation: 90, scale: 0 });
463 gsap.set(".comment-bubble", { x: -10 });
464 gsap.set(".assets-panel", { x: -320 });
465 gsap.set(".designer-cursor", { x: 200, y: 200 });
466 gsap.set(".engineer-cursor", { x: -100, y: 500 });
467 gsap.set(".pm-cursor", { x: 2000, y: 1100 });
468
469 // Designer enters
470 tl.to(".designer-cursor", { x: 960, y: 540, duration: 1.0, ease: cursorEase }, 0);
471
472 // Frame appears
473 tl.to(".web-frame", { opacity: 1, scale: 1, duration: 0.6, ease: "back.out(1.4)" }, 0.5);
474
475 // UI Stagger
476 tl.to(".ui-content", { opacity: 1, duration: 0.4 }, 1.0);
477 tl.to(".hero-heading", { opacity: 1, y: 0, duration: 0.7, ease: "back.out(1.2)" }, 1.2);
478 tl.to(
479 ".subtitle-line",
480 { opacity: 1, y: 0, duration: 0.5, stagger: 0.08, ease: "power2.out" },
481 1.4,
482 );
483 tl.to(".cta-button", { opacity: 1, scale: 1, duration: 0.5, ease: "back.out(1.7)" }, 1.7);
484
485 // Labels
486 tl.to(".width-label", { scale: 1, duration: 0.4, ease: "back.out(2)" }, 1.9);
487 tl.to(".height-label", { scale: 1, rotation: 90, duration: 0.4, ease: "back.out(2)" }, 2.0);
488
489 // Collaboration
490 tl.to(".engineer-cursor", { x: 400, y: 400, duration: 1.2, ease: cursorEase }, 3.5);
491 tl.to(".pm-cursor", { x: 1500, y: 800, duration: 1.5, ease: cursorEase }, 3.7);
492 tl.to(
493 ".engineer-cursor",
494 { x: 960, y: 680, duration: 0.9, ease: cursorEase, overwrite: "auto" },
495 4.5,
496 );
497 tl.to(".selection-handles", { opacity: 1, duration: 0.2 }, 5.3);
498 tl.to(".cta-button", { outline: "2px solid #1ABCFE", duration: 0.1 }, 5.3);
499
500 tl.to(".pm-cursor", { x: 960, y: 420, duration: 1.1, ease: cursorEase }, 5.5);
501 tl.to(".comment-container", { opacity: 1, duration: 0.1 }, 6.5);
502 tl.from(".comment-pin", { scale: 0, duration: 0.5, ease: "back.out(1.2)" }, 6.5);
503 tl.to(".comment-bubble", { opacity: 1, x: 0, duration: 0.4, ease: "back.out(1.5)" }, 6.9);
504
505 const commentText = "Let's use the product shot here";
506 const textObj = { val: 0 };
507 tl.to(
508 textObj,
509 {
510 val: commentText.length,
511 duration: commentText.length / 30,
512 ease: "none",
513 onUpdate: () => {
514 const el = document.querySelector(
515 '[data-composition-id="scene2-4-canvas"] .comment-text',
516 );
517 if (el) el.innerText = commentText.substring(0, Math.ceil(textObj.val));
518 },
519 },
520 7.1,
521 );
522
523 // Assets Panel
524 tl.to(".assets-panel", { x: 0, duration: 0.4, ease: "power3.out" }, 8.0);
525 tl.to(".engineer-cursor", { x: 160, y: 150, duration: 0.7, ease: cursorEase }, 8.3);
526 tl.to(".dragged-card", { opacity: 1, scale: 1, x: 160, y: 150, duration: 0.2 }, 8.9);
527 tl.to(
528 [".engineer-cursor", ".dragged-card"],
529 { x: 960, y: 700, duration: 0.9, ease: cursorEase },
530 9.1,
531 );
532
533 // Reformat UI as card is dragged in
534 tl.to(".hero-section", { y: -150, duration: 0.8, ease: "power3.inOut" }, 9.1);
535 tl.to(".hero-heading", { scale: 0.8, duration: 0.8, ease: "power3.inOut" }, 9.1);
536 tl.to(".subtitle-lines", { scale: 0.8, duration: 0.8, ease: "power3.inOut" }, 9.1);
537 tl.to(".cta-button", { scale: 0.8, duration: 0.8, ease: "power3.inOut" }, 9.1);
538
539 // Stamping into Grid/Row
540 tl.to(".stamped-cards", { y: 200, duration: 0.1 }, 9.1); // Position the container
541 tl.to(".card-1", { opacity: 1, y: 0, duration: 0.6, ease: "back.out(1.5)" }, 9.9);
542 tl.to(".card-2", { opacity: 1, y: 0, duration: 0.6, ease: "back.out(1.5)" }, 10.1);
543 tl.to(".card-3", { opacity: 1, y: 0, duration: 0.6, ease: "back.out(1.5)" }, 10.3);
544
545 tl.to(".dragged-card", { opacity: 0, scale: 0.8, duration: 0.2 }, 10.5);
546 tl.to(".checkmark", { scale: 1, duration: 0.4, ease: "back.out(1.8)" }, 10.7);
547 tl.to(".comment-pin", { backgroundColor: "#0ACF83", duration: 0.3 }, 10.7);
548 tl.to(".assets-panel", { x: -320, duration: 0.4, ease: "power3.in" }, 11.5);
549
550 // Scene 5 Transition: Wipe everything to the left
551 tl.to(
552 [
553 ".web-frame",
554 ".cursor",
555 ".dragged-card",
556 ".stamped-cards",
557 ".comment-container",
558 ".assets-panel",
559 ],
560 {
561 x: -2000,
562 duration: 0.5,
563 ease: "expo.in",
564 stagger: 0.02,
565 },
566 12.0,
567 );
568
569 window.__timelines = window.__timelines || {};
570 window.__timelines["scene2-4-canvas"] = tl;
571 })();
572 </script>
573 </div>
574 </template>
575
575 lines HTML