mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-02 12:08:50 +00:00
feat(registry): add mk-line-graph — minimal line graph
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
2039bf5f44
commit
4ce35b7cba
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
title: "Minimal Line Graph"
|
||||||
|
description: "One or two SVG series draw on with dots popping and value labels riding the draw front; dim baseline axis, x-labels, color-dot legend"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Minimal Line Graph
|
||||||
|
|
||||||
|
One or two SVG series draw on with dots popping and value labels riding the draw front; dim baseline axis, x-labels, color-dot legend
|
||||||
|
|
||||||
|
`data-viz` `chart` `graph` `minimal`
|
||||||
|
|
||||||
|
<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/blocks/mk-line-graph.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/mk-line-graph.png" autoPlay muted loop playsInline />
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
|
||||||
|
```bash Terminal
|
||||||
|
npx hyperframes add mk-line-graph
|
||||||
|
```
|
||||||
|
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
|
## Details
|
||||||
|
|
||||||
|
| Property | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| Type | Block |
|
||||||
|
| Dimensions | 1920×1080 |
|
||||||
|
| Duration | 7s |
|
||||||
|
|
||||||
|
## Files
|
||||||
|
|
||||||
|
| File | Target | Type |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `mk-line-graph.html` | `compositions/mk-line-graph.html` | hyperframes:composition |
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
After installing, add the block to your host composition:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div data-composition-id="mk-line-graph" data-composition-src="compositions/mk-line-graph.html" data-start="0" data-duration="7" data-track-index="1" data-width="1920" data-height="1080"></div>
|
||||||
|
```
|
||||||
+283
@@ -0,0 +1,283 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||||||
|
<style>
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background: transparent;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#mk-lg-root {
|
||||||
|
/* ---- mk tokens: override in the host to re-skin the family ---- */
|
||||||
|
--mk-font: "Inter", -apple-system, sans-serif;
|
||||||
|
--mk-ink: #1d1d1f;
|
||||||
|
--mk-ink-dim: #6e6e73;
|
||||||
|
--mk-accent: #0071e3;
|
||||||
|
--mk-paper: #ffffff;
|
||||||
|
--mk-blob-2: #45d6c8;
|
||||||
|
--mk-axis: rgba(29, 29, 31, 0.22);
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
width: 1920px;
|
||||||
|
height: 1080px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: transparent; /* overlays footage or mk-background */
|
||||||
|
font-family: var(--mk-font);
|
||||||
|
}
|
||||||
|
#mk-lg-svg {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
}
|
||||||
|
.mk-lg-line {
|
||||||
|
fill: none;
|
||||||
|
stroke-width: 5;
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
.mk-lg-dot {
|
||||||
|
stroke-width: 4;
|
||||||
|
fill: var(--mk-paper);
|
||||||
|
}
|
||||||
|
.mk-lg-axis {
|
||||||
|
stroke: var(--mk-axis);
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.mk-lg-value {
|
||||||
|
position: absolute;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 30px;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
color: var(--mk-ink);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
transform: translate(-50%, -100%);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.mk-lg-xlabel {
|
||||||
|
position: absolute;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 26px;
|
||||||
|
color: var(--mk-ink-dim);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.mk-lg-legend {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
gap: 40px;
|
||||||
|
}
|
||||||
|
.mk-lg-legend-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 30px;
|
||||||
|
color: var(--mk-ink-dim);
|
||||||
|
}
|
||||||
|
.mk-lg-legend-dot {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div
|
||||||
|
id="mk-lg-root"
|
||||||
|
data-composition-id="mk-line-graph"
|
||||||
|
data-start="0"
|
||||||
|
data-duration="7"
|
||||||
|
data-width="1920"
|
||||||
|
data-height="1080"
|
||||||
|
>
|
||||||
|
<svg id="mk-lg-svg" viewBox="0 0 1920 1080"></svg>
|
||||||
|
<div id="mk-lg-labels"></div>
|
||||||
|
<div
|
||||||
|
id="mk-lg-drv"
|
||||||
|
class="clip"
|
||||||
|
data-start="0"
|
||||||
|
data-duration="7"
|
||||||
|
data-track-index="0"
|
||||||
|
style="position:absolute;width:1px;height:1px;opacity:0;pointer-events:none"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
window.__timelines = window.__timelines || {};
|
||||||
|
|
||||||
|
/* ---- published parameters (inspector-style CONFIG) ----
|
||||||
|
A minimal presentation line graph: 1–2 series draw on, dots pop, value labels
|
||||||
|
ride their points, axes dimmer than labels (clear hierarchy). */
|
||||||
|
var CONFIG = {
|
||||||
|
// no scheme param — scheme-agnostic; re-skin via the --mk-* tokens
|
||||||
|
series: [
|
||||||
|
{ name: "Renders", color: null /* accent */, values: [12, 26, 22, 38, 44, 58] },
|
||||||
|
{ name: "Projects", color: null /* blob-2 */, values: [8, 14, 18, 16, 28, 36] },
|
||||||
|
],
|
||||||
|
xLabels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"],
|
||||||
|
showValues: true,
|
||||||
|
area: { x: 160, y: 240, w: 980, h: 500 }, // plot rectangle
|
||||||
|
animationIn: true,
|
||||||
|
animationOut: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
var DUR = 7;
|
||||||
|
var NS = "http://www.w3.org/2000/svg";
|
||||||
|
var root = document.getElementById("mk-lg-root");
|
||||||
|
var svg = document.getElementById("mk-lg-svg");
|
||||||
|
var labels = document.getElementById("mk-lg-labels");
|
||||||
|
var A = CONFIG.area;
|
||||||
|
|
||||||
|
var accent = getComputedStyle(root).getPropertyValue("--mk-accent").trim();
|
||||||
|
var blob2 = getComputedStyle(root).getPropertyValue("--mk-blob-2").trim();
|
||||||
|
if (CONFIG.series[1] && !CONFIG.series[1].color) CONFIG.series[1].color = blob2;
|
||||||
|
|
||||||
|
/* scale: 0..max(all values)*1.15 into the plot rect */
|
||||||
|
var max = 0;
|
||||||
|
CONFIG.series.forEach(function (s) {
|
||||||
|
s.values.forEach(function (v) {
|
||||||
|
if (v > max) max = v;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
max *= 1.15;
|
||||||
|
var n = CONFIG.series[0].values.length;
|
||||||
|
function px(i) {
|
||||||
|
return A.x + (i / (n - 1)) * A.w;
|
||||||
|
}
|
||||||
|
function py(v) {
|
||||||
|
return A.y + A.h - (v / max) * A.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* baseline axis */
|
||||||
|
var axis = document.createElementNS(NS, "line");
|
||||||
|
axis.setAttribute("class", "mk-lg-axis");
|
||||||
|
axis.setAttribute("x1", A.x - 20);
|
||||||
|
axis.setAttribute("y1", A.y + A.h);
|
||||||
|
axis.setAttribute("x2", A.x + A.w + 20);
|
||||||
|
axis.setAttribute("y2", A.y + A.h);
|
||||||
|
axis.id = "mk-lg-axis";
|
||||||
|
svg.appendChild(axis);
|
||||||
|
|
||||||
|
/* series paths, dots, value labels */
|
||||||
|
var paths = [],
|
||||||
|
dots = [],
|
||||||
|
vals = [];
|
||||||
|
CONFIG.series.forEach(function (s, si) {
|
||||||
|
var color = s.color || accent;
|
||||||
|
var d = s.values
|
||||||
|
.map(function (v, i) {
|
||||||
|
return (i === 0 ? "M" : "L") + px(i) + " " + py(v);
|
||||||
|
})
|
||||||
|
.join(" ");
|
||||||
|
var path = document.createElementNS(NS, "path");
|
||||||
|
path.setAttribute("class", "mk-lg-line");
|
||||||
|
path.setAttribute("d", d);
|
||||||
|
path.setAttribute("stroke", color);
|
||||||
|
path.id = "mk-lg-path-" + si;
|
||||||
|
svg.appendChild(path);
|
||||||
|
paths.push(path);
|
||||||
|
|
||||||
|
s.values.forEach(function (v, i) {
|
||||||
|
var dot = document.createElementNS(NS, "circle");
|
||||||
|
dot.setAttribute("class", "mk-lg-dot");
|
||||||
|
dot.setAttribute("cx", px(i));
|
||||||
|
dot.setAttribute("cy", py(v));
|
||||||
|
dot.setAttribute("r", 9);
|
||||||
|
dot.setAttribute("stroke", color);
|
||||||
|
dot.id = "mk-lg-dot-" + si + "-" + i;
|
||||||
|
svg.appendChild(dot);
|
||||||
|
dots.push({ el: dot, si: si, i: i });
|
||||||
|
|
||||||
|
if (CONFIG.showValues) {
|
||||||
|
var val = document.createElement("div");
|
||||||
|
val.className = "mk-lg-value";
|
||||||
|
val.id = "mk-lg-val-" + si + "-" + i;
|
||||||
|
val.textContent = v;
|
||||||
|
val.style.left = px(i) + "px";
|
||||||
|
val.style.top = py(v) - 20 + "px";
|
||||||
|
labels.appendChild(val);
|
||||||
|
vals.push({ el: val, si: si, i: i });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/* x labels + legend */
|
||||||
|
CONFIG.xLabels.slice(0, n).forEach(function (t, i) {
|
||||||
|
var xl = document.createElement("div");
|
||||||
|
xl.className = "mk-lg-xlabel";
|
||||||
|
xl.id = "mk-lg-xl-" + i;
|
||||||
|
xl.textContent = t;
|
||||||
|
xl.style.left = px(i) + "px";
|
||||||
|
xl.style.top = A.y + A.h + 24 + "px";
|
||||||
|
labels.appendChild(xl);
|
||||||
|
});
|
||||||
|
var legend = document.createElement("div");
|
||||||
|
legend.className = "mk-lg-legend";
|
||||||
|
legend.id = "mk-lg-legend";
|
||||||
|
legend.style.left = A.x + "px";
|
||||||
|
legend.style.top = A.y + A.h + 90 + "px";
|
||||||
|
CONFIG.series.forEach(function (s) {
|
||||||
|
var item = document.createElement("div");
|
||||||
|
item.className = "mk-lg-legend-item";
|
||||||
|
var dot = document.createElement("span");
|
||||||
|
dot.className = "mk-lg-legend-dot";
|
||||||
|
dot.style.background = s.color || accent;
|
||||||
|
item.appendChild(dot);
|
||||||
|
item.appendChild(document.createTextNode(s.name));
|
||||||
|
legend.appendChild(item);
|
||||||
|
});
|
||||||
|
labels.appendChild(legend);
|
||||||
|
|
||||||
|
var tl = gsap.timeline({ paused: true });
|
||||||
|
var DRAW = 1.3;
|
||||||
|
|
||||||
|
/* entrance: axis + x labels settle first */
|
||||||
|
gsap.set([axis, legend], { opacity: 0 });
|
||||||
|
tl.to(axis, { opacity: 1, duration: 0.5, ease: "power2.out" }, 0.2);
|
||||||
|
CONFIG.xLabels.slice(0, n).forEach(function (t, i) {
|
||||||
|
var xl = document.getElementById("mk-lg-xl-" + i);
|
||||||
|
gsap.set(xl, { opacity: 0, y: 10 });
|
||||||
|
tl.to(xl, { opacity: 1, y: 0, duration: 0.4, ease: "power2.out" }, 0.25 + i * 0.05);
|
||||||
|
});
|
||||||
|
|
||||||
|
/* draw each series, dots + values riding the draw front */
|
||||||
|
CONFIG.series.forEach(function (s, si) {
|
||||||
|
var t0 = (CONFIG.animationIn ? 0.5 : 0) + si * 0.35;
|
||||||
|
var path = paths[si];
|
||||||
|
var len = path.getTotalLength();
|
||||||
|
gsap.set(path, { strokeDasharray: len, strokeDashoffset: len });
|
||||||
|
tl.to(path, { strokeDashoffset: 0, duration: DRAW, ease: "power2.inOut" }, t0);
|
||||||
|
|
||||||
|
s.values.forEach(function (v, i) {
|
||||||
|
var dot = document.getElementById("mk-lg-dot-" + si + "-" + i);
|
||||||
|
var td = t0 + (i / (n - 1)) * DRAW * 0.92;
|
||||||
|
gsap.set(dot, { scale: 0, transformOrigin: "50% 50%" });
|
||||||
|
tl.to(dot, { scale: 1, duration: 0.35, ease: "back.out(1.2)" }, td);
|
||||||
|
if (CONFIG.showValues) {
|
||||||
|
var val = document.getElementById("mk-lg-val-" + si + "-" + i);
|
||||||
|
gsap.set(val, { opacity: 0, y: 8 });
|
||||||
|
tl.to(val, { opacity: 1, y: 0, duration: 0.35, ease: "power2.out" }, td + 0.06);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tl.to(legend, { opacity: 1, duration: 0.5, ease: "power2.out" }, 2.3);
|
||||||
|
|
||||||
|
/* exit + hard kill */
|
||||||
|
if (CONFIG.animationOut) {
|
||||||
|
tl.to([svg, labels], { opacity: 0, y: -20, duration: 0.4, ease: "power2.in" }, DUR - 0.5);
|
||||||
|
}
|
||||||
|
tl.set(root, { visibility: "hidden" }, DUR - 0.02);
|
||||||
|
|
||||||
|
window.__timelines["mk-line-graph"] = tl;
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
|
||||||
|
"name": "mk-line-graph",
|
||||||
|
"type": "hyperframes:block",
|
||||||
|
"title": "Minimal Line Graph",
|
||||||
|
"description": "One or two SVG series draw on with dots popping and value labels riding the draw front; dim baseline axis, x-labels, color-dot legend",
|
||||||
|
"tags": [
|
||||||
|
"data-viz",
|
||||||
|
"chart",
|
||||||
|
"graph",
|
||||||
|
"minimal"
|
||||||
|
],
|
||||||
|
"dimensions": {
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1080
|
||||||
|
},
|
||||||
|
"duration": 7,
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "mk-line-graph.html",
|
||||||
|
"target": "compositions/mk-line-graph.html",
|
||||||
|
"type": "hyperframes:composition"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -583,6 +583,10 @@
|
|||||||
"name": "mk-progress-stat",
|
"name": "mk-progress-stat",
|
||||||
"type": "hyperframes:block"
|
"type": "hyperframes:block"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mk-line-graph",
|
||||||
|
"type": "hyperframes:block"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "parallax-zoom",
|
"name": "parallax-zoom",
|
||||||
"type": "hyperframes:component"
|
"type": "hyperframes:component"
|
||||||
|
|||||||
Reference in New Issue
Block a user