mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 06:30:03 +00:00
175 lines
5.1 KiB
HTML
Vendored
175 lines
5.1 KiB
HTML
Vendored
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=1920, height=1080" />
|
||
<title>Captions – Karaoke</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link
|
||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=block"
|
||
rel="stylesheet"
|
||
/>
|
||
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
html,
|
||
body {
|
||
margin: 0;
|
||
width: 1920px;
|
||
height: 1080px;
|
||
overflow: hidden;
|
||
background: #000;
|
||
}
|
||
|
||
#captions-karaoke {
|
||
position: relative;
|
||
width: 1920px;
|
||
height: 1080px;
|
||
overflow: hidden;
|
||
background: linear-gradient(180deg, #0b0d15 0%, #101320 50%, #0b0d15 100%);
|
||
}
|
||
|
||
#captions-karaoke::before {
|
||
content: "";
|
||
position: absolute;
|
||
bottom: -60px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 800px;
|
||
height: 400px;
|
||
background: radial-gradient(ellipse, rgba(139, 92, 246, 0.05) 0%, transparent 70%);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.caption-group {
|
||
position: absolute;
|
||
bottom: 120px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
text-align: center;
|
||
font-family: "Inter", system-ui, sans-serif;
|
||
font-weight: 700;
|
||
font-size: 72px;
|
||
line-height: 1.2;
|
||
white-space: nowrap;
|
||
opacity: 0;
|
||
visibility: hidden;
|
||
will-change: opacity;
|
||
font-variant-numeric: tabular-nums;
|
||
/* Frosted glass pill */
|
||
background: rgba(255, 255, 255, 0.06);
|
||
backdrop-filter: blur(12px);
|
||
-webkit-backdrop-filter: blur(12px);
|
||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||
border-radius: 24px;
|
||
padding: 24px 56px;
|
||
}
|
||
|
||
.caption-group .word {
|
||
display: inline-block;
|
||
color: rgba(255, 255, 255, 0.3);
|
||
margin: 0 8px;
|
||
will-change: color, transform;
|
||
transform-origin: center bottom;
|
||
}
|
||
|
||
.driver {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 1px;
|
||
height: 1px;
|
||
opacity: 0;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div
|
||
id="captions-karaoke"
|
||
data-composition-id="captions-karaoke"
|
||
data-width="1920"
|
||
data-height="1080"
|
||
data-start="0"
|
||
data-duration="13"
|
||
data-root="true"
|
||
>
|
||
<div class="driver" data-track-index="0"></div>
|
||
</div>
|
||
|
||
<script>
|
||
(function () {
|
||
var GROUPS = [
|
||
{ text: "Write HTML", start: 0.3, end: 1.8 },
|
||
{ text: "render video", start: 2.0, end: 3.5 },
|
||
{ text: "No timeline editors", start: 3.8, end: 5.5 },
|
||
{ text: "no After Effects", start: 5.7, end: 7.2 },
|
||
{ text: "Ship 10x faster", start: 7.5, end: 9.5 },
|
||
{ text: "with HyperFrames", start: 9.8, end: 12.0 },
|
||
];
|
||
|
||
var root = document.getElementById("captions-karaoke");
|
||
|
||
// Build caption group elements with per-word spans
|
||
GROUPS.forEach(function (group, gi) {
|
||
var div = document.createElement("div");
|
||
div.className = "caption-group";
|
||
div.id = "cg-" + gi;
|
||
|
||
var words = group.text.split(" ");
|
||
words.forEach(function (word, wi) {
|
||
var span = document.createElement("span");
|
||
span.className = "word";
|
||
span.id = "cg-" + gi + "-w" + wi;
|
||
span.textContent = word;
|
||
div.appendChild(span);
|
||
});
|
||
|
||
root.appendChild(div);
|
||
});
|
||
|
||
// Build timeline
|
||
var tl = gsap.timeline({ paused: true });
|
||
|
||
GROUPS.forEach(function (group, gi) {
|
||
var el = "#cg-" + gi;
|
||
var words = group.text.split(" ");
|
||
var totalWords = words.length;
|
||
var groupDuration = group.end - group.start;
|
||
|
||
// Show group (dimmed words visible)
|
||
tl.set(el, { opacity: 1, visibility: "visible" }, group.start);
|
||
|
||
// Highlight each word as its time arrives
|
||
words.forEach(function (word, wi) {
|
||
var wordStart = group.start + (wi / totalWords) * groupDuration;
|
||
var wordEl = "#cg-" + gi + "-w" + wi;
|
||
tl.to(
|
||
wordEl,
|
||
{ color: "#ffffff", scale: 1.05, duration: 0.15, ease: "power2.out" },
|
||
wordStart,
|
||
);
|
||
});
|
||
|
||
// Fade out group
|
||
tl.to(el, { opacity: 0, duration: 0.15, ease: "power2.in" }, group.end - 0.15);
|
||
|
||
// Hard kill: reset all words and hide group
|
||
words.forEach(function (word, wi) {
|
||
var wordEl = "#cg-" + gi + "-w" + wi;
|
||
tl.set(wordEl, { color: "rgba(255,255,255,0.3)", scale: 1 }, group.end);
|
||
});
|
||
tl.set(el, { opacity: 0, visibility: "hidden" }, group.end);
|
||
});
|
||
|
||
window.__timelines = window.__timelines || [];
|
||
window.__timelines.push(tl);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|