mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-11 06:30:03 +00:00
Merge pull request #927 from heygen-com/fix/caption-polish
fix(registry): polish caption timing and add highlight style
This commit is contained in:
@@ -9,7 +9,7 @@ RGB chromatic aberration with CRT scanline overlay
|
|||||||
|
|
||||||
`captions` `caption-style` `glitch` `cyber` `tech`
|
`captions` `caption-style` `glitch` `cyber` `tech`
|
||||||
|
|
||||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-glitch-rgb.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-glitch-rgb.png" autoPlay muted loop playsInline />
|
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-glitch-rgb.mp4?v=1779066308" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-glitch-rgb.png" autoPlay muted loop playsInline />
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
title: "Highlight"
|
||||||
|
description: "Red background sweep behind each active word, TikTok-style"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Highlight
|
||||||
|
|
||||||
|
Red background sweep behind each active word, TikTok-style
|
||||||
|
|
||||||
|
`captions` `caption-style` `highlight` `social` `tiktok`
|
||||||
|
|
||||||
|
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-highlight.mp4?v=1779066308" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-highlight.png" autoPlay muted loop playsInline />
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
|
||||||
|
```bash Terminal
|
||||||
|
npx hyperframes add caption-highlight
|
||||||
|
```
|
||||||
|
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
| Property | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| Type | Component |
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
| File | Target | Type |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `caption-highlight.html` | `compositions/components/caption-highlight.html` | hyperframes:snippet |
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Open `compositions/components/caption-highlight.html` and paste its contents into your composition. See the comment header in the file for detailed instructions.
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Typewriter"
|
|
||||||
description: "Green terminal character-by-character reveal with blinking cursor"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Typewriter
|
|
||||||
|
|
||||||
Green terminal character-by-character reveal with blinking cursor
|
|
||||||
|
|
||||||
`captions` `caption-style` `terminal` `typewriter` `hacker`
|
|
||||||
|
|
||||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-typewriter.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-typewriter.png" autoPlay muted loop playsInline />
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
<CodeGroup>
|
|
||||||
|
|
||||||
```bash Terminal
|
|
||||||
npx hyperframes add caption-typewriter
|
|
||||||
```
|
|
||||||
|
|
||||||
</CodeGroup>
|
|
||||||
|
|
||||||
## Details
|
|
||||||
|
|
||||||
| Property | Value |
|
|
||||||
| --- | --- |
|
|
||||||
| Type | Component |
|
|
||||||
|
|
||||||
## Files
|
|
||||||
|
|
||||||
| File | Target | Type |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `caption-typewriter.html` | `compositions/components/caption-typewriter.html` | hyperframes:snippet |
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Open `compositions/components/caption-typewriter.html` and paste its contents into your composition. See the comment header in the file for detailed instructions.
|
|
||||||
@@ -9,7 +9,7 @@ Elegant font-weight transition between caption lines
|
|||||||
|
|
||||||
`captions` `caption-style` `minimal` `typography`
|
`captions` `caption-style` `minimal` `typography`
|
||||||
|
|
||||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-weight-shift.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-weight-shift.png" autoPlay muted loop playsInline />
|
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-weight-shift.mp4?v=1779066308" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-weight-shift.png" autoPlay muted loop playsInline />
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -103,6 +103,7 @@
|
|||||||
"catalog/components/caption-emoji-pop",
|
"catalog/components/caption-emoji-pop",
|
||||||
"catalog/components/caption-glitch-rgb",
|
"catalog/components/caption-glitch-rgb",
|
||||||
"catalog/components/caption-gradient-fill",
|
"catalog/components/caption-gradient-fill",
|
||||||
|
"catalog/components/caption-highlight",
|
||||||
"catalog/components/caption-kinetic-slam",
|
"catalog/components/caption-kinetic-slam",
|
||||||
"catalog/components/caption-matrix-decode",
|
"catalog/components/caption-matrix-decode",
|
||||||
"catalog/components/caption-neon-accent",
|
"catalog/components/caption-neon-accent",
|
||||||
@@ -111,7 +112,6 @@
|
|||||||
"catalog/components/caption-particle-burst",
|
"catalog/components/caption-particle-burst",
|
||||||
"catalog/components/caption-pill-karaoke",
|
"catalog/components/caption-pill-karaoke",
|
||||||
"catalog/components/caption-texture-lava",
|
"catalog/components/caption-texture-lava",
|
||||||
"catalog/components/caption-typewriter",
|
|
||||||
"catalog/components/caption-weight-shift"
|
"catalog/components/caption-weight-shift"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -114,6 +114,21 @@
|
|||||||
"href": "/catalog/components/caption-gradient-fill",
|
"href": "/catalog/components/caption-gradient-fill",
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-gradient-fill.png"
|
"preview": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-gradient-fill.png"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "caption-highlight",
|
||||||
|
"type": "component",
|
||||||
|
"title": "Highlight",
|
||||||
|
"description": "Red background sweep behind each active word, TikTok-style",
|
||||||
|
"tags": [
|
||||||
|
"captions",
|
||||||
|
"caption-style",
|
||||||
|
"highlight",
|
||||||
|
"social",
|
||||||
|
"tiktok"
|
||||||
|
],
|
||||||
|
"href": "/catalog/components/caption-highlight",
|
||||||
|
"preview": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-highlight.png"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "caption-kinetic-slam",
|
"name": "caption-kinetic-slam",
|
||||||
"type": "component",
|
"type": "component",
|
||||||
@@ -233,21 +248,6 @@
|
|||||||
"href": "/catalog/components/caption-texture-lava",
|
"href": "/catalog/components/caption-texture-lava",
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-texture-lava.png"
|
"preview": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-texture-lava.png"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "caption-typewriter",
|
|
||||||
"type": "component",
|
|
||||||
"title": "Typewriter",
|
|
||||||
"description": "Green terminal character-by-character reveal with blinking cursor",
|
|
||||||
"tags": [
|
|
||||||
"captions",
|
|
||||||
"caption-style",
|
|
||||||
"terminal",
|
|
||||||
"typewriter",
|
|
||||||
"hacker"
|
|
||||||
],
|
|
||||||
"href": "/catalog/components/caption-typewriter",
|
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/docs/images/catalog/components/caption-typewriter.png"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "caption-weight-shift",
|
"name": "caption-weight-shift",
|
||||||
"type": "component",
|
"type": "component",
|
||||||
|
|||||||
@@ -257,15 +257,32 @@ async function buildFontFaceCss(
|
|||||||
const unresolved: string[] = [];
|
const unresolved: string[] = [];
|
||||||
|
|
||||||
for (const [normalizedFamily, originalCaseFamily] of requestedFamilies) {
|
for (const [normalizedFamily, originalCaseFamily] of requestedFamilies) {
|
||||||
// Path 1: pre-bundled fonts via FONT_ALIASES
|
// Path 1: pre-bundled fonts via FONT_ALIASES — emit embedded faces,
|
||||||
|
// then fetch from Google Fonts to fill any weights not in the bundle.
|
||||||
const canonicalKey = FONT_ALIASES[normalizedFamily];
|
const canonicalKey = FONT_ALIASES[normalizedFamily];
|
||||||
if (canonicalKey) {
|
if (canonicalKey) {
|
||||||
const canonical = CANONICAL_FONTS[canonicalKey];
|
const canonical = CANONICAL_FONTS[canonicalKey];
|
||||||
if (!canonical) continue;
|
if (!canonical) continue;
|
||||||
|
|
||||||
|
const coveredWeights = new Set<string>();
|
||||||
for (const face of canonical.faces) {
|
for (const face of canonical.faces) {
|
||||||
const style = face.style || "normal";
|
const style = face.style || "normal";
|
||||||
const src = fontDataUri(canonical.packageName, face.weight, style);
|
const src = fontDataUri(canonical.packageName, face.weight, style);
|
||||||
rules.push(buildFontFaceRule(originalCaseFamily, src, face.weight, style));
|
rules.push(buildFontFaceRule(originalCaseFamily, src, face.weight, style));
|
||||||
|
coveredWeights.add(`${face.weight}:${style}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch all weights from Google Fonts and add any that aren't
|
||||||
|
// already covered by the embedded bundle. This ensures that
|
||||||
|
// compositions requesting e.g. wght@200 get that weight even
|
||||||
|
// if the bundle only ships 400/700/900.
|
||||||
|
const googleFaces = await fetchGoogleFont(originalCaseFamily, options);
|
||||||
|
for (const face of googleFaces) {
|
||||||
|
const key = `${face.weight}:${face.style}`;
|
||||||
|
if (!coveredWeights.has(key)) {
|
||||||
|
rules.push(buildFontFaceRule(originalCaseFamily, face.dataUri, face.weight, face.style));
|
||||||
|
coveredWeights.add(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@
|
|||||||
var ws = pair[0],
|
var ws = pair[0],
|
||||||
we = pair[1];
|
we = pair[1];
|
||||||
var nextStart = gi + 1 < RAW_GROUPS.length ? WORDS[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
var nextStart = gi + 1 < RAW_GROUPS.length ? WORDS[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
||||||
var gEnd = Math.min(WORDS[we].end + 0.35, nextStart - 0.05);
|
var gEnd = Math.min(WORDS[we].end + 0.5, nextStart - 0.05);
|
||||||
return { wordStart: ws, wordEnd: we, start: WORDS[ws].start, end: gEnd };
|
return { wordStart: ws, wordEnd: we, start: WORDS[ws].start, end: gEnd };
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -210,13 +210,13 @@
|
|||||||
|
|
||||||
tl.to(
|
tl.to(
|
||||||
wordEl,
|
wordEl,
|
||||||
{ clipPath: "inset(0 0% 0 0)", duration: 0.15, ease: "power3.out" },
|
{ clipPath: "inset(0 0% 0 0)", duration: 0.3, ease: "power2.out" },
|
||||||
w.start,
|
w.start,
|
||||||
);
|
);
|
||||||
if (isKW) {
|
if (isKW) {
|
||||||
tl.to(wordEl, { color: "#FFD700", duration: 0.05 }, w.start + 0.1);
|
tl.to(wordEl, { color: "#FFD700", duration: 0.05 }, w.start + 0.1);
|
||||||
}
|
}
|
||||||
tl.to(wordEl, { color: "rgba(255,255,255,0.4)", duration: 0.12 }, w.end);
|
tl.to(wordEl, { color: "rgba(255,255,255,0.4)", duration: 0.2 }, w.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
var wordEls = grp.querySelectorAll(".wp-word");
|
var wordEls = grp.querySelectorAll(".wp-word");
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
wordEls,
|
wordEls,
|
||||||
{
|
{
|
||||||
clipPath: "inset(0 0% 0 100%)",
|
clipPath: "inset(0 0% 0 100%)",
|
||||||
duration: 0.14,
|
duration: 0.25,
|
||||||
stagger: 0.04,
|
stagger: 0.04,
|
||||||
ease: "power2.in",
|
ease: "power2.in",
|
||||||
},
|
},
|
||||||
|
|||||||
+4
-4
@@ -169,7 +169,7 @@
|
|||||||
var ws = pair[0],
|
var ws = pair[0],
|
||||||
we = pair[1];
|
we = pair[1];
|
||||||
var nextStart = gi + 1 < RAW_GROUPS.length ? WORDS[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
var nextStart = gi + 1 < RAW_GROUPS.length ? WORDS[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
||||||
var gEnd = Math.min(WORDS[we].end + 0.35, nextStart - 0.05);
|
var gEnd = Math.min(WORDS[we].end + 0.5, nextStart - 0.05);
|
||||||
return { wordStart: ws, wordEnd: we, start: WORDS[ws].start, end: gEnd };
|
return { wordStart: ws, wordEnd: we, start: WORDS[ws].start, end: gEnd };
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -210,13 +210,13 @@
|
|||||||
|
|
||||||
tl.to(
|
tl.to(
|
||||||
wordEl,
|
wordEl,
|
||||||
{ clipPath: "inset(0 0% 0 0)", duration: 0.15, ease: "power3.out" },
|
{ clipPath: "inset(0 0% 0 0)", duration: 0.3, ease: "power2.out" },
|
||||||
w.start,
|
w.start,
|
||||||
);
|
);
|
||||||
if (isKW) {
|
if (isKW) {
|
||||||
tl.to(wordEl, { color: "#FFD700", duration: 0.05 }, w.start + 0.1);
|
tl.to(wordEl, { color: "#FFD700", duration: 0.05 }, w.start + 0.1);
|
||||||
}
|
}
|
||||||
tl.to(wordEl, { color: "rgba(255,255,255,0.4)", duration: 0.12 }, w.end);
|
tl.to(wordEl, { color: "rgba(255,255,255,0.4)", duration: 0.2 }, w.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
var wordEls = grp.querySelectorAll(".wp-word");
|
var wordEls = grp.querySelectorAll(".wp-word");
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
wordEls,
|
wordEls,
|
||||||
{
|
{
|
||||||
clipPath: "inset(0 0% 0 100%)",
|
clipPath: "inset(0 0% 0 100%)",
|
||||||
duration: 0.14,
|
duration: 0.25,
|
||||||
stagger: 0.04,
|
stagger: 0.04,
|
||||||
ease: "power2.in",
|
ease: "power2.in",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,5 +12,5 @@
|
|||||||
"type": "hyperframes:snippet"
|
"type": "hyperframes:snippet"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-clip-wipe/preview.mp4?v=1779051416"
|
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-clip-wipe/preview.mp4?v=1779057707"
|
||||||
}
|
}
|
||||||
|
|||||||
+133
-101
@@ -25,7 +25,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #0a0a0a;
|
background: #0a0a0a;
|
||||||
}
|
}
|
||||||
#glitch-rgb {
|
#caption-glitch-rgb {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
@@ -43,8 +43,13 @@
|
|||||||
.gl-overlay {
|
.gl-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: rgba(0, 0, 0, 0.45);
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgba(0, 0, 0, 0.08) 0%,
|
||||||
|
rgba(0, 0, 0, 0.16) 54%,
|
||||||
|
rgba(0, 0, 0, 0.5) 100%
|
||||||
|
);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.gl-scanlines {
|
.gl-scanlines {
|
||||||
@@ -56,9 +61,10 @@
|
|||||||
to bottom,
|
to bottom,
|
||||||
transparent 0px,
|
transparent 0px,
|
||||||
transparent 3px,
|
transparent 3px,
|
||||||
rgba(0, 0, 0, 0.08) 3px,
|
rgba(0, 0, 0, 0.16) 3px,
|
||||||
rgba(0, 0, 0, 0.08) 4px
|
rgba(0, 0, 0, 0.16) 4px
|
||||||
);
|
);
|
||||||
|
opacity: 0.55;
|
||||||
}
|
}
|
||||||
#gl-container {
|
#gl-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -75,7 +81,7 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 24px;
|
gap: 14px;
|
||||||
padding: 0 100px;
|
padding: 0 100px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
@@ -85,17 +91,18 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 88px;
|
font-size: 88px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: rgba(180, 230, 255, 0.45);
|
color: #ffffff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.03em;
|
||||||
line-height: 1;
|
line-height: 0.96;
|
||||||
will-change: transform, text-shadow, color;
|
text-shadow: 0 5px 18px rgba(0, 0, 0, 0.52);
|
||||||
|
will-change: transform, text-shadow;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div
|
<div
|
||||||
id="glitch-rgb"
|
id="caption-glitch-rgb"
|
||||||
data-composition-id="caption-glitch-rgb"
|
data-composition-id="caption-glitch-rgb"
|
||||||
data-start="0"
|
data-start="0"
|
||||||
data-duration="8"
|
data-duration="8"
|
||||||
@@ -121,30 +128,7 @@
|
|||||||
(function () {
|
(function () {
|
||||||
window.__timelines = window.__timelines || {};
|
window.__timelines = window.__timelines || {};
|
||||||
|
|
||||||
var _fitCanvas = document.createElement("canvas");
|
var TRANSCRIPT = [
|
||||||
var _fitCtx = _fitCanvas.getContext("2d");
|
|
||||||
function fitFontSize(text, baseFontSize, fontWeight, fontFamily, maxWidth) {
|
|
||||||
var size = baseFontSize;
|
|
||||||
var minSize = Math.floor(baseFontSize * 0.45);
|
|
||||||
while (size > minSize) {
|
|
||||||
_fitCtx.font = fontWeight + " " + size + "px " + fontFamily;
|
|
||||||
if (_fitCtx.measureText(text).width <= maxWidth) return size;
|
|
||||||
size -= 2;
|
|
||||||
}
|
|
||||||
return minSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mulberry32(seed) {
|
|
||||||
return function () {
|
|
||||||
seed |= 0;
|
|
||||||
seed = (seed + 0x6d2b79f5) | 0;
|
|
||||||
var t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
|
|
||||||
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
||||||
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var WORDS = [
|
|
||||||
{ text: "Every", start: 0.0, end: 0.3 },
|
{ text: "Every", start: 0.0, end: 0.3 },
|
||||||
{ text: "great", start: 0.3, end: 0.55 },
|
{ text: "great", start: 0.3, end: 0.55 },
|
||||||
{ text: "video", start: 0.55, end: 0.85 },
|
{ text: "video", start: 0.55, end: 0.85 },
|
||||||
@@ -175,27 +159,69 @@
|
|||||||
{ text: "cinema.", start: 7.3, end: 7.7 },
|
{ text: "cinema.", start: 7.3, end: 7.7 },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Keywords get white + glow on activation
|
var _fitCanvas = document.createElement("canvas");
|
||||||
var KEYWORDS = new Set([8, 12, 15, 24, 27]); // HyperFrames, HTML, professional, code, cinema.
|
var _fitCtx = _fitCanvas.getContext("2d");
|
||||||
|
function fitFontSize(text, baseFontSize, fontWeight, fontFamily, maxWidth) {
|
||||||
|
var size = baseFontSize;
|
||||||
|
var minSize = Math.floor(baseFontSize * 0.45);
|
||||||
|
while (size > minSize) {
|
||||||
|
_fitCtx.font = fontWeight + " " + size + "px " + fontFamily;
|
||||||
|
if (_fitCtx.measureText(text).width <= maxWidth) return size;
|
||||||
|
size -= 2;
|
||||||
|
}
|
||||||
|
return minSize;
|
||||||
|
}
|
||||||
|
|
||||||
var RAW_GROUPS = [
|
function mulberry32(seed) {
|
||||||
[0, 3],
|
return function () {
|
||||||
[4, 7],
|
seed |= 0;
|
||||||
[8, 8],
|
seed = (seed + 0x6d2b79f5) | 0;
|
||||||
[9, 12],
|
var t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
|
||||||
[13, 15],
|
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
||||||
[16, 16],
|
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
||||||
[17, 19],
|
};
|
||||||
[20, 22],
|
}
|
||||||
[23, 24],
|
|
||||||
[25, 27],
|
function buildGroups(words) {
|
||||||
];
|
var groups = [];
|
||||||
|
var start = 0;
|
||||||
|
var chars = 0;
|
||||||
|
for (var i = 0; i < words.length; i++) {
|
||||||
|
chars += words[i].text.length + 1;
|
||||||
|
var endsSentence = /[.!?]$/.test(words[i].text);
|
||||||
|
var nextGap = i + 1 < words.length ? words[i + 1].start - words[i].end : 0;
|
||||||
|
var full = i - start >= 3 || chars >= 21;
|
||||||
|
if (endsSentence || nextGap > 0.28 || full || i === words.length - 1) {
|
||||||
|
groups.push([start, i]);
|
||||||
|
start = i + 1;
|
||||||
|
chars = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
function glitchPlan(word, nextWord) {
|
||||||
|
var nextStart = nextWord ? nextWord.start : word.end + 0.3;
|
||||||
|
var available = Math.min(word.end, nextStart) - word.start - 0.02;
|
||||||
|
var total = Math.min(0.24, Math.max(0.08, available));
|
||||||
|
return {
|
||||||
|
d1: total * 0.35,
|
||||||
|
d2: total * 0.65,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldAftershock(word) {
|
||||||
|
return /\d|\$|%/.test(word.text) || word.text.replace(/[^\w]/g, "").length >= 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
var RAW_GROUPS = buildGroups(TRANSCRIPT);
|
||||||
var GROUPS = RAW_GROUPS.map(function (pair, gi) {
|
var GROUPS = RAW_GROUPS.map(function (pair, gi) {
|
||||||
var ws = pair[0],
|
var ws = pair[0];
|
||||||
we = pair[1];
|
var we = pair[1];
|
||||||
var nextStart = gi + 1 < RAW_GROUPS.length ? WORDS[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
var nextStart =
|
||||||
var gEnd = Math.min(WORDS[we].end + 0.35, nextStart - 0.05);
|
gi + 1 < RAW_GROUPS.length ? TRANSCRIPT[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
||||||
return { wordStart: ws, wordEnd: we, start: WORDS[ws].start, end: gEnd };
|
var end = Math.min(TRANSCRIPT[we].end + 0.24, nextStart - 0.04);
|
||||||
|
return { wordStart: ws, wordEnd: we, start: TRANSCRIPT[ws].start, end: end };
|
||||||
});
|
});
|
||||||
|
|
||||||
var BASE_FONT = 88;
|
var BASE_FONT = 88;
|
||||||
@@ -203,7 +229,7 @@
|
|||||||
var tl = gsap.timeline({ paused: true });
|
var tl = gsap.timeline({ paused: true });
|
||||||
|
|
||||||
GROUPS.forEach(function (g, gi) {
|
GROUPS.forEach(function (g, gi) {
|
||||||
var groupWords = WORDS.slice(g.wordStart, g.wordEnd + 1);
|
var groupWords = TRANSCRIPT.slice(g.wordStart, g.wordEnd + 1);
|
||||||
var grp = document.createElement("div");
|
var grp = document.createElement("div");
|
||||||
grp.className = "gl-group";
|
grp.className = "gl-group";
|
||||||
grp.id = "gl-grp-" + gi;
|
grp.id = "gl-grp-" + gi;
|
||||||
@@ -230,77 +256,83 @@
|
|||||||
tl.set(grp, { visibility: "visible" }, g.start);
|
tl.set(grp, { visibility: "visible" }, g.start);
|
||||||
tl.fromTo(
|
tl.fromTo(
|
||||||
grp,
|
grp,
|
||||||
{ opacity: 0, x: -8 },
|
{ opacity: 0 },
|
||||||
{ opacity: 1, x: 0, duration: 0.18, ease: "power3.out" },
|
{ opacity: 1, duration: 0.12, ease: "power2.out" },
|
||||||
g.start,
|
g.start,
|
||||||
);
|
);
|
||||||
|
|
||||||
groupWords.forEach(function (w, i) {
|
groupWords.forEach(function (w, i) {
|
||||||
var wi = g.wordStart + i;
|
var wi = g.wordStart + i;
|
||||||
var wordEl = document.getElementById("gl-w-" + wi);
|
var wordEl = document.getElementById("gl-w-" + wi);
|
||||||
var isKW = KEYWORDS.has(wi);
|
var plan = glitchPlan(w, TRANSCRIPT[wi + 1]);
|
||||||
|
|
||||||
var rng = mulberry32(wi * 777 + 13);
|
var rng = mulberry32(wi * 777 + 13);
|
||||||
var j1 = (rng() - 0.5) * 10;
|
var travel = -(8 + rng() * 8);
|
||||||
var j2 = (rng() - 0.5) * 8;
|
var shadowMag = 5 + rng() * 7;
|
||||||
var j3 = (rng() - 0.5) * 6;
|
|
||||||
var shadowMag = 3 + rng() * 4;
|
|
||||||
var sm = shadowMag.toFixed(1);
|
var sm = shadowMag.toFixed(1);
|
||||||
|
var nextWord = TRANSCRIPT[wi + 1];
|
||||||
|
var nextStart = nextWord ? nextWord.start : g.end;
|
||||||
|
var aftershockEnd = Math.min(g.end - 0.08, nextStart - 0.04);
|
||||||
|
|
||||||
tl.to(
|
tl.to(
|
||||||
wordEl,
|
wordEl,
|
||||||
{
|
{
|
||||||
x: j1,
|
x: travel,
|
||||||
color: "#ffffff",
|
textShadow:
|
||||||
textShadow: sm + "px 0 #ff003c, -" + sm + "px 0 #00e5ff",
|
sm + "px 0 #ff003c, -" + sm + "px 0 #00e5ff, 0 5px 18px rgba(0,0,0,0.52)",
|
||||||
duration: 0.045,
|
duration: plan.d1,
|
||||||
ease: "none",
|
ease: "none",
|
||||||
},
|
},
|
||||||
w.start,
|
w.start,
|
||||||
);
|
);
|
||||||
tl.to(
|
|
||||||
wordEl,
|
|
||||||
{
|
|
||||||
x: j2,
|
|
||||||
textShadow:
|
|
||||||
"-" +
|
|
||||||
(shadowMag * 0.7).toFixed(1) +
|
|
||||||
"px 0 #ff003c, " +
|
|
||||||
(shadowMag * 0.7).toFixed(1) +
|
|
||||||
"px 0 #00e5ff",
|
|
||||||
duration: 0.038,
|
|
||||||
ease: "none",
|
|
||||||
},
|
|
||||||
w.start + 0.045,
|
|
||||||
);
|
|
||||||
tl.to(
|
|
||||||
wordEl,
|
|
||||||
{
|
|
||||||
x: j3,
|
|
||||||
textShadow: sm + "px 0 #ff003c, -" + sm + "px 0 #00e5ff",
|
|
||||||
duration: 0.03,
|
|
||||||
ease: "none",
|
|
||||||
},
|
|
||||||
w.start + 0.083,
|
|
||||||
);
|
|
||||||
tl.to(
|
tl.to(
|
||||||
wordEl,
|
wordEl,
|
||||||
{
|
{
|
||||||
x: 0,
|
x: 0,
|
||||||
textShadow: "none",
|
textShadow: "0 5px 18px rgba(0,0,0,0.52)",
|
||||||
color: isKW ? "#ffffff" : "#00e5ff",
|
duration: plan.d2,
|
||||||
duration: 0.05,
|
ease: "power3.out",
|
||||||
ease: "power2.out",
|
|
||||||
},
|
},
|
||||||
w.start + 0.113,
|
w.start + plan.d1,
|
||||||
);
|
|
||||||
tl.to(
|
|
||||||
wordEl,
|
|
||||||
{ color: "rgba(180,230,255,0.4)", textShadow: "none", duration: 0.12 },
|
|
||||||
w.end,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (shouldAftershock(w) && aftershockEnd - w.end > 0.22) {
|
||||||
|
var pulseStart = w.end + 0.08;
|
||||||
|
var pulseIndex = 0;
|
||||||
|
while (pulseStart + 0.1 < aftershockEnd) {
|
||||||
|
var pulseTravel = -(3 + rng() * 5);
|
||||||
|
var pulseShadow = (3 + rng() * 5).toFixed(1);
|
||||||
|
tl.to(
|
||||||
|
wordEl,
|
||||||
|
{
|
||||||
|
x: pulseTravel,
|
||||||
|
textShadow:
|
||||||
|
pulseShadow +
|
||||||
|
"px 0 #ff003c, -" +
|
||||||
|
pulseShadow +
|
||||||
|
"px 0 #00e5ff, 0 5px 18px rgba(0,0,0,0.52)",
|
||||||
|
duration: 0.045,
|
||||||
|
ease: "none",
|
||||||
|
},
|
||||||
|
pulseStart,
|
||||||
|
);
|
||||||
|
tl.to(
|
||||||
|
wordEl,
|
||||||
|
{
|
||||||
|
x: 0,
|
||||||
|
textShadow: "0 5px 18px rgba(0,0,0,0.52)",
|
||||||
|
duration: 0.075,
|
||||||
|
ease: "power3.out",
|
||||||
|
},
|
||||||
|
pulseStart + 0.045,
|
||||||
|
);
|
||||||
|
pulseIndex++;
|
||||||
|
pulseStart += pulseIndex % 2 === 0 ? 0.18 : 0.24;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
tl.to(grp, { opacity: 0, x: 8, duration: 0.15 }, g.end - 0.15);
|
tl.to(grp, { opacity: 0, duration: 0.1, ease: "power2.in" }, g.end - 0.1);
|
||||||
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+133
-101
@@ -25,7 +25,7 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #0a0a0a;
|
background: #0a0a0a;
|
||||||
}
|
}
|
||||||
#glitch-rgb {
|
#caption-glitch-rgb {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
@@ -43,8 +43,13 @@
|
|||||||
.gl-overlay {
|
.gl-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: rgba(0, 0, 0, 0.45);
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgba(0, 0, 0, 0.08) 0%,
|
||||||
|
rgba(0, 0, 0, 0.16) 54%,
|
||||||
|
rgba(0, 0, 0, 0.5) 100%
|
||||||
|
);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.gl-scanlines {
|
.gl-scanlines {
|
||||||
@@ -56,9 +61,10 @@
|
|||||||
to bottom,
|
to bottom,
|
||||||
transparent 0px,
|
transparent 0px,
|
||||||
transparent 3px,
|
transparent 3px,
|
||||||
rgba(0, 0, 0, 0.08) 3px,
|
rgba(0, 0, 0, 0.16) 3px,
|
||||||
rgba(0, 0, 0, 0.08) 4px
|
rgba(0, 0, 0, 0.16) 4px
|
||||||
);
|
);
|
||||||
|
opacity: 0.55;
|
||||||
}
|
}
|
||||||
#gl-container {
|
#gl-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -75,7 +81,7 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 24px;
|
gap: 14px;
|
||||||
padding: 0 100px;
|
padding: 0 100px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
@@ -85,17 +91,18 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 88px;
|
font-size: 88px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: rgba(180, 230, 255, 0.45);
|
color: #ffffff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.03em;
|
||||||
line-height: 1;
|
line-height: 0.96;
|
||||||
will-change: transform, text-shadow, color;
|
text-shadow: 0 5px 18px rgba(0, 0, 0, 0.52);
|
||||||
|
will-change: transform, text-shadow;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div
|
<div
|
||||||
id="glitch-rgb"
|
id="caption-glitch-rgb"
|
||||||
data-composition-id="caption-glitch-rgb"
|
data-composition-id="caption-glitch-rgb"
|
||||||
data-start="0"
|
data-start="0"
|
||||||
data-duration="8"
|
data-duration="8"
|
||||||
@@ -121,30 +128,7 @@
|
|||||||
(function () {
|
(function () {
|
||||||
window.__timelines = window.__timelines || {};
|
window.__timelines = window.__timelines || {};
|
||||||
|
|
||||||
var _fitCanvas = document.createElement("canvas");
|
var TRANSCRIPT = [
|
||||||
var _fitCtx = _fitCanvas.getContext("2d");
|
|
||||||
function fitFontSize(text, baseFontSize, fontWeight, fontFamily, maxWidth) {
|
|
||||||
var size = baseFontSize;
|
|
||||||
var minSize = Math.floor(baseFontSize * 0.45);
|
|
||||||
while (size > minSize) {
|
|
||||||
_fitCtx.font = fontWeight + " " + size + "px " + fontFamily;
|
|
||||||
if (_fitCtx.measureText(text).width <= maxWidth) return size;
|
|
||||||
size -= 2;
|
|
||||||
}
|
|
||||||
return minSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
function mulberry32(seed) {
|
|
||||||
return function () {
|
|
||||||
seed |= 0;
|
|
||||||
seed = (seed + 0x6d2b79f5) | 0;
|
|
||||||
var t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
|
|
||||||
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
|
||||||
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var WORDS = [
|
|
||||||
{ text: "Every", start: 0.0, end: 0.3 },
|
{ text: "Every", start: 0.0, end: 0.3 },
|
||||||
{ text: "great", start: 0.3, end: 0.55 },
|
{ text: "great", start: 0.3, end: 0.55 },
|
||||||
{ text: "video", start: 0.55, end: 0.85 },
|
{ text: "video", start: 0.55, end: 0.85 },
|
||||||
@@ -175,27 +159,69 @@
|
|||||||
{ text: "cinema.", start: 7.3, end: 7.7 },
|
{ text: "cinema.", start: 7.3, end: 7.7 },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Keywords get white + glow on activation
|
var _fitCanvas = document.createElement("canvas");
|
||||||
var KEYWORDS = new Set([8, 12, 15, 24, 27]); // HyperFrames, HTML, professional, code, cinema.
|
var _fitCtx = _fitCanvas.getContext("2d");
|
||||||
|
function fitFontSize(text, baseFontSize, fontWeight, fontFamily, maxWidth) {
|
||||||
|
var size = baseFontSize;
|
||||||
|
var minSize = Math.floor(baseFontSize * 0.45);
|
||||||
|
while (size > minSize) {
|
||||||
|
_fitCtx.font = fontWeight + " " + size + "px " + fontFamily;
|
||||||
|
if (_fitCtx.measureText(text).width <= maxWidth) return size;
|
||||||
|
size -= 2;
|
||||||
|
}
|
||||||
|
return minSize;
|
||||||
|
}
|
||||||
|
|
||||||
var RAW_GROUPS = [
|
function mulberry32(seed) {
|
||||||
[0, 3],
|
return function () {
|
||||||
[4, 7],
|
seed |= 0;
|
||||||
[8, 8],
|
seed = (seed + 0x6d2b79f5) | 0;
|
||||||
[9, 12],
|
var t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
|
||||||
[13, 15],
|
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
|
||||||
[16, 16],
|
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
|
||||||
[17, 19],
|
};
|
||||||
[20, 22],
|
}
|
||||||
[23, 24],
|
|
||||||
[25, 27],
|
function buildGroups(words) {
|
||||||
];
|
var groups = [];
|
||||||
|
var start = 0;
|
||||||
|
var chars = 0;
|
||||||
|
for (var i = 0; i < words.length; i++) {
|
||||||
|
chars += words[i].text.length + 1;
|
||||||
|
var endsSentence = /[.!?]$/.test(words[i].text);
|
||||||
|
var nextGap = i + 1 < words.length ? words[i + 1].start - words[i].end : 0;
|
||||||
|
var full = i - start >= 3 || chars >= 21;
|
||||||
|
if (endsSentence || nextGap > 0.28 || full || i === words.length - 1) {
|
||||||
|
groups.push([start, i]);
|
||||||
|
start = i + 1;
|
||||||
|
chars = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
function glitchPlan(word, nextWord) {
|
||||||
|
var nextStart = nextWord ? nextWord.start : word.end + 0.3;
|
||||||
|
var available = Math.min(word.end, nextStart) - word.start - 0.02;
|
||||||
|
var total = Math.min(0.24, Math.max(0.08, available));
|
||||||
|
return {
|
||||||
|
d1: total * 0.35,
|
||||||
|
d2: total * 0.65,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldAftershock(word) {
|
||||||
|
return /\d|\$|%/.test(word.text) || word.text.replace(/[^\w]/g, "").length >= 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
var RAW_GROUPS = buildGroups(TRANSCRIPT);
|
||||||
var GROUPS = RAW_GROUPS.map(function (pair, gi) {
|
var GROUPS = RAW_GROUPS.map(function (pair, gi) {
|
||||||
var ws = pair[0],
|
var ws = pair[0];
|
||||||
we = pair[1];
|
var we = pair[1];
|
||||||
var nextStart = gi + 1 < RAW_GROUPS.length ? WORDS[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
var nextStart =
|
||||||
var gEnd = Math.min(WORDS[we].end + 0.35, nextStart - 0.05);
|
gi + 1 < RAW_GROUPS.length ? TRANSCRIPT[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
||||||
return { wordStart: ws, wordEnd: we, start: WORDS[ws].start, end: gEnd };
|
var end = Math.min(TRANSCRIPT[we].end + 0.24, nextStart - 0.04);
|
||||||
|
return { wordStart: ws, wordEnd: we, start: TRANSCRIPT[ws].start, end: end };
|
||||||
});
|
});
|
||||||
|
|
||||||
var BASE_FONT = 88;
|
var BASE_FONT = 88;
|
||||||
@@ -203,7 +229,7 @@
|
|||||||
var tl = gsap.timeline({ paused: true });
|
var tl = gsap.timeline({ paused: true });
|
||||||
|
|
||||||
GROUPS.forEach(function (g, gi) {
|
GROUPS.forEach(function (g, gi) {
|
||||||
var groupWords = WORDS.slice(g.wordStart, g.wordEnd + 1);
|
var groupWords = TRANSCRIPT.slice(g.wordStart, g.wordEnd + 1);
|
||||||
var grp = document.createElement("div");
|
var grp = document.createElement("div");
|
||||||
grp.className = "gl-group";
|
grp.className = "gl-group";
|
||||||
grp.id = "gl-grp-" + gi;
|
grp.id = "gl-grp-" + gi;
|
||||||
@@ -230,77 +256,83 @@
|
|||||||
tl.set(grp, { visibility: "visible" }, g.start);
|
tl.set(grp, { visibility: "visible" }, g.start);
|
||||||
tl.fromTo(
|
tl.fromTo(
|
||||||
grp,
|
grp,
|
||||||
{ opacity: 0, x: -8 },
|
{ opacity: 0 },
|
||||||
{ opacity: 1, x: 0, duration: 0.18, ease: "power3.out" },
|
{ opacity: 1, duration: 0.12, ease: "power2.out" },
|
||||||
g.start,
|
g.start,
|
||||||
);
|
);
|
||||||
|
|
||||||
groupWords.forEach(function (w, i) {
|
groupWords.forEach(function (w, i) {
|
||||||
var wi = g.wordStart + i;
|
var wi = g.wordStart + i;
|
||||||
var wordEl = document.getElementById("gl-w-" + wi);
|
var wordEl = document.getElementById("gl-w-" + wi);
|
||||||
var isKW = KEYWORDS.has(wi);
|
var plan = glitchPlan(w, TRANSCRIPT[wi + 1]);
|
||||||
|
|
||||||
var rng = mulberry32(wi * 777 + 13);
|
var rng = mulberry32(wi * 777 + 13);
|
||||||
var j1 = (rng() - 0.5) * 10;
|
var travel = -(8 + rng() * 8);
|
||||||
var j2 = (rng() - 0.5) * 8;
|
var shadowMag = 5 + rng() * 7;
|
||||||
var j3 = (rng() - 0.5) * 6;
|
|
||||||
var shadowMag = 3 + rng() * 4;
|
|
||||||
var sm = shadowMag.toFixed(1);
|
var sm = shadowMag.toFixed(1);
|
||||||
|
var nextWord = TRANSCRIPT[wi + 1];
|
||||||
|
var nextStart = nextWord ? nextWord.start : g.end;
|
||||||
|
var aftershockEnd = Math.min(g.end - 0.08, nextStart - 0.04);
|
||||||
|
|
||||||
tl.to(
|
tl.to(
|
||||||
wordEl,
|
wordEl,
|
||||||
{
|
{
|
||||||
x: j1,
|
x: travel,
|
||||||
color: "#ffffff",
|
textShadow:
|
||||||
textShadow: sm + "px 0 #ff003c, -" + sm + "px 0 #00e5ff",
|
sm + "px 0 #ff003c, -" + sm + "px 0 #00e5ff, 0 5px 18px rgba(0,0,0,0.52)",
|
||||||
duration: 0.045,
|
duration: plan.d1,
|
||||||
ease: "none",
|
ease: "none",
|
||||||
},
|
},
|
||||||
w.start,
|
w.start,
|
||||||
);
|
);
|
||||||
tl.to(
|
|
||||||
wordEl,
|
|
||||||
{
|
|
||||||
x: j2,
|
|
||||||
textShadow:
|
|
||||||
"-" +
|
|
||||||
(shadowMag * 0.7).toFixed(1) +
|
|
||||||
"px 0 #ff003c, " +
|
|
||||||
(shadowMag * 0.7).toFixed(1) +
|
|
||||||
"px 0 #00e5ff",
|
|
||||||
duration: 0.038,
|
|
||||||
ease: "none",
|
|
||||||
},
|
|
||||||
w.start + 0.045,
|
|
||||||
);
|
|
||||||
tl.to(
|
|
||||||
wordEl,
|
|
||||||
{
|
|
||||||
x: j3,
|
|
||||||
textShadow: sm + "px 0 #ff003c, -" + sm + "px 0 #00e5ff",
|
|
||||||
duration: 0.03,
|
|
||||||
ease: "none",
|
|
||||||
},
|
|
||||||
w.start + 0.083,
|
|
||||||
);
|
|
||||||
tl.to(
|
tl.to(
|
||||||
wordEl,
|
wordEl,
|
||||||
{
|
{
|
||||||
x: 0,
|
x: 0,
|
||||||
textShadow: "none",
|
textShadow: "0 5px 18px rgba(0,0,0,0.52)",
|
||||||
color: isKW ? "#ffffff" : "#00e5ff",
|
duration: plan.d2,
|
||||||
duration: 0.05,
|
ease: "power3.out",
|
||||||
ease: "power2.out",
|
|
||||||
},
|
},
|
||||||
w.start + 0.113,
|
w.start + plan.d1,
|
||||||
);
|
|
||||||
tl.to(
|
|
||||||
wordEl,
|
|
||||||
{ color: "rgba(180,230,255,0.4)", textShadow: "none", duration: 0.12 },
|
|
||||||
w.end,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (shouldAftershock(w) && aftershockEnd - w.end > 0.22) {
|
||||||
|
var pulseStart = w.end + 0.08;
|
||||||
|
var pulseIndex = 0;
|
||||||
|
while (pulseStart + 0.1 < aftershockEnd) {
|
||||||
|
var pulseTravel = -(3 + rng() * 5);
|
||||||
|
var pulseShadow = (3 + rng() * 5).toFixed(1);
|
||||||
|
tl.to(
|
||||||
|
wordEl,
|
||||||
|
{
|
||||||
|
x: pulseTravel,
|
||||||
|
textShadow:
|
||||||
|
pulseShadow +
|
||||||
|
"px 0 #ff003c, -" +
|
||||||
|
pulseShadow +
|
||||||
|
"px 0 #00e5ff, 0 5px 18px rgba(0,0,0,0.52)",
|
||||||
|
duration: 0.045,
|
||||||
|
ease: "none",
|
||||||
|
},
|
||||||
|
pulseStart,
|
||||||
|
);
|
||||||
|
tl.to(
|
||||||
|
wordEl,
|
||||||
|
{
|
||||||
|
x: 0,
|
||||||
|
textShadow: "0 5px 18px rgba(0,0,0,0.52)",
|
||||||
|
duration: 0.075,
|
||||||
|
ease: "power3.out",
|
||||||
|
},
|
||||||
|
pulseStart + 0.045,
|
||||||
|
);
|
||||||
|
pulseIndex++;
|
||||||
|
pulseStart += pulseIndex % 2 === 0 ? 0.18 : 0.24;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
tl.to(grp, { opacity: 0, x: 8, duration: 0.15 }, g.end - 0.15);
|
tl.to(grp, { opacity: 0, duration: 0.1, ease: "power2.in" }, g.end - 0.1);
|
||||||
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -12,5 +12,5 @@
|
|||||||
"type": "hyperframes:snippet"
|
"type": "hyperframes:snippet"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-glitch-rgb/preview.mp4?v=1779051416"
|
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-glitch-rgb/preview.mp4?v=1779065047"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,11 +233,11 @@
|
|||||||
groupWords.forEach(function (w, i) {
|
groupWords.forEach(function (w, i) {
|
||||||
var wi = g.wordStart + i;
|
var wi = g.wordStart + i;
|
||||||
var el = document.getElementById("gr-w-" + wi);
|
var el = document.getElementById("gr-w-" + wi);
|
||||||
tl.to(el, { opacity: 1, scale: 1.1, duration: 0.08 }, w.start);
|
tl.to(el, { opacity: 1, scale: 1.1, duration: 0.15 }, w.start);
|
||||||
tl.to(el, { opacity: 0.3, scale: 1, duration: 0.08 }, w.end);
|
tl.to(el, { opacity: 0.3, scale: 1, duration: 0.15 }, w.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
tl.to(grp, { y: -26, opacity: 0, duration: 0.18 }, g.end - 0.18);
|
tl.to(grp, { y: -26, opacity: 0, duration: 0.25 }, g.end - 0.25);
|
||||||
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -233,11 +233,11 @@
|
|||||||
groupWords.forEach(function (w, i) {
|
groupWords.forEach(function (w, i) {
|
||||||
var wi = g.wordStart + i;
|
var wi = g.wordStart + i;
|
||||||
var el = document.getElementById("gr-w-" + wi);
|
var el = document.getElementById("gr-w-" + wi);
|
||||||
tl.to(el, { opacity: 1, scale: 1.1, duration: 0.08 }, w.start);
|
tl.to(el, { opacity: 1, scale: 1.1, duration: 0.15 }, w.start);
|
||||||
tl.to(el, { opacity: 0.3, scale: 1, duration: 0.08 }, w.end);
|
tl.to(el, { opacity: 0.3, scale: 1, duration: 0.15 }, w.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
tl.to(grp, { y: -26, opacity: 0, duration: 0.18 }, g.end - 0.18);
|
tl.to(grp, { y: -26, opacity: 0, duration: 0.25 }, g.end - 0.25);
|
||||||
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -12,5 +12,5 @@
|
|||||||
"type": "hyperframes:snippet"
|
"type": "hyperframes:snippet"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-gradient-fill/preview.mp4?v=1779051416"
|
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-gradient-fill/preview.mp4?v=1779057707"
|
||||||
}
|
}
|
||||||
|
|||||||
+106
-91
@@ -3,11 +3,11 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=1920, height=1080" />
|
<meta name="viewport" content="width=1920, height=1080" />
|
||||||
<title>Typewriter</title>
|
<title>Highlight</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@700&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@800&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||||||
@@ -23,16 +23,16 @@
|
|||||||
height: 1080px;
|
height: 1080px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #000;
|
background: #0a0a0a;
|
||||||
}
|
}
|
||||||
#typewriter {
|
#highlight {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #000;
|
background: #0a0a0a;
|
||||||
}
|
}
|
||||||
#tw-video {
|
#hl-video {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
@@ -40,78 +40,77 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
.tw-overlay {
|
.hl-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: rgba(0, 0, 0, 0.85);
|
background: rgba(0, 0, 0, 0.4);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
#tw-container {
|
#hl-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.tw-group {
|
.hl-group {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 120px;
|
bottom: 140px;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 24px;
|
gap: 8px;
|
||||||
padding: 0 80px;
|
padding: 0 100px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
.tw-word {
|
.hl-word {
|
||||||
font-family: "JetBrains Mono", monospace;
|
font-family: "Montserrat", sans-serif;
|
||||||
font-weight: 700;
|
font-weight: 800;
|
||||||
font-size: 76px;
|
font-size: 80px;
|
||||||
color: #00ff41;
|
text-transform: uppercase;
|
||||||
text-shadow: 0 0 12px rgba(0, 255, 65, 0.5);
|
color: #ffffff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.02em;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
white-space: nowrap;
|
position: relative;
|
||||||
|
padding: 6px 12px 8px;
|
||||||
|
text-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
|
||||||
|
transform-origin: 50% 58%;
|
||||||
|
will-change: transform, filter;
|
||||||
}
|
}
|
||||||
.tw-char {
|
.hl-word-bg {
|
||||||
display: none;
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: linear-gradient(135deg, #ff1745 0%, #df1238 100%);
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 12px 30px rgba(229, 20, 58, 0.32);
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: 0% 50%;
|
||||||
|
z-index: -1;
|
||||||
}
|
}
|
||||||
.tw-cursor {
|
.hl-word-text {
|
||||||
font-family: "JetBrains Mono", monospace;
|
position: relative;
|
||||||
font-weight: 700;
|
z-index: 1;
|
||||||
font-size: 76px;
|
|
||||||
color: #00ff41;
|
|
||||||
text-shadow: 0 0 12px rgba(0, 255, 65, 0.5);
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div
|
<div
|
||||||
id="typewriter"
|
id="highlight"
|
||||||
data-composition-id="caption-typewriter"
|
data-composition-id="caption-highlight"
|
||||||
data-start="0"
|
data-start="0"
|
||||||
data-duration="8"
|
data-duration="8"
|
||||||
data-fps="30"
|
data-fps="30"
|
||||||
data-width="1920"
|
data-width="1920"
|
||||||
data-height="1080"
|
data-height="1080"
|
||||||
>
|
>
|
||||||
<video
|
<div class="hl-overlay"></div>
|
||||||
id="tw-video"
|
<div id="hl-container"></div>
|
||||||
muted
|
|
||||||
playsinline
|
|
||||||
data-start="0"
|
|
||||||
data-duration="8"
|
|
||||||
data-track-index="0"
|
|
||||||
data-has-audio="false"
|
|
||||||
></video>
|
|
||||||
<div class="tw-overlay"></div>
|
|
||||||
<div id="tw-container"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -162,82 +161,98 @@
|
|||||||
{ text: "cinema.", start: 7.3, end: 7.7 },
|
{ text: "cinema.", start: 7.3, end: 7.7 },
|
||||||
];
|
];
|
||||||
|
|
||||||
var GROUPS = [
|
var RAW_GROUPS = [
|
||||||
{ wordStart: 0, wordEnd: 3, start: 0.0, end: 1.1 },
|
[0, 3],
|
||||||
{ wordStart: 4, wordEnd: 7, start: 1.1, end: 2.05 },
|
[4, 7],
|
||||||
{ wordStart: 8, wordEnd: 8, start: 2.1, end: 2.6 },
|
[8, 8],
|
||||||
{ wordStart: 9, wordEnd: 12, start: 2.65, end: 3.5 },
|
[9, 12],
|
||||||
{ wordStart: 13, wordEnd: 15, start: 3.55, end: 4.4 },
|
[13, 15],
|
||||||
{ wordStart: 16, wordEnd: 16, start: 3.95, end: 4.75 },
|
[16, 16],
|
||||||
{ wordStart: 17, wordEnd: 19, start: 4.9, end: 5.4 },
|
[17, 19],
|
||||||
{ wordStart: 20, wordEnd: 22, start: 5.65, end: 6.2 },
|
[20, 22],
|
||||||
{ wordStart: 23, wordEnd: 24, start: 6.35, end: 6.75 },
|
[23, 24],
|
||||||
{ wordStart: 25, wordEnd: 27, start: 6.8, end: 7.8 },
|
[25, 27],
|
||||||
];
|
];
|
||||||
|
var GROUPS = RAW_GROUPS.map(function (pair, gi) {
|
||||||
|
var ws = pair[0],
|
||||||
|
we = pair[1];
|
||||||
|
var nextStart = gi + 1 < RAW_GROUPS.length ? WORDS[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
||||||
|
var gEnd = Math.min(WORDS[we].end + 0.5, nextStart - 0.05);
|
||||||
|
return { wordStart: ws, wordEnd: we, start: WORDS[ws].start, end: gEnd };
|
||||||
|
});
|
||||||
|
|
||||||
var container = document.getElementById("tw-container");
|
var container = document.getElementById("hl-container");
|
||||||
var tl = gsap.timeline({ paused: true });
|
var tl = gsap.timeline({ paused: true });
|
||||||
|
|
||||||
GROUPS.forEach(function (g, gi) {
|
GROUPS.forEach(function (g, gi) {
|
||||||
var groupWords = WORDS.slice(g.wordStart, g.wordEnd + 1);
|
var groupWords = WORDS.slice(g.wordStart, g.wordEnd + 1);
|
||||||
|
var grp = document.createElement("div");
|
||||||
|
grp.className = "hl-group";
|
||||||
|
grp.id = "hl-grp-" + gi;
|
||||||
|
|
||||||
var groupText = groupWords
|
var groupText = groupWords
|
||||||
.map(function (w) {
|
.map(function (w) {
|
||||||
return w.text;
|
return w.text.toUpperCase();
|
||||||
})
|
})
|
||||||
.join(" ");
|
.join(" ");
|
||||||
var fontSize = fitFontSize(groupText, 76, "700", "'JetBrains Mono', monospace", 1760);
|
var computedSize = fitFontSize(groupText, 80, "800", "Montserrat", 1620);
|
||||||
var grp = document.createElement("div");
|
|
||||||
grp.className = "tw-group";
|
|
||||||
grp.id = "tw-grp-" + gi;
|
|
||||||
|
|
||||||
groupWords.forEach(function (w, i) {
|
groupWords.forEach(function (w, i) {
|
||||||
var wi = g.wordStart + i;
|
var wi = g.wordStart + i;
|
||||||
var wordWrap = document.createElement("span");
|
var wordEl = document.createElement("span");
|
||||||
wordWrap.className = "tw-word";
|
wordEl.className = "hl-word";
|
||||||
wordWrap.id = "tw-w-" + wi;
|
wordEl.id = "hl-w-" + wi;
|
||||||
wordWrap.style.fontSize = fontSize + "px";
|
wordEl.style.fontSize = computedSize + "px";
|
||||||
|
|
||||||
w.text.split("").forEach(function (c, ci) {
|
var bgEl = document.createElement("span");
|
||||||
var charEl = document.createElement("span");
|
bgEl.className = "hl-word-bg";
|
||||||
charEl.className = "tw-char";
|
bgEl.id = "hl-bg-" + wi;
|
||||||
charEl.id = "tw-c-" + wi + "-" + ci;
|
|
||||||
charEl.textContent = c;
|
|
||||||
wordWrap.appendChild(charEl);
|
|
||||||
});
|
|
||||||
|
|
||||||
var cursor = document.createElement("span");
|
var textEl = document.createElement("span");
|
||||||
cursor.className = "tw-cursor";
|
textEl.className = "hl-word-text";
|
||||||
cursor.id = "tw-cur-" + wi;
|
textEl.textContent = w.text.toUpperCase();
|
||||||
cursor.textContent = "_";
|
|
||||||
cursor.style.fontSize = fontSize + "px";
|
wordEl.appendChild(bgEl);
|
||||||
wordWrap.appendChild(cursor);
|
wordEl.appendChild(textEl);
|
||||||
grp.appendChild(wordWrap);
|
grp.appendChild(wordEl);
|
||||||
});
|
});
|
||||||
|
|
||||||
container.appendChild(grp);
|
container.appendChild(grp);
|
||||||
|
|
||||||
tl.set(grp, { visibility: "visible", opacity: 1 }, g.start);
|
tl.set(grp, { visibility: "visible" }, g.start);
|
||||||
|
tl.fromTo(
|
||||||
|
grp,
|
||||||
|
{ opacity: 0 },
|
||||||
|
{ opacity: 1, duration: 0.12, ease: "power2.out" },
|
||||||
|
g.start,
|
||||||
|
);
|
||||||
|
|
||||||
groupWords.forEach(function (w, i) {
|
groupWords.forEach(function (w, i) {
|
||||||
var wi = g.wordStart + i;
|
var wi = g.wordStart + i;
|
||||||
var chars = w.text.split("");
|
var bgEl = document.getElementById("hl-bg-" + wi);
|
||||||
var wordDuration = Math.max(w.end - w.start, 0.1);
|
var wordEl = document.getElementById("hl-w-" + wi);
|
||||||
var charCount = chars.length;
|
|
||||||
var cursorEl = document.getElementById("tw-cur-" + wi);
|
|
||||||
|
|
||||||
tl.set(cursorEl, { display: "inline" }, w.start);
|
tl.to(bgEl, { opacity: 1, scaleX: 1, duration: 0.15, ease: "power2.out" }, w.start);
|
||||||
chars.forEach(function (c, ci) {
|
tl.to(
|
||||||
var charEl = document.getElementById("tw-c-" + wi + "-" + ci);
|
wordEl,
|
||||||
tl.set(charEl, { display: "inline" }, w.start + ci * (wordDuration / charCount));
|
{ filter: "brightness(1.05)", duration: 0.08, ease: "power2.out" },
|
||||||
});
|
w.start,
|
||||||
tl.set(cursorEl, { display: "none" }, w.end);
|
);
|
||||||
|
tl.to(
|
||||||
|
wordEl,
|
||||||
|
{ filter: "brightness(1)", duration: 0.16, ease: "power2.out" },
|
||||||
|
w.start + 0.08,
|
||||||
|
);
|
||||||
|
tl.to(bgEl, { opacity: 0, scaleX: 1.02, duration: 0.1, ease: "power2.in" }, w.end);
|
||||||
|
tl.set(bgEl, { scaleX: 0 }, w.end + 0.1);
|
||||||
});
|
});
|
||||||
|
|
||||||
tl.to(grp, { opacity: 0, duration: 0.2 }, g.end - 0.2);
|
tl.to(grp, { opacity: 0, duration: 0.1, ease: "power2.in" }, g.end - 0.1);
|
||||||
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.__timelines["caption-typewriter"] = tl;
|
tl.seek(0);
|
||||||
|
window.__timelines["caption-highlight"] = tl;
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
Vendored
+106
-91
@@ -3,11 +3,11 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=1920, height=1080" />
|
<meta name="viewport" content="width=1920, height=1080" />
|
||||||
<title>Typewriter</title>
|
<title>Highlight</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@700&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@800&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||||||
@@ -23,16 +23,16 @@
|
|||||||
height: 1080px;
|
height: 1080px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #000;
|
background: #0a0a0a;
|
||||||
}
|
}
|
||||||
#typewriter {
|
#highlight {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 1920px;
|
width: 1920px;
|
||||||
height: 1080px;
|
height: 1080px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #000;
|
background: #0a0a0a;
|
||||||
}
|
}
|
||||||
#tw-video {
|
#hl-video {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
@@ -40,78 +40,77 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
.tw-overlay {
|
.hl-overlay {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background: rgba(0, 0, 0, 0.85);
|
background: rgba(0, 0, 0, 0.4);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
#tw-container {
|
#hl-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.tw-group {
|
.hl-group {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 120px;
|
bottom: 140px;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 24px;
|
gap: 8px;
|
||||||
padding: 0 80px;
|
padding: 0 100px;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
.tw-word {
|
.hl-word {
|
||||||
font-family: "JetBrains Mono", monospace;
|
font-family: "Montserrat", sans-serif;
|
||||||
font-weight: 700;
|
font-weight: 800;
|
||||||
font-size: 76px;
|
font-size: 80px;
|
||||||
color: #00ff41;
|
text-transform: uppercase;
|
||||||
text-shadow: 0 0 12px rgba(0, 255, 65, 0.5);
|
color: #ffffff;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.02em;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
white-space: nowrap;
|
position: relative;
|
||||||
|
padding: 6px 12px 8px;
|
||||||
|
text-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
|
||||||
|
transform-origin: 50% 58%;
|
||||||
|
will-change: transform, filter;
|
||||||
}
|
}
|
||||||
.tw-char {
|
.hl-word-bg {
|
||||||
display: none;
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: linear-gradient(135deg, #ff1745 0%, #df1238 100%);
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 12px 30px rgba(229, 20, 58, 0.32);
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleX(0);
|
||||||
|
transform-origin: 0% 50%;
|
||||||
|
z-index: -1;
|
||||||
}
|
}
|
||||||
.tw-cursor {
|
.hl-word-text {
|
||||||
font-family: "JetBrains Mono", monospace;
|
position: relative;
|
||||||
font-weight: 700;
|
z-index: 1;
|
||||||
font-size: 76px;
|
|
||||||
color: #00ff41;
|
|
||||||
text-shadow: 0 0 12px rgba(0, 255, 65, 0.5);
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div
|
<div
|
||||||
id="typewriter"
|
id="highlight"
|
||||||
data-composition-id="caption-typewriter"
|
data-composition-id="caption-highlight"
|
||||||
data-start="0"
|
data-start="0"
|
||||||
data-duration="8"
|
data-duration="8"
|
||||||
data-fps="30"
|
data-fps="30"
|
||||||
data-width="1920"
|
data-width="1920"
|
||||||
data-height="1080"
|
data-height="1080"
|
||||||
>
|
>
|
||||||
<video
|
<div class="hl-overlay"></div>
|
||||||
id="tw-video"
|
<div id="hl-container"></div>
|
||||||
muted
|
|
||||||
playsinline
|
|
||||||
data-start="0"
|
|
||||||
data-duration="8"
|
|
||||||
data-track-index="0"
|
|
||||||
data-has-audio="false"
|
|
||||||
></video>
|
|
||||||
<div class="tw-overlay"></div>
|
|
||||||
<div id="tw-container"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -162,82 +161,98 @@
|
|||||||
{ text: "cinema.", start: 7.3, end: 7.7 },
|
{ text: "cinema.", start: 7.3, end: 7.7 },
|
||||||
];
|
];
|
||||||
|
|
||||||
var GROUPS = [
|
var RAW_GROUPS = [
|
||||||
{ wordStart: 0, wordEnd: 3, start: 0.0, end: 1.1 },
|
[0, 3],
|
||||||
{ wordStart: 4, wordEnd: 7, start: 1.1, end: 2.05 },
|
[4, 7],
|
||||||
{ wordStart: 8, wordEnd: 8, start: 2.1, end: 2.6 },
|
[8, 8],
|
||||||
{ wordStart: 9, wordEnd: 12, start: 2.65, end: 3.5 },
|
[9, 12],
|
||||||
{ wordStart: 13, wordEnd: 15, start: 3.55, end: 4.4 },
|
[13, 15],
|
||||||
{ wordStart: 16, wordEnd: 16, start: 3.95, end: 4.75 },
|
[16, 16],
|
||||||
{ wordStart: 17, wordEnd: 19, start: 4.9, end: 5.4 },
|
[17, 19],
|
||||||
{ wordStart: 20, wordEnd: 22, start: 5.65, end: 6.2 },
|
[20, 22],
|
||||||
{ wordStart: 23, wordEnd: 24, start: 6.35, end: 6.75 },
|
[23, 24],
|
||||||
{ wordStart: 25, wordEnd: 27, start: 6.8, end: 7.8 },
|
[25, 27],
|
||||||
];
|
];
|
||||||
|
var GROUPS = RAW_GROUPS.map(function (pair, gi) {
|
||||||
|
var ws = pair[0],
|
||||||
|
we = pair[1];
|
||||||
|
var nextStart = gi + 1 < RAW_GROUPS.length ? WORDS[RAW_GROUPS[gi + 1][0]].start : 8.0;
|
||||||
|
var gEnd = Math.min(WORDS[we].end + 0.5, nextStart - 0.05);
|
||||||
|
return { wordStart: ws, wordEnd: we, start: WORDS[ws].start, end: gEnd };
|
||||||
|
});
|
||||||
|
|
||||||
var container = document.getElementById("tw-container");
|
var container = document.getElementById("hl-container");
|
||||||
var tl = gsap.timeline({ paused: true });
|
var tl = gsap.timeline({ paused: true });
|
||||||
|
|
||||||
GROUPS.forEach(function (g, gi) {
|
GROUPS.forEach(function (g, gi) {
|
||||||
var groupWords = WORDS.slice(g.wordStart, g.wordEnd + 1);
|
var groupWords = WORDS.slice(g.wordStart, g.wordEnd + 1);
|
||||||
|
var grp = document.createElement("div");
|
||||||
|
grp.className = "hl-group";
|
||||||
|
grp.id = "hl-grp-" + gi;
|
||||||
|
|
||||||
var groupText = groupWords
|
var groupText = groupWords
|
||||||
.map(function (w) {
|
.map(function (w) {
|
||||||
return w.text;
|
return w.text.toUpperCase();
|
||||||
})
|
})
|
||||||
.join(" ");
|
.join(" ");
|
||||||
var fontSize = fitFontSize(groupText, 76, "700", "'JetBrains Mono', monospace", 1760);
|
var computedSize = fitFontSize(groupText, 80, "800", "Montserrat", 1620);
|
||||||
var grp = document.createElement("div");
|
|
||||||
grp.className = "tw-group";
|
|
||||||
grp.id = "tw-grp-" + gi;
|
|
||||||
|
|
||||||
groupWords.forEach(function (w, i) {
|
groupWords.forEach(function (w, i) {
|
||||||
var wi = g.wordStart + i;
|
var wi = g.wordStart + i;
|
||||||
var wordWrap = document.createElement("span");
|
var wordEl = document.createElement("span");
|
||||||
wordWrap.className = "tw-word";
|
wordEl.className = "hl-word";
|
||||||
wordWrap.id = "tw-w-" + wi;
|
wordEl.id = "hl-w-" + wi;
|
||||||
wordWrap.style.fontSize = fontSize + "px";
|
wordEl.style.fontSize = computedSize + "px";
|
||||||
|
|
||||||
w.text.split("").forEach(function (c, ci) {
|
var bgEl = document.createElement("span");
|
||||||
var charEl = document.createElement("span");
|
bgEl.className = "hl-word-bg";
|
||||||
charEl.className = "tw-char";
|
bgEl.id = "hl-bg-" + wi;
|
||||||
charEl.id = "tw-c-" + wi + "-" + ci;
|
|
||||||
charEl.textContent = c;
|
|
||||||
wordWrap.appendChild(charEl);
|
|
||||||
});
|
|
||||||
|
|
||||||
var cursor = document.createElement("span");
|
var textEl = document.createElement("span");
|
||||||
cursor.className = "tw-cursor";
|
textEl.className = "hl-word-text";
|
||||||
cursor.id = "tw-cur-" + wi;
|
textEl.textContent = w.text.toUpperCase();
|
||||||
cursor.textContent = "_";
|
|
||||||
cursor.style.fontSize = fontSize + "px";
|
wordEl.appendChild(bgEl);
|
||||||
wordWrap.appendChild(cursor);
|
wordEl.appendChild(textEl);
|
||||||
grp.appendChild(wordWrap);
|
grp.appendChild(wordEl);
|
||||||
});
|
});
|
||||||
|
|
||||||
container.appendChild(grp);
|
container.appendChild(grp);
|
||||||
|
|
||||||
tl.set(grp, { visibility: "visible", opacity: 1 }, g.start);
|
tl.set(grp, { visibility: "visible" }, g.start);
|
||||||
|
tl.fromTo(
|
||||||
|
grp,
|
||||||
|
{ opacity: 0 },
|
||||||
|
{ opacity: 1, duration: 0.12, ease: "power2.out" },
|
||||||
|
g.start,
|
||||||
|
);
|
||||||
|
|
||||||
groupWords.forEach(function (w, i) {
|
groupWords.forEach(function (w, i) {
|
||||||
var wi = g.wordStart + i;
|
var wi = g.wordStart + i;
|
||||||
var chars = w.text.split("");
|
var bgEl = document.getElementById("hl-bg-" + wi);
|
||||||
var wordDuration = Math.max(w.end - w.start, 0.1);
|
var wordEl = document.getElementById("hl-w-" + wi);
|
||||||
var charCount = chars.length;
|
|
||||||
var cursorEl = document.getElementById("tw-cur-" + wi);
|
|
||||||
|
|
||||||
tl.set(cursorEl, { display: "inline" }, w.start);
|
tl.to(bgEl, { opacity: 1, scaleX: 1, duration: 0.15, ease: "power2.out" }, w.start);
|
||||||
chars.forEach(function (c, ci) {
|
tl.to(
|
||||||
var charEl = document.getElementById("tw-c-" + wi + "-" + ci);
|
wordEl,
|
||||||
tl.set(charEl, { display: "inline" }, w.start + ci * (wordDuration / charCount));
|
{ filter: "brightness(1.05)", duration: 0.08, ease: "power2.out" },
|
||||||
});
|
w.start,
|
||||||
tl.set(cursorEl, { display: "none" }, w.end);
|
);
|
||||||
|
tl.to(
|
||||||
|
wordEl,
|
||||||
|
{ filter: "brightness(1)", duration: 0.16, ease: "power2.out" },
|
||||||
|
w.start + 0.08,
|
||||||
|
);
|
||||||
|
tl.to(bgEl, { opacity: 0, scaleX: 1.02, duration: 0.1, ease: "power2.in" }, w.end);
|
||||||
|
tl.set(bgEl, { scaleX: 0 }, w.end + 0.1);
|
||||||
});
|
});
|
||||||
|
|
||||||
tl.to(grp, { opacity: 0, duration: 0.2 }, g.end - 0.2);
|
tl.to(grp, { opacity: 0, duration: 0.1, ease: "power2.in" }, g.end - 0.1);
|
||||||
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
tl.set(grp, { opacity: 0, visibility: "hidden" }, g.end);
|
||||||
});
|
});
|
||||||
|
|
||||||
window.__timelines["caption-typewriter"] = tl;
|
tl.seek(0);
|
||||||
|
window.__timelines["caption-highlight"] = tl;
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
|
||||||
|
"name": "caption-highlight",
|
||||||
|
"type": "hyperframes:component",
|
||||||
|
"title": "Highlight",
|
||||||
|
"description": "Red background sweep behind each active word, TikTok-style",
|
||||||
|
"tags": ["captions", "caption-style", "highlight", "social", "tiktok"],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "caption-highlight.html",
|
||||||
|
"target": "compositions/components/caption-highlight.html",
|
||||||
|
"type": "hyperframes:snippet"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-highlight/preview.mp4"
|
||||||
|
}
|
||||||
@@ -181,16 +181,16 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
var GROUPS = [
|
var GROUPS = [
|
||||||
{ wordStart: 0, wordEnd: 3, start: 0.0, end: 1.05 },
|
{ wordStart: 0, wordEnd: 3, start: 0.0, end: 1.35 },
|
||||||
{ wordStart: 4, wordEnd: 7, start: 1.1, end: 2.05 },
|
{ wordStart: 4, wordEnd: 7, start: 1.1, end: 2.35 },
|
||||||
{ wordStart: 8, wordEnd: 8, start: 2.1, end: 2.6 },
|
{ wordStart: 8, wordEnd: 8, start: 2.1, end: 2.9 },
|
||||||
{ wordStart: 9, wordEnd: 12, start: 2.65, end: 3.5 },
|
{ wordStart: 9, wordEnd: 12, start: 2.65, end: 3.8 },
|
||||||
{ wordStart: 13, wordEnd: 15, start: 3.55, end: 4.4 },
|
{ wordStart: 13, wordEnd: 15, start: 3.55, end: 4.7 },
|
||||||
{ wordStart: 16, wordEnd: 16, start: 3.95, end: 4.75 },
|
{ wordStart: 16, wordEnd: 16, start: 3.95, end: 5.0 },
|
||||||
{ wordStart: 17, wordEnd: 19, start: 4.9, end: 5.4 },
|
{ wordStart: 17, wordEnd: 19, start: 4.9, end: 5.7 },
|
||||||
{ wordStart: 20, wordEnd: 22, start: 5.65, end: 6.2 },
|
{ wordStart: 20, wordEnd: 22, start: 5.65, end: 6.5 },
|
||||||
{ wordStart: 23, wordEnd: 24, start: 6.35, end: 6.75 },
|
{ wordStart: 23, wordEnd: 24, start: 6.35, end: 7.05 },
|
||||||
{ wordStart: 25, wordEnd: 27, start: 6.8, end: 7.8 },
|
{ wordStart: 25, wordEnd: 27, start: 6.8, end: 7.9 },
|
||||||
];
|
];
|
||||||
|
|
||||||
var container = document.getElementById("sc-container");
|
var container = document.getElementById("sc-container");
|
||||||
@@ -248,10 +248,10 @@
|
|||||||
var scr1El = document.getElementById("sc-scr1-" + wi);
|
var scr1El = document.getElementById("sc-scr1-" + wi);
|
||||||
|
|
||||||
tl.set(scr0El, { display: "inline" }, w.start);
|
tl.set(scr0El, { display: "inline" }, w.start);
|
||||||
tl.set(scr1El, { display: "inline" }, w.start + 0.05);
|
tl.set(scr1El, { display: "inline" }, w.start + 0.1);
|
||||||
tl.set(scr0El, { display: "none" }, w.start + 0.05);
|
tl.set(scr0El, { display: "none" }, w.start + 0.1);
|
||||||
tl.set(realEl, { display: "inline" }, w.start + 0.1);
|
tl.set(realEl, { display: "inline" }, w.start + 0.2);
|
||||||
tl.set(scr1El, { display: "none" }, w.start + 0.1);
|
tl.set(scr1El, { display: "none" }, w.start + 0.2);
|
||||||
});
|
});
|
||||||
|
|
||||||
tl.to(grp, { opacity: 0, duration: 0.12 }, g.end - 0.12);
|
tl.to(grp, { opacity: 0, duration: 0.12 }, g.end - 0.12);
|
||||||
|
|||||||
+14
-14
@@ -181,16 +181,16 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
var GROUPS = [
|
var GROUPS = [
|
||||||
{ wordStart: 0, wordEnd: 3, start: 0.0, end: 1.05 },
|
{ wordStart: 0, wordEnd: 3, start: 0.0, end: 1.35 },
|
||||||
{ wordStart: 4, wordEnd: 7, start: 1.1, end: 2.05 },
|
{ wordStart: 4, wordEnd: 7, start: 1.1, end: 2.35 },
|
||||||
{ wordStart: 8, wordEnd: 8, start: 2.1, end: 2.6 },
|
{ wordStart: 8, wordEnd: 8, start: 2.1, end: 2.9 },
|
||||||
{ wordStart: 9, wordEnd: 12, start: 2.65, end: 3.5 },
|
{ wordStart: 9, wordEnd: 12, start: 2.65, end: 3.8 },
|
||||||
{ wordStart: 13, wordEnd: 15, start: 3.55, end: 4.4 },
|
{ wordStart: 13, wordEnd: 15, start: 3.55, end: 4.7 },
|
||||||
{ wordStart: 16, wordEnd: 16, start: 3.95, end: 4.75 },
|
{ wordStart: 16, wordEnd: 16, start: 3.95, end: 5.0 },
|
||||||
{ wordStart: 17, wordEnd: 19, start: 4.9, end: 5.4 },
|
{ wordStart: 17, wordEnd: 19, start: 4.9, end: 5.7 },
|
||||||
{ wordStart: 20, wordEnd: 22, start: 5.65, end: 6.2 },
|
{ wordStart: 20, wordEnd: 22, start: 5.65, end: 6.5 },
|
||||||
{ wordStart: 23, wordEnd: 24, start: 6.35, end: 6.75 },
|
{ wordStart: 23, wordEnd: 24, start: 6.35, end: 7.05 },
|
||||||
{ wordStart: 25, wordEnd: 27, start: 6.8, end: 7.8 },
|
{ wordStart: 25, wordEnd: 27, start: 6.8, end: 7.9 },
|
||||||
];
|
];
|
||||||
|
|
||||||
var container = document.getElementById("sc-container");
|
var container = document.getElementById("sc-container");
|
||||||
@@ -248,10 +248,10 @@
|
|||||||
var scr1El = document.getElementById("sc-scr1-" + wi);
|
var scr1El = document.getElementById("sc-scr1-" + wi);
|
||||||
|
|
||||||
tl.set(scr0El, { display: "inline" }, w.start);
|
tl.set(scr0El, { display: "inline" }, w.start);
|
||||||
tl.set(scr1El, { display: "inline" }, w.start + 0.05);
|
tl.set(scr1El, { display: "inline" }, w.start + 0.1);
|
||||||
tl.set(scr0El, { display: "none" }, w.start + 0.05);
|
tl.set(scr0El, { display: "none" }, w.start + 0.1);
|
||||||
tl.set(realEl, { display: "inline" }, w.start + 0.1);
|
tl.set(realEl, { display: "inline" }, w.start + 0.2);
|
||||||
tl.set(scr1El, { display: "none" }, w.start + 0.1);
|
tl.set(scr1El, { display: "none" }, w.start + 0.2);
|
||||||
});
|
});
|
||||||
|
|
||||||
tl.to(grp, { opacity: 0, duration: 0.12 }, g.end - 0.12);
|
tl.to(grp, { opacity: 0, duration: 0.12 }, g.end - 0.12);
|
||||||
|
|||||||
@@ -12,5 +12,5 @@
|
|||||||
"type": "hyperframes:snippet"
|
"type": "hyperframes:snippet"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-matrix-decode/preview.mp4?v=1779051416"
|
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-matrix-decode/preview.mp4?v=1779060427"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
|
|
||||||
"name": "caption-typewriter",
|
|
||||||
"type": "hyperframes:component",
|
|
||||||
"title": "Typewriter",
|
|
||||||
"description": "Green terminal character-by-character reveal with blinking cursor",
|
|
||||||
"tags": ["captions", "caption-style", "terminal", "typewriter", "hacker"],
|
|
||||||
"files": [
|
|
||||||
{
|
|
||||||
"path": "caption-typewriter.html",
|
|
||||||
"target": "compositions/components/caption-typewriter.html",
|
|
||||||
"type": "hyperframes:snippet"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-typewriter/preview.mp4?v=1779051416"
|
|
||||||
}
|
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: 1400px;
|
width: 1400px;
|
||||||
height: 260px;
|
height: 278px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 1400px;
|
width: 1400px;
|
||||||
height: 260px;
|
height: 278px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function splitLines(words) {
|
function splitLines(words) {
|
||||||
if (measureLineWidth(words) <= MAX_LINE_WIDTH) {
|
if (words.length < 2) {
|
||||||
return [{ words: words, startIndex: 0 }];
|
return [{ words: words, startIndex: 0 }];
|
||||||
}
|
}
|
||||||
var bestSplit = Math.ceil(words.length / 2);
|
var bestSplit = Math.ceil(words.length / 2);
|
||||||
@@ -248,6 +248,35 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function avoidSingleWordGroups(groups) {
|
||||||
|
var out = [];
|
||||||
|
groups.forEach(function (group) {
|
||||||
|
if (
|
||||||
|
group.words.length === 1 &&
|
||||||
|
out.length > 0 &&
|
||||||
|
out[out.length - 1].words.length < MAX_WORDS_PER_GROUP
|
||||||
|
) {
|
||||||
|
out[out.length - 1] = makeGroup(out[out.length - 1].words.concat(group.words));
|
||||||
|
} else {
|
||||||
|
out.push(group);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < out.length; i++) {
|
||||||
|
if (out[i].words.length !== 1) continue;
|
||||||
|
if (i + 1 < out.length && out[i + 1].words.length < MAX_WORDS_PER_GROUP) {
|
||||||
|
out[i] = makeGroup(out[i].words.concat(out[i + 1].words));
|
||||||
|
out.splice(i + 1, 1);
|
||||||
|
} else if (i > 0 && out[i - 1].words.length < MAX_WORDS_PER_GROUP) {
|
||||||
|
out[i - 1] = makeGroup(out[i - 1].words.concat(out[i].words));
|
||||||
|
out.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
function makeGroups(words) {
|
function makeGroups(words) {
|
||||||
var groups = [];
|
var groups = [];
|
||||||
var current = [];
|
var current = [];
|
||||||
@@ -273,7 +302,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (current.length) groups.push(makeGroup(current));
|
if (current.length) groups.push(makeGroup(current));
|
||||||
return groups;
|
return avoidSingleWordGroups(groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeGroup(words) {
|
function makeGroup(words) {
|
||||||
@@ -311,9 +340,10 @@
|
|||||||
lineEl.id = "caption-group-" + groupIndex + "-line-" + lineIndex;
|
lineEl.id = "caption-group-" + groupIndex + "-line-" + lineIndex;
|
||||||
lineEl.style.fontWeight = lineIndex === 0 ? FONT_WEIGHT_BOLD : FONT_WEIGHT_LIGHT;
|
lineEl.style.fontWeight = lineIndex === 0 ? FONT_WEIGHT_BOLD : FONT_WEIGHT_LIGHT;
|
||||||
lineEl.style.fontSize = computedSize + "px";
|
lineEl.style.fontSize = computedSize + "px";
|
||||||
line.words.forEach(function (word) {
|
line.words.forEach(function (word, wordIndex) {
|
||||||
var wordEl = document.createElement("span");
|
var wordEl = document.createElement("span");
|
||||||
wordEl.textContent = word.text.toLowerCase();
|
wordEl.textContent = word.text.toLowerCase();
|
||||||
|
wordEl.style.display = "inline-block";
|
||||||
lineEl.appendChild(wordEl);
|
lineEl.appendChild(wordEl);
|
||||||
});
|
});
|
||||||
copyEl.appendChild(lineEl);
|
copyEl.appendChild(lineEl);
|
||||||
@@ -362,6 +392,7 @@
|
|||||||
var line2El = document.getElementById("caption-group-" + groupIndex + "-line-1");
|
var line2El = document.getElementById("caption-group-" + groupIndex + "-line-1");
|
||||||
var line2FirstWord = group.lines[1].words[0];
|
var line2FirstWord = group.lines[1].words[0];
|
||||||
var switchTime = line2FirstWord.start;
|
var switchTime = line2FirstWord.start;
|
||||||
|
|
||||||
tl.to(
|
tl.to(
|
||||||
line1El,
|
line1El,
|
||||||
{ fontWeight: FONT_WEIGHT_LIGHT, duration: WEIGHT_TRANSITION, ease: "power2.out" },
|
{ fontWeight: FONT_WEIGHT_LIGHT, duration: WEIGHT_TRANSITION, ease: "power2.out" },
|
||||||
|
|||||||
+36
-5
@@ -59,7 +59,7 @@
|
|||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: 1400px;
|
width: 1400px;
|
||||||
height: 260px;
|
height: 278px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 1400px;
|
width: 1400px;
|
||||||
height: 260px;
|
height: 278px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function splitLines(words) {
|
function splitLines(words) {
|
||||||
if (measureLineWidth(words) <= MAX_LINE_WIDTH) {
|
if (words.length < 2) {
|
||||||
return [{ words: words, startIndex: 0 }];
|
return [{ words: words, startIndex: 0 }];
|
||||||
}
|
}
|
||||||
var bestSplit = Math.ceil(words.length / 2);
|
var bestSplit = Math.ceil(words.length / 2);
|
||||||
@@ -248,6 +248,35 @@
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function avoidSingleWordGroups(groups) {
|
||||||
|
var out = [];
|
||||||
|
groups.forEach(function (group) {
|
||||||
|
if (
|
||||||
|
group.words.length === 1 &&
|
||||||
|
out.length > 0 &&
|
||||||
|
out[out.length - 1].words.length < MAX_WORDS_PER_GROUP
|
||||||
|
) {
|
||||||
|
out[out.length - 1] = makeGroup(out[out.length - 1].words.concat(group.words));
|
||||||
|
} else {
|
||||||
|
out.push(group);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < out.length; i++) {
|
||||||
|
if (out[i].words.length !== 1) continue;
|
||||||
|
if (i + 1 < out.length && out[i + 1].words.length < MAX_WORDS_PER_GROUP) {
|
||||||
|
out[i] = makeGroup(out[i].words.concat(out[i + 1].words));
|
||||||
|
out.splice(i + 1, 1);
|
||||||
|
} else if (i > 0 && out[i - 1].words.length < MAX_WORDS_PER_GROUP) {
|
||||||
|
out[i - 1] = makeGroup(out[i - 1].words.concat(out[i].words));
|
||||||
|
out.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
function makeGroups(words) {
|
function makeGroups(words) {
|
||||||
var groups = [];
|
var groups = [];
|
||||||
var current = [];
|
var current = [];
|
||||||
@@ -273,7 +302,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (current.length) groups.push(makeGroup(current));
|
if (current.length) groups.push(makeGroup(current));
|
||||||
return groups;
|
return avoidSingleWordGroups(groups);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeGroup(words) {
|
function makeGroup(words) {
|
||||||
@@ -311,9 +340,10 @@
|
|||||||
lineEl.id = "caption-group-" + groupIndex + "-line-" + lineIndex;
|
lineEl.id = "caption-group-" + groupIndex + "-line-" + lineIndex;
|
||||||
lineEl.style.fontWeight = lineIndex === 0 ? FONT_WEIGHT_BOLD : FONT_WEIGHT_LIGHT;
|
lineEl.style.fontWeight = lineIndex === 0 ? FONT_WEIGHT_BOLD : FONT_WEIGHT_LIGHT;
|
||||||
lineEl.style.fontSize = computedSize + "px";
|
lineEl.style.fontSize = computedSize + "px";
|
||||||
line.words.forEach(function (word) {
|
line.words.forEach(function (word, wordIndex) {
|
||||||
var wordEl = document.createElement("span");
|
var wordEl = document.createElement("span");
|
||||||
wordEl.textContent = word.text.toLowerCase();
|
wordEl.textContent = word.text.toLowerCase();
|
||||||
|
wordEl.style.display = "inline-block";
|
||||||
lineEl.appendChild(wordEl);
|
lineEl.appendChild(wordEl);
|
||||||
});
|
});
|
||||||
copyEl.appendChild(lineEl);
|
copyEl.appendChild(lineEl);
|
||||||
@@ -362,6 +392,7 @@
|
|||||||
var line2El = document.getElementById("caption-group-" + groupIndex + "-line-1");
|
var line2El = document.getElementById("caption-group-" + groupIndex + "-line-1");
|
||||||
var line2FirstWord = group.lines[1].words[0];
|
var line2FirstWord = group.lines[1].words[0];
|
||||||
var switchTime = line2FirstWord.start;
|
var switchTime = line2FirstWord.start;
|
||||||
|
|
||||||
tl.to(
|
tl.to(
|
||||||
line1El,
|
line1El,
|
||||||
{ fontWeight: FONT_WEIGHT_LIGHT, duration: WEIGHT_TRANSITION, ease: "power2.out" },
|
{ fontWeight: FONT_WEIGHT_LIGHT, duration: WEIGHT_TRANSITION, ease: "power2.out" },
|
||||||
|
|||||||
@@ -12,5 +12,5 @@
|
|||||||
"type": "hyperframes:snippet"
|
"type": "hyperframes:snippet"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-weight-shift/preview.mp4?v=1779051416"
|
"preview": "https://static.heygen.ai/hyperframes-oss/registry/components/caption-weight-shift/preview.mp4?v=1779065047"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,10 +95,6 @@
|
|||||||
"name": "caption-glitch-rgb",
|
"name": "caption-glitch-rgb",
|
||||||
"type": "hyperframes:component"
|
"type": "hyperframes:component"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "caption-typewriter",
|
|
||||||
"type": "hyperframes:component"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "caption-matrix-decode",
|
"name": "caption-matrix-decode",
|
||||||
"type": "hyperframes:component"
|
"type": "hyperframes:component"
|
||||||
@@ -127,6 +123,10 @@
|
|||||||
"name": "caption-neon-glow",
|
"name": "caption-neon-glow",
|
||||||
"type": "hyperframes:component"
|
"type": "hyperframes:component"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "caption-highlight",
|
||||||
|
"type": "hyperframes:component"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "instagram-follow",
|
"name": "instagram-follow",
|
||||||
"type": "hyperframes:block"
|
"type": "hyperframes:block"
|
||||||
|
|||||||
Reference in New Issue
Block a user