LEVEL 2 · ระดับกลาง
Sub-composition — ประกอบเรื่องจากชิ้นส่วน
การ์ดใบเดียวอยู่ไฟล์เดียวได้สบาย แต่พองานโต — หลายฉาก หรืออยากใช้การ์ดปิดเดิมซ้ำในคลิปอื่นของทีม — คุณต้องแตกไฟล์ และการแตกไฟล์ใน HyperFrames มีกลไกขนส่งเฉพาะตัวที่ต้องเข้าใจก่อน ไม่งั้นเจอบั๊กที่ "ทุกด่านผ่านแต่ render พัง"
8.1 template คือตู้คอนเทนเนอร์ — ของนอกตู้ถูกทิ้งท่าเรือ
ตอน mount ไฟล์ลูก runtime ทำแค่นี้: fetch ไฟล์ → หา template → โคลนเฉพาะของข้างใน ไปวางในเรื่อง ทุกอย่างนอก template — รวมทั้ง head ทั้งหัว — ถูกทิ้ง
ผลคือกฎเหล็กข้อแรก: style และ script ของไฟล์ลูกต้องอยู่ใน template วางไว้ใน head ตามสัญชาตญาณ HTML ปกติ = สไตล์ทั้งชุดหายเงียบ อาการคือตัวหนังสือจิ๋วไม่ติดสไตล์กองมุมซ้ายบน — ด่าน static ทุกตัวผ่านหมดเพราะแต่ละไฟล์ถูกต้องในตัวเอง พังเฉพาะตอนประกอบ
template — ทุกอย่างนอกนั้นรวมทั้ง head ถูกทิ้งตั้งแต่ท่าเรือ (สไตล์ที่เผลอวางใน head จึงหายเงียบทั้งชุด) · และชื่อ composition ต้องตรงกันสามจุด: ช่องเสียบ = root ของไฟล์ลูก = กุญแจ timeline8.2 ของจริง: การ์ดปิดของเรา
ผมแตกการ์ดปิดออกเป็น compositions/outro.html โครงตามนี้ (ตัดให้สั้น):
<body>
<template>
<style>
#root { position: absolute; inset: 0; }
#outro-card-line { position: absolute; left: 200px; top: 920px; ... }
</style>
<div id="root" data-composition-id="outro-card" data-width="1920" data-height="1080">
<div id="outro-card-line">เตรียมอัปเดตงานของตัวเอง คนละ 1 นาที แล้วเจอกันครับ</div>
</div>
<script>
const outroTl = gsap.timeline({ paused: true });
outroTl.fromTo("#outro-card-line", { autoAlpha: 0, y: 16 },
{ autoAlpha: 1, y: 0, duration: 0.8 }, 0.1);
window.__timelines["outro-card"] = outroTl;
</script>
</template>
</body>ฝั่งเรื่องหลัก clip ตัวเดิมกลายเป็น "ช่องเสียบ":
<div id="outro" data-composition-id="outro-card"
data-composition-src="compositions/outro.html"
data-start="6.5" data-duration="3.5" data-track-index="4"
data-width="1920" data-height="1080"></div>สังเกตสามอย่าง: (ก) id ต้องตรงกันสามจุด — บนช่องเสียบ บน root ของไฟล์ลูก และกุญแจ __timelines — เพราะชื่อนี้คือทางเดียวที่เครื่องใช้จับคู่ timeline อย่าตั้งชื่อช่องเสียบเป็น outro-mount เด็ดขาด (ข) เวลาใน timeline ลูกเป็นเวลาท้องถิ่น: 0.1 ของมันคือ 6.6 ของเรื่อง (ค) สไตล์ root ของไฟล์ลูกต้องเขียนผ่าน #root — ตอนประกอบ CSS ทุกกฎถูก scope ด้วย composition-id เป็น descendant selector คลาสที่แปะบน root เองจึงไม่มีวัน match แล้วกฎทั้งชุดหายเงียบ
8.3 ด่านตรวจของบทนี้: snapshot กลางฉาก
บั๊ก mount ทั้งตระกูลนี้ผ่าน static check ได้หมด ด่านเดียวที่จับคือถ่ายเฟรมกลางช่วงของ slot แล้วดูด้วยตา — ผมรัน snapshot --at 7.5 แล้วเห็นการ์ดปิดขึ้นครบถูกตำแหน่ง ฟอนต์มาเต็ม นั่นคือเสียงเขียวจริงของบทนี้ (check ก็ยังผ่านเต็มทุกหมวด รวม motion sidecar ที่ assert ทะลุเข้าไปหา element ในไฟล์ลูกได้ด้วย)