mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
feat(registry): add spain-map block + fix MDX preview paths
New block: spain-map — animated Spain choropleth by autonomous community using D3 conic conformal projection with GDP per capita data and red-to-amber color scale. Also switches all map MDX preview URLs from S3 to local paths so they render in mintlify dev without needing S3 upload first.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: "Spain Map"
|
||||
description: "Animated Spain choropleth by autonomous community with staggered reveals and gradient legend"
|
||||
---
|
||||
|
||||
# Spain Map
|
||||
|
||||
Animated Spain choropleth by autonomous community with staggered reveals and gradient legend — D3 conic conformal projection with GSAP timeline. GDP per capita data with warm red-to-amber color scale.
|
||||
|
||||
`data` `map` `geography` `spain` `europe` `choropleth`
|
||||
|
||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="/images/catalog/blocks/spain-map.mp4" poster="/images/catalog/blocks/spain-map.png" autoPlay muted loop playsInline />
|
||||
|
||||
## Install
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash Terminal
|
||||
npx hyperframes add spain-map
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Details
|
||||
|
||||
| Property | Value |
|
||||
| --- | --- |
|
||||
| Type | Block |
|
||||
| Dimensions | 1920×1080 |
|
||||
| Duration | 12s |
|
||||
|
||||
## Files
|
||||
|
||||
| File | Target | Type |
|
||||
| --- | --- | --- |
|
||||
| `spain-map.html` | `compositions/spain-map.html` | hyperframes:composition |
|
||||
|
||||
## Usage
|
||||
|
||||
After installing, add the block to your host composition:
|
||||
|
||||
```html
|
||||
<div data-composition-id="spain-map" data-composition-src="compositions/spain-map.html" data-start="0" data-duration="12" data-track-index="1" data-width="1920" data-height="1080"></div>
|
||||
```
|
||||
@@ -9,7 +9,7 @@ Animated US bubble map with proportional city markers, value callouts, and conne
|
||||
|
||||
`data` `map` `geography` `usa` `bubble` `cities`
|
||||
|
||||
<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/us-map-bubble.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/us-map-bubble.png" autoPlay muted loop playsInline />
|
||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="/images/catalog/blocks/us-map-bubble.mp4" poster="/images/catalog/blocks/us-map-bubble.png" autoPlay muted loop playsInline />
|
||||
|
||||
## Install
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Animated connection arcs between US cities over a base map — composable origin
|
||||
|
||||
`data` `map` `geography` `usa` `flow` `connections` `arcs`
|
||||
|
||||
<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/us-map-flow.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/us-map-flow.png" autoPlay muted loop playsInline />
|
||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="/images/catalog/blocks/us-map-flow.mp4" poster="/images/catalog/blocks/us-map-flow.png" autoPlay muted loop playsInline />
|
||||
|
||||
## Install
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Animated hexagonal tile grid map — each state as an equal-weight hex with data
|
||||
|
||||
`data` `map` `geography` `usa` `hexgrid` `tilegrid`
|
||||
|
||||
<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/us-map-hex.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/us-map-hex.png" autoPlay muted loop playsInline />
|
||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="/images/catalog/blocks/us-map-hex.mp4" poster="/images/catalog/blocks/us-map-hex.png" autoPlay muted loop playsInline />
|
||||
|
||||
## Install
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Animated US choropleth map with staggered state reveals, value labels, and gradi
|
||||
|
||||
`data` `map` `geography` `usa` `choropleth`
|
||||
|
||||
<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/us-map.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/us-map.png" autoPlay muted loop playsInline />
|
||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="/images/catalog/blocks/us-map.mp4" poster="/images/catalog/blocks/us-map.png" autoPlay muted loop playsInline />
|
||||
|
||||
## Install
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Animated world choropleth with country-by-country reveal, gradient legend, and h
|
||||
|
||||
`data` `map` `geography` `world` `choropleth`
|
||||
|
||||
<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/world-map.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/world-map.png" autoPlay muted loop playsInline />
|
||||
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="/images/catalog/blocks/world-map.mp4" poster="/images/catalog/blocks/world-map.png" autoPlay muted loop playsInline />
|
||||
|
||||
## Install
|
||||
|
||||
|
||||
+2
-1
@@ -195,7 +195,8 @@
|
||||
"catalog/blocks/us-map-bubble",
|
||||
"catalog/blocks/us-map-hex",
|
||||
"catalog/blocks/us-map-flow",
|
||||
"catalog/blocks/world-map"
|
||||
"catalog/blocks/world-map",
|
||||
"catalog/blocks/spain-map"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
|
||||
"name": "spain-map",
|
||||
"type": "hyperframes:block",
|
||||
"title": "Spain Map",
|
||||
"description": "Animated Spain choropleth by autonomous community with staggered reveals and gradient legend — D3 conic conformal projection",
|
||||
"tags": ["data", "map", "geography", "spain", "europe", "choropleth"],
|
||||
"dimensions": { "width": 1920, "height": 1080 },
|
||||
"duration": 12,
|
||||
"files": [
|
||||
{
|
||||
"path": "spain-map.html",
|
||||
"target": "compositions/spain-map.html",
|
||||
"type": "hyperframes:composition"
|
||||
}
|
||||
]
|
||||
}
|
||||
+393
@@ -0,0 +1,393 @@
|
||||
<!doctype html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=1920, height=1080" />
|
||||
<title>Spain Map</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=block"
|
||||
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/d3@7/dist/d3.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/topojson-client@3.1.0/dist/topojson-client.min.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
overflow: hidden;
|
||||
background-color: #0f172a;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div
|
||||
id="spain-map"
|
||||
data-composition-id="spain-map"
|
||||
data-width="1920"
|
||||
data-height="1080"
|
||||
data-start="0"
|
||||
data-duration="12"
|
||||
>
|
||||
<div class="map-container">
|
||||
<div class="header">
|
||||
<h1 class="headline">PIB per cápita por Comunidad Autónoma</h1>
|
||||
<p class="subtitle">Producto Interior Bruto per cápita, estimación 2024</p>
|
||||
</div>
|
||||
|
||||
<svg class="map-svg" viewBox="0 0 1400 820" preserveAspectRatio="xMidYMid meet">
|
||||
<g class="regions-group"></g>
|
||||
<g class="labels-group"></g>
|
||||
</svg>
|
||||
|
||||
<div class="legend">
|
||||
<span class="legend-label legend-low">Bajo</span>
|
||||
<div class="legend-bar"></div>
|
||||
<span class="legend-label legend-high">Alto</span>
|
||||
</div>
|
||||
|
||||
<div class="source">Fuente: Instituto Nacional de Estadística</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#spain-map {
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
background: linear-gradient(145deg, #0f172a 0%, #1e293b 100%);
|
||||
font-family: "Inter", sans-serif;
|
||||
color: #e2e8f0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#spain-map .map-container {
|
||||
width: 1700px;
|
||||
height: 950px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#spain-map .header {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#spain-map .headline {
|
||||
font-size: 48px;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
color: #f8fafc;
|
||||
clip-path: inset(0 100% 0 0);
|
||||
}
|
||||
|
||||
#spain-map .subtitle {
|
||||
font-size: 20px;
|
||||
font-weight: 300;
|
||||
color: #94a3b8;
|
||||
margin-top: 8px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#spain-map .map-svg {
|
||||
width: 1500px;
|
||||
height: 750px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
#spain-map .region-path {
|
||||
stroke: #1e293b;
|
||||
stroke-width: 0.8;
|
||||
opacity: 0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#spain-map .region-label {
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
fill: #f8fafc;
|
||||
text-anchor: middle;
|
||||
dominant-baseline: central;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#spain-map .legend {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-top: 16px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#spain-map .legend-bar {
|
||||
width: 300px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
background: linear-gradient(90deg, #7f1d1d, #dc2626, #fbbf24);
|
||||
}
|
||||
|
||||
#spain-map .legend-label {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
#spain-map .source {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 40px;
|
||||
font-size: 12px;
|
||||
color: #475569;
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var SPAIN_TOPO_URL =
|
||||
"https://cdn.jsdelivr.net/npm/es-atlas@0.6.0/es/autonomous_regions.json";
|
||||
|
||||
var data = {
|
||||
"01": { name: "Andalucía", abbr: "AND", gdp: 20200 },
|
||||
"02": { name: "Aragón", abbr: "ARA", gdp: 30500 },
|
||||
"03": { name: "Asturias", abbr: "AST", gdp: 24100 },
|
||||
"04": { name: "Illes Balears", abbr: "BAL", gdp: 28900 },
|
||||
"05": { name: "Canarias", abbr: "CAN", gdp: 21500 },
|
||||
"06": { name: "Cantabria", abbr: "CNT", gdp: 25200 },
|
||||
"07": { name: "Castilla y León", abbr: "CYL", gdp: 25800 },
|
||||
"08": { name: "Castilla-La Mancha", abbr: "CLM", gdp: 21400 },
|
||||
"09": { name: "Catalunya", abbr: "CAT", gdp: 33700 },
|
||||
10: { name: "Comunitat Valenciana", abbr: "VAL", gdp: 23800 },
|
||||
11: { name: "Extremadura", abbr: "EXT", gdp: 19200 },
|
||||
12: { name: "Galicia", abbr: "GAL", gdp: 24500 },
|
||||
13: { name: "Comunidad de Madrid", abbr: "MAD", gdp: 38100 },
|
||||
14: { name: "Región de Murcia", abbr: "MUR", gdp: 22100 },
|
||||
15: { name: "Navarra", abbr: "NAV", gdp: 35200 },
|
||||
16: { name: "País Vasco", abbr: "PVA", gdp: 36800 },
|
||||
17: { name: "La Rioja", abbr: "RIO", gdp: 29800 },
|
||||
18: { name: "Ceuta", abbr: "CEU", gdp: 21000 },
|
||||
19: { name: "Melilla", abbr: "MEL", gdp: 19500 },
|
||||
};
|
||||
|
||||
var nameMap = {};
|
||||
for (var key in data) {
|
||||
nameMap[data[key].name.toLowerCase()] = key;
|
||||
}
|
||||
|
||||
var minGdp = 19200;
|
||||
var maxGdp = 38100;
|
||||
|
||||
function gdpToColor(gdp) {
|
||||
var t = Math.min(Math.max((gdp - minGdp) / (maxGdp - minGdp), 0), 1);
|
||||
if (t < 0.5) {
|
||||
var s = t / 0.5;
|
||||
return lerpColor([127, 29, 29], [220, 38, 38], s);
|
||||
} else {
|
||||
var s2 = (t - 0.5) / 0.5;
|
||||
return lerpColor([220, 38, 38], [251, 191, 36], s2);
|
||||
}
|
||||
}
|
||||
|
||||
function lerpColor(a, b, t) {
|
||||
var r = Math.round(a[0] + (b[0] - a[0]) * t);
|
||||
var g = Math.round(a[1] + (b[1] - a[1]) * t);
|
||||
var bl = Math.round(a[2] + (b[2] - a[2]) * t);
|
||||
return "rgb(" + r + "," + g + "," + bl + ")";
|
||||
}
|
||||
|
||||
function findData(feature) {
|
||||
var id = String(feature.id).padStart(2, "0");
|
||||
if (data[id]) return data[id];
|
||||
var fname = (feature.properties && feature.properties.name) || "";
|
||||
var fnameLower = fname.toLowerCase();
|
||||
for (var k in data) {
|
||||
var dname = data[k].name.toLowerCase();
|
||||
if (fnameLower.indexOf(dname) >= 0 || dname.indexOf(fnameLower) >= 0) {
|
||||
return data[k];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
var svg = document.querySelector("#spain-map .map-svg");
|
||||
var regionsGroup = svg.querySelector(".regions-group");
|
||||
var labelsGroup = svg.querySelector(".labels-group");
|
||||
var tl = gsap.timeline({ paused: true });
|
||||
|
||||
fetch(SPAIN_TOPO_URL)
|
||||
.then(function (r) {
|
||||
return r.json();
|
||||
})
|
||||
.then(function (es) {
|
||||
var featureCollection = topojson.feature(es, es.objects.autonomous_regions);
|
||||
var features = featureCollection.features;
|
||||
|
||||
var projection = d3
|
||||
.geoConicConformal()
|
||||
.center([0, 39.5])
|
||||
.rotate([3.5, 0])
|
||||
.fitSize([1200, 750], featureCollection);
|
||||
var path = d3.geoPath().projection(projection);
|
||||
|
||||
var sortedFeatures = features
|
||||
.filter(function (f) {
|
||||
return findData(f) !== null;
|
||||
})
|
||||
.sort(function (a, b) {
|
||||
return findData(a).gdp - findData(b).gdp;
|
||||
});
|
||||
|
||||
sortedFeatures.forEach(function (feature) {
|
||||
var info = findData(feature);
|
||||
if (!info) return;
|
||||
|
||||
var d = path(feature);
|
||||
if (!d) return;
|
||||
|
||||
var el = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
||||
el.setAttribute("d", d);
|
||||
el.setAttribute("class", "region-path");
|
||||
el.setAttribute("data-region", info.abbr);
|
||||
el.setAttribute("data-gdp", String(info.gdp));
|
||||
el.style.fill = gdpToColor(info.gdp);
|
||||
regionsGroup.appendChild(el);
|
||||
|
||||
var centroid = path.centroid(feature);
|
||||
if (centroid[0] && centroid[1]) {
|
||||
var label = document.createElementNS("http://www.w3.org/2000/svg", "text");
|
||||
label.setAttribute("x", String(centroid[0]));
|
||||
label.setAttribute("y", String(centroid[1]));
|
||||
label.setAttribute("class", "region-label");
|
||||
label.textContent = info.abbr;
|
||||
labelsGroup.appendChild(label);
|
||||
}
|
||||
});
|
||||
|
||||
buildTimeline();
|
||||
});
|
||||
|
||||
function buildTimeline() {
|
||||
var regionPaths = regionsGroup.querySelectorAll(".region-path");
|
||||
var regionLabels = labelsGroup.querySelectorAll(".region-label");
|
||||
|
||||
tl.to(
|
||||
"#spain-map .headline",
|
||||
{
|
||||
clipPath: "inset(0 0% 0 0)",
|
||||
duration: 1.0,
|
||||
ease: "power2.inOut",
|
||||
},
|
||||
0,
|
||||
);
|
||||
|
||||
tl.to(
|
||||
"#spain-map .subtitle",
|
||||
{
|
||||
opacity: 1,
|
||||
duration: 0.6,
|
||||
ease: "power2.out",
|
||||
},
|
||||
0.4,
|
||||
);
|
||||
|
||||
tl.to(
|
||||
regionPaths,
|
||||
{
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
duration: 0.4,
|
||||
stagger: {
|
||||
each: 0.08,
|
||||
from: "random",
|
||||
},
|
||||
ease: "back.out(1.4)",
|
||||
},
|
||||
1.0,
|
||||
);
|
||||
|
||||
tl.to(
|
||||
regionLabels,
|
||||
{
|
||||
opacity: 1,
|
||||
duration: 0.3,
|
||||
stagger: {
|
||||
each: 0.05,
|
||||
from: "random",
|
||||
},
|
||||
ease: "power2.out",
|
||||
},
|
||||
4.0,
|
||||
);
|
||||
|
||||
tl.to(
|
||||
"#spain-map .legend",
|
||||
{
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
duration: 0.6,
|
||||
ease: "power2.out",
|
||||
},
|
||||
5.5,
|
||||
);
|
||||
|
||||
tl.to(
|
||||
"#spain-map .source",
|
||||
{
|
||||
opacity: 1,
|
||||
duration: 0.5,
|
||||
ease: "power2.out",
|
||||
},
|
||||
6.0,
|
||||
);
|
||||
|
||||
var highlightRegions = ["MAD", "PVA", "NAV"];
|
||||
highlightRegions.forEach(function (abbr, i) {
|
||||
var el = regionsGroup.querySelector('[data-region="' + abbr + '"]');
|
||||
if (!el) return;
|
||||
|
||||
tl.to(
|
||||
el,
|
||||
{
|
||||
filter: "brightness(1.5) drop-shadow(0 0 8px rgba(255,255,255,0.4))",
|
||||
stroke: "#f8fafc",
|
||||
strokeWidth: 2.5,
|
||||
duration: 0.5,
|
||||
ease: "power2.out",
|
||||
},
|
||||
6.5 + i * 0.8,
|
||||
);
|
||||
|
||||
tl.to(
|
||||
el,
|
||||
{
|
||||
filter: "brightness(1) drop-shadow(0 0 0px rgba(255,255,255,0))",
|
||||
stroke: "#1e293b",
|
||||
strokeWidth: 0.8,
|
||||
duration: 0.5,
|
||||
ease: "power2.in",
|
||||
},
|
||||
7.0 + i * 0.8,
|
||||
);
|
||||
});
|
||||
|
||||
window.__timelines = window.__timelines || {};
|
||||
window.__timelines["spain-map"] = tl;
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -59,6 +59,10 @@
|
||||
"name": "world-map",
|
||||
"type": "hyperframes:block"
|
||||
},
|
||||
{
|
||||
"name": "spain-map",
|
||||
"type": "hyperframes:block"
|
||||
},
|
||||
{
|
||||
"name": "flowchart",
|
||||
"type": "hyperframes:block"
|
||||
|
||||
Reference in New Issue
Block a user