mirror of
https://github.com/nexu-io/open-design.git
synced 2026-06-01 03:14:35 +07:00
Add WeRead year-in-review HyperFrames template (#2131)
Co-authored-by: Tuola Ge <gexingli@refly.ai>
This commit is contained in:
parent
a38e09f931
commit
5254559cb1
8 changed files with 913 additions and 0 deletions
|
|
@ -788,6 +788,11 @@ export const FR_PROMPT_TEMPLATE_COPY: Record<string, Partial<Pick<PromptTemplate
|
|||
summary:
|
||||
'Clip hype vertical HyperFrames 1080×1920 de 6 secondes — compteur style Apple de $0 à $10,000 avec flash vert, particules money-burst, icône cash stack et kicker headline. Bâti sur le bloc HyperFrames `apple-money-count`.',
|
||||
},
|
||||
'weread-year-in-review-video-template': {
|
||||
title: 'Template vidéo WeRead Year in Review',
|
||||
summary:
|
||||
'Template vidéo HyperFrames 9:16 pour rapports annuels de lecture façon WeRead : papier chaud, typographie chinoise éditoriale, transitions de pages, statistiques de lecture, traces de notes, mots-clés d’intérêt et carte finale de persona lecteur.',
|
||||
},
|
||||
'hyperframes-product-reveal-minimal': {
|
||||
title: 'HyperFrames : product reveal minimal de 5 secondes',
|
||||
summary:
|
||||
|
|
|
|||
|
|
@ -788,6 +788,11 @@ export const RU_PROMPT_TEMPLATE_COPY: Record<string, Partial<Pick<PromptTemplate
|
|||
summary:
|
||||
'6-секундный вертикальный HyperFrames-клип 1080x1920 — счетчик в духе Apple от $0 до $10 000 с зеленой вспышкой, денежными частицами, иконкой пачки наличных и заголовком-kicker. Основано на каталожном блоке HyperFrames `apple-money-count`.',
|
||||
},
|
||||
'weread-year-in-review-video-template': {
|
||||
title: 'Видео-шаблон WeRead Year in Review',
|
||||
summary:
|
||||
'Вертикальный 9:16 HyperFrames-шаблон для годовых отчетов о чтении в стиле WeRead: теплая бумажная фактура, редакционная китайская типографика, переходы страниц, статистика чтения, следы заметок, ключевые интересы и финальная карточка читательского persona.',
|
||||
},
|
||||
'hyperframes-product-reveal-minimal': {
|
||||
title: 'HyperFrames: 5-секундный минималистичный product reveal',
|
||||
summary:
|
||||
|
|
|
|||
|
|
@ -826,6 +826,11 @@ const DE_PROMPT_TEMPLATE_COPY: Record<string, LocalizedPromptTemplateCopy> = {
|
|||
summary:
|
||||
'Ein 6-sekündiger vertikaler 1080×1920-HyperFrames-Hype-Clip – Apple-artiger $0 → $10.000-Counter mit grünem Flash, Money-Burst-Partikeln, Cash-Stack-Icon, Kicker-Headline. Aufgebaut auf dem HyperFrames-`apple-money-count`-Catalog-Block.',
|
||||
},
|
||||
'weread-year-in-review-video-template': {
|
||||
title: 'WeRead Year in Review Video Template',
|
||||
summary:
|
||||
'A 9:16 HyperFrames video template for WeRead-style annual reading reports: warm paper texture, editorial Chinese typography, book-page transitions, reading stats, note traces, interest keywords, and a final reading persona card.',
|
||||
},
|
||||
'hyperframes-product-reveal-minimal': {
|
||||
title: 'HyperFrames: 5-Sekunden minimaler Product Reveal',
|
||||
summary:
|
||||
|
|
|
|||
93
skills/weread-year-in-review-video-template/SKILL.md
Normal file
93
skills/weread-year-in-review-video-template/SKILL.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
name: weread-year-in-review-video-template
|
||||
description: |
|
||||
WeRead-inspired HyperFrames video template for vertical annual reading reports,
|
||||
personal reading dashboards, book-note recaps, and shareable year-in-review
|
||||
stories. Use when users want a 9:16 HTML-to-MP4 reading report with warm paper
|
||||
texture, editorial Chinese typography, book-page metaphors, data highlights,
|
||||
and deterministic motion.
|
||||
triggers:
|
||||
- "WeRead year in review"
|
||||
- "WeRead annual report"
|
||||
- "reading year in review video"
|
||||
- "annual reading report template"
|
||||
- "微信读书年度报告"
|
||||
- "读书年度总结视频"
|
||||
- "阅读年报 HyperFrames"
|
||||
od:
|
||||
mode: template
|
||||
surface: video
|
||||
type: hyperframes
|
||||
platform: mobile
|
||||
preview:
|
||||
type: html
|
||||
entry: example.html
|
||||
reload: debounce-100
|
||||
design_system:
|
||||
requires: false
|
||||
outputs:
|
||||
primary: index.html
|
||||
secondary:
|
||||
- template.html
|
||||
- example.html
|
||||
example_prompt: "Create a WeRead-style 9:16 HyperFrames annual reading report video with 12 scenes, warm paper texture, book-page transitions, reading stats, notes, keywords, and a final reading persona card."
|
||||
capabilities_required:
|
||||
- file_write
|
||||
---
|
||||
|
||||
# WeRead Year in Review Video Template
|
||||
|
||||
Create a vertical HyperFrames composition for annual reading reports: WeRead,
|
||||
Goodreads, Readwise, Notion reading logs, book clubs, or personal learning
|
||||
recaps. The template turns reading time, active days, bookshelf assets, notes,
|
||||
keywords, and a reading persona into a shareable 9:16 video.
|
||||
|
||||
## Resource Map
|
||||
|
||||
```text
|
||||
weread-year-in-review-video-template/
|
||||
├── SKILL.md
|
||||
├── assets/
|
||||
│ ├── template.html
|
||||
│ └── default-showcase.mp4
|
||||
├── references/
|
||||
│ └── checklist.md
|
||||
└── example.html
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Copy `assets/template.html` to `index.html`.
|
||||
2. Replace the default report data in the `REPORT` object:
|
||||
- owner/title
|
||||
- reading hours and active days
|
||||
- bookshelf and completion stats
|
||||
- note composition
|
||||
- interest keywords
|
||||
- reading persona and share line
|
||||
3. Preserve the 12-scene timeline unless the user asks for a shorter cut.
|
||||
4. Keep the WeRead-inspired visual language:
|
||||
- warm paper background
|
||||
- ink-blue typography
|
||||
- restrained WeRead green accents
|
||||
- book pages, bookmarks, highlights, note cards, and shelf metaphors
|
||||
5. Motion should feel like flipping through a reading journal. Avoid techy
|
||||
slide transitions, bouncy UI effects, and dashboard-loading motion.
|
||||
6. Keep the composition deterministic:
|
||||
- direct `data-start`, `data-duration`, and `data-track-index` attributes
|
||||
- no unseeded randomness
|
||||
- no infinite loops or `repeat: -1`
|
||||
- no dependency on scroll, hover, localStorage, or runtime class discovery
|
||||
7. Validate against `references/checklist.md` before emitting.
|
||||
|
||||
## Output Contract
|
||||
|
||||
Emit one short orientation sentence, then a single HTML artifact:
|
||||
|
||||
```xml
|
||||
<artifact identifier="weread-year-in-review-video-template" type="text/html" title="WeRead Year in Review Video Template">
|
||||
<!doctype html>
|
||||
<html>...</html>
|
||||
</artifact>
|
||||
```
|
||||
|
||||
Binary file not shown.
714
skills/weread-year-in-review-video-template/assets/template.html
Normal file
714
skills/weread-year-in-review-video-template/assets/template.html
Normal file
|
|
@ -0,0 +1,714 @@
|
|||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=1080, height=1920" />
|
||||
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||||
<title>WeRead Year in Review Video Template</title>
|
||||
<style>
|
||||
:root {
|
||||
--paper: #fbfaf5;
|
||||
--paper-warm: #f4f1e8;
|
||||
--ink: #27394c;
|
||||
--ink-soft: #526477;
|
||||
--muted: #788174;
|
||||
--line: rgba(39, 57, 76, 0.16);
|
||||
--weread: #65b782;
|
||||
--gold: #c4aa73;
|
||||
--sage: #8fa58c;
|
||||
--brick: #b97861;
|
||||
--font-display: "Songti SC", "Noto Serif CJK SC", "Source Han Serif SC", "SimSun", serif;
|
||||
--font-body: -apple-system, BlinkMacSystemFont, "PingFang SC", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
|
||||
--font-mono: "SFMono-Regular", ui-monospace, monospace;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html, body {
|
||||
margin: 0;
|
||||
width: 1080px;
|
||||
height: 1920px;
|
||||
overflow: hidden;
|
||||
background:
|
||||
radial-gradient(circle at 18% 8%, rgba(101, 183, 130, 0.12), transparent 30%),
|
||||
radial-gradient(circle at 82% 12%, rgba(196, 170, 115, 0.11), transparent 28%),
|
||||
linear-gradient(180deg, #f1f2eb, #e9ebe2);
|
||||
color: var(--ink);
|
||||
font-family: var(--font-body);
|
||||
}
|
||||
|
||||
#root {
|
||||
position: relative;
|
||||
width: 1080px;
|
||||
height: 1920px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scene {
|
||||
--accent: var(--weread);
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
grid-template-rows: 184px minmax(0, 1fr) 230px;
|
||||
padding: 78px 76px 82px;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255,255,255,0.38), transparent 36%),
|
||||
repeating-linear-gradient(0deg, transparent 0 39px, rgba(39,57,76,0.026) 40px),
|
||||
linear-gradient(90deg, transparent 0 62px, color-mix(in srgb, var(--accent), transparent 88%) 63px, transparent 64px),
|
||||
radial-gradient(circle at 82% 8%, color-mix(in srgb, var(--accent), transparent 90%), transparent 28%),
|
||||
var(--paper);
|
||||
border-radius: 34px;
|
||||
border: 1px solid rgba(39, 57, 76, 0.08);
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
.scene:first-of-type {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
.scene::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 36px;
|
||||
border: 1px solid rgba(39, 57, 76, 0.06);
|
||||
border-radius: 24px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.scene::after {
|
||||
content: attr(data-label);
|
||||
position: absolute;
|
||||
right: 74px;
|
||||
top: 66px;
|
||||
font: 700 18px/1 var(--font-mono);
|
||||
color: color-mix(in srgb, var(--accent), var(--ink) 45%);
|
||||
letter-spacing: 0.18em;
|
||||
}
|
||||
.scene.gold { --accent: var(--gold); }
|
||||
.scene.sage { --accent: var(--sage); }
|
||||
.scene.brick { --accent: var(--brick); }
|
||||
|
||||
.header { align-self: start; position: relative; z-index: 2; }
|
||||
.kicker {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
color: color-mix(in srgb, var(--ink), var(--accent) 22%);
|
||||
font: 800 22px/1 var(--font-mono);
|
||||
letter-spacing: 0.14em;
|
||||
}
|
||||
.kicker::before {
|
||||
content: "";
|
||||
width: 48px;
|
||||
height: 1px;
|
||||
background: currentColor;
|
||||
opacity: 0.46;
|
||||
}
|
||||
h1, h2, p { margin: 0; }
|
||||
h1, h2, .serif, .mega, .persona {
|
||||
font-family: var(--font-display);
|
||||
font-weight: 500;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 50px;
|
||||
font-size: 116px;
|
||||
line-height: 1.06;
|
||||
max-width: 820px;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 42px;
|
||||
font-size: 64px;
|
||||
line-height: 1.18;
|
||||
max-width: 820px;
|
||||
}
|
||||
.visual {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
min-height: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
.caption {
|
||||
align-self: end;
|
||||
position: relative;
|
||||
z-index: 3;
|
||||
padding-top: 30px;
|
||||
border-top: 1px solid color-mix(in srgb, var(--accent), transparent 70%);
|
||||
color: var(--muted);
|
||||
font-size: 30px;
|
||||
line-height: 1.62;
|
||||
font-weight: 650;
|
||||
}
|
||||
.caption strong { color: var(--ink); }
|
||||
|
||||
.cover-stack {
|
||||
width: 560px;
|
||||
height: 360px;
|
||||
border: 1px solid color-mix(in srgb, var(--weread), transparent 62%);
|
||||
border-radius: 8px 34px 34px 8px;
|
||||
background:
|
||||
linear-gradient(90deg, rgba(101,183,130,0.22) 0 18px, transparent 18px),
|
||||
linear-gradient(180deg, rgba(255,255,255,0.56), rgba(255,255,255,0.08)),
|
||||
#f8fbf4;
|
||||
box-shadow: -30px 26px 0 rgba(101,183,130,0.10), 24px 22px 0 rgba(101,183,130,0.06);
|
||||
}
|
||||
.cover-stack i {
|
||||
display: block;
|
||||
height: 1px;
|
||||
margin: 96px 88px 0;
|
||||
background: rgba(39,57,76,0.13);
|
||||
}
|
||||
.cover-stack i + i { width: 54%; margin-top: 38px; }
|
||||
.cover-number {
|
||||
margin-top: 88px;
|
||||
text-align: center;
|
||||
color: rgba(39,57,76,0.34);
|
||||
font: 500 68px/1 var(--font-display);
|
||||
}
|
||||
.cover-number small {
|
||||
display: block;
|
||||
margin-top: 16px;
|
||||
font: 700 22px/1 var(--font-body);
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
.badge {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 88px;
|
||||
color: var(--weread);
|
||||
font: 800 24px/1 var(--font-mono);
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
|
||||
.mega {
|
||||
color: var(--ink);
|
||||
font-size: 220px;
|
||||
line-height: 0.88;
|
||||
text-align: center;
|
||||
}
|
||||
.mega .unit {
|
||||
display: block;
|
||||
margin-top: 34px;
|
||||
color: var(--ink-soft);
|
||||
font: 800 44px/1.25 var(--font-body);
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.orbit {
|
||||
position: absolute;
|
||||
width: 620px;
|
||||
height: 620px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid rgba(101,183,130,0.24);
|
||||
}
|
||||
.orbit::before,
|
||||
.orbit::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 78px;
|
||||
border: 2px solid rgba(196,170,115,0.24);
|
||||
border-radius: inherit;
|
||||
}
|
||||
.orbit::after { inset: 160px; border-color: rgba(39,57,76,0.12); }
|
||||
|
||||
.path-card {
|
||||
width: 620px;
|
||||
height: 620px;
|
||||
position: relative;
|
||||
}
|
||||
.path-card svg { width: 100%; height: 100%; overflow: visible; }
|
||||
.path-card .mega {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-size: 190px;
|
||||
}
|
||||
|
||||
.kpi-grid {
|
||||
width: 850px;
|
||||
display: grid;
|
||||
grid-template-columns: 1.2fr 1fr 1fr;
|
||||
gap: 32px;
|
||||
align-items: end;
|
||||
}
|
||||
.kpi-main {
|
||||
grid-row: span 2;
|
||||
padding-right: 30px;
|
||||
border-right: 1px solid var(--line);
|
||||
}
|
||||
.kpi-main span,
|
||||
.kpi em {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
}
|
||||
.kpi-main b {
|
||||
display: block;
|
||||
margin-top: 34px;
|
||||
color: var(--ink);
|
||||
font: 500 92px/0.96 var(--font-display);
|
||||
}
|
||||
.kpi {
|
||||
min-height: 142px;
|
||||
padding-bottom: 22px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.kpi strong {
|
||||
display: block;
|
||||
margin-top: 18px;
|
||||
color: var(--ink);
|
||||
font: 500 62px/1 var(--font-display);
|
||||
}
|
||||
|
||||
.rhythm {
|
||||
width: 820px;
|
||||
display: grid;
|
||||
gap: 28px;
|
||||
position: relative;
|
||||
padding-left: 72px;
|
||||
}
|
||||
.month {
|
||||
display: grid;
|
||||
grid-template-columns: 44px 1fr;
|
||||
align-items: center;
|
||||
gap: 28px;
|
||||
color: var(--muted);
|
||||
font: 800 22px/1 var(--font-mono);
|
||||
}
|
||||
.month i {
|
||||
display: block;
|
||||
width: calc(var(--v) * 1%);
|
||||
height: 8px;
|
||||
border-radius: 999px;
|
||||
background: var(--c);
|
||||
transform-origin: left center;
|
||||
}
|
||||
.curve {
|
||||
position: absolute;
|
||||
left: 110px;
|
||||
right: 20px;
|
||||
top: 210px;
|
||||
height: 280px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.book-card {
|
||||
width: 640px;
|
||||
height: 430px;
|
||||
position: relative;
|
||||
border: 1px solid rgba(196,170,115,0.52);
|
||||
border-radius: 8px 34px 34px 8px;
|
||||
background: linear-gradient(90deg, rgba(185,120,97,0.18) 0 22px, rgba(255,255,255,0.26) 22px);
|
||||
}
|
||||
.book-card::before {
|
||||
content: "《定位》";
|
||||
position: absolute;
|
||||
left: 82px;
|
||||
top: 132px;
|
||||
color: var(--ink);
|
||||
font: 500 86px/1 var(--font-display);
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
.book-card::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 82px;
|
||||
right: 110px;
|
||||
bottom: 110px;
|
||||
height: 12px;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(90deg, var(--gold) 0 78%, rgba(196,170,115,0.18) 78% 100%);
|
||||
transform-origin: left center;
|
||||
}
|
||||
.bookmark {
|
||||
position: absolute;
|
||||
right: 74px;
|
||||
top: 0;
|
||||
width: 56px;
|
||||
height: 170px;
|
||||
background: var(--weread);
|
||||
clip-path: polygon(0 0,100% 0,100% 100%,50% 78%,0 100%);
|
||||
}
|
||||
|
||||
.map {
|
||||
width: 780px;
|
||||
height: 600px;
|
||||
position: relative;
|
||||
background:
|
||||
linear-gradient(var(--line) 1px, transparent 1px),
|
||||
linear-gradient(90deg, var(--line) 1px, transparent 1px);
|
||||
background-size: 86px 86px;
|
||||
mask-image: radial-gradient(circle, #000 0 58%, transparent 78%);
|
||||
}
|
||||
.topic {
|
||||
position: absolute;
|
||||
left: var(--x);
|
||||
top: var(--y);
|
||||
transform: translate(-50%, -50%);
|
||||
color: var(--c);
|
||||
font: 500 var(--s)/1 var(--font-display);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.topic::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: var(--d);
|
||||
height: var(--d);
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: 50%;
|
||||
border: 1px solid color-mix(in srgb, currentColor, transparent 60%);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.margin-notes {
|
||||
width: 760px;
|
||||
height: 620px;
|
||||
position: relative;
|
||||
}
|
||||
.margin-notes::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 20px;
|
||||
bottom: 20px;
|
||||
width: 1px;
|
||||
background: var(--line);
|
||||
}
|
||||
.note {
|
||||
position: absolute;
|
||||
left: var(--x);
|
||||
top: var(--y);
|
||||
width: var(--w);
|
||||
padding-top: 18px;
|
||||
border-top: 2px solid color-mix(in srgb, var(--c), transparent 30%);
|
||||
color: var(--c);
|
||||
font: 800 26px/1.35 var(--font-body);
|
||||
}
|
||||
.note b {
|
||||
display: block;
|
||||
margin-top: 12px;
|
||||
font: 500 54px/1 var(--font-display);
|
||||
}
|
||||
|
||||
.shelves {
|
||||
width: 800px;
|
||||
display: grid;
|
||||
gap: 70px;
|
||||
}
|
||||
.asset-number {
|
||||
position: absolute;
|
||||
right: 106px;
|
||||
top: 260px;
|
||||
text-align: right;
|
||||
color: var(--ink);
|
||||
font: 500 120px/0.9 var(--font-display);
|
||||
}
|
||||
.asset-number small {
|
||||
display: block;
|
||||
margin-top: 24px;
|
||||
color: var(--muted);
|
||||
font: 800 24px/1 var(--font-body);
|
||||
}
|
||||
.shelf-row {
|
||||
position: relative;
|
||||
min-height: 118px;
|
||||
padding-top: 38px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.shelf-row i {
|
||||
display: block;
|
||||
width: max(var(--w), var(--min, 0px));
|
||||
height: var(--h);
|
||||
border-radius: 999px;
|
||||
background: var(--c);
|
||||
opacity: var(--o, 0.78);
|
||||
}
|
||||
.shelf-row span {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
color: var(--muted);
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.shelf-row b {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
color: var(--ink);
|
||||
font: 500 48px/1 var(--font-display);
|
||||
}
|
||||
|
||||
.pages {
|
||||
width: 690px;
|
||||
height: 650px;
|
||||
position: relative;
|
||||
}
|
||||
.page-stack i {
|
||||
position: absolute;
|
||||
left: calc(var(--n) * 24px);
|
||||
top: calc(var(--n) * 16px);
|
||||
width: 430px;
|
||||
height: 560px;
|
||||
border-radius: 8px 34px 34px 8px;
|
||||
border: 1px solid color-mix(in srgb, var(--c), transparent 32%);
|
||||
background: color-mix(in srgb, var(--c), white 88%);
|
||||
}
|
||||
.progress {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 14px;
|
||||
border-radius: 999px;
|
||||
background: rgba(39,57,76,0.12);
|
||||
}
|
||||
.progress i {
|
||||
display: block;
|
||||
width: 70.52%;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: var(--weread);
|
||||
transform-origin: left center;
|
||||
}
|
||||
.legend {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 88px;
|
||||
display: grid;
|
||||
gap: 30px;
|
||||
color: var(--muted);
|
||||
font-size: 26px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.legend span::before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 14px;
|
||||
border-radius: 50%;
|
||||
background: var(--c);
|
||||
}
|
||||
|
||||
.notes-scene {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
gap: 54px;
|
||||
width: 860px;
|
||||
height: 880px;
|
||||
}
|
||||
.notes-scene .mega { font-size: 190px; }
|
||||
.word-cloud {
|
||||
position: relative;
|
||||
min-height: 360px;
|
||||
border-top: 1px solid var(--line);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.word-cloud span {
|
||||
position: absolute;
|
||||
left: var(--x);
|
||||
top: var(--y);
|
||||
transform: translate(-50%, -50%) rotate(var(--r));
|
||||
color: var(--c);
|
||||
font-family: var(--font-display);
|
||||
font-size: var(--s);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.annotation {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
border-left: 2px solid rgba(185,120,97,0.46);
|
||||
padding-left: 22px;
|
||||
}
|
||||
.annotation div {
|
||||
display: grid;
|
||||
grid-template-columns: 150px 1fr;
|
||||
align-items: center;
|
||||
min-height: 70px;
|
||||
padding: 0 22px;
|
||||
border: 1px solid color-mix(in srgb, var(--c), transparent 48%);
|
||||
border-radius: 14px;
|
||||
color: var(--muted);
|
||||
font-size: 24px;
|
||||
font-weight: 750;
|
||||
}
|
||||
.annotation b {
|
||||
color: var(--c);
|
||||
font: 500 44px/1 var(--font-display);
|
||||
}
|
||||
|
||||
.persona-card {
|
||||
width: 760px;
|
||||
min-height: 650px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
text-align: center;
|
||||
border: 1px solid rgba(101,183,130,0.52);
|
||||
border-radius: 90px 90px 34px 34px;
|
||||
background: radial-gradient(circle at 50% 18%, rgba(101,183,130,0.11), transparent 36%);
|
||||
}
|
||||
.persona {
|
||||
font-size: 126px;
|
||||
line-height: 1.08;
|
||||
}
|
||||
.chips {
|
||||
margin: 56px auto 0;
|
||||
max-width: 660px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 18px;
|
||||
}
|
||||
.chips span {
|
||||
border: 1px solid rgba(101,183,130,0.50);
|
||||
border-radius: 999px;
|
||||
padding: 14px 22px;
|
||||
color: var(--ink-soft);
|
||||
font-size: 24px;
|
||||
font-weight: 800;
|
||||
background: rgba(255,255,255,0.24);
|
||||
}
|
||||
.share {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 18px;
|
||||
margin-top: 34px;
|
||||
color: var(--ink);
|
||||
font-size: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
.share b {
|
||||
display: block;
|
||||
font: 500 40px/1 var(--font-display);
|
||||
}
|
||||
|
||||
@keyframes gentleFloat {
|
||||
from { transform: translateY(0); }
|
||||
to { transform: translateY(-8px); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main id="root" data-composition-id="main" data-start="0" data-duration="40.8" data-width="1080" data-height="1920">
|
||||
<section class="scene clip" id="scene-01" data-label="01" data-start="0" data-duration="3.8" data-track-index="10">
|
||||
<div class="header"><div class="kicker">年度开场</div><h1>我的微信读书<br />年度报告</h1></div>
|
||||
<div class="visual"><div class="cover-stack"><i></i><i></i><div class="cover-number">1693<small>小时 30 分钟</small></div></div><div class="badge">2024-2026 读书报告</div></div>
|
||||
<p class="caption">过去两年,我在书里停留了 <strong>1693 小时 30 分钟</strong>。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip" id="scene-02" data-label="02" data-start="3.8" data-duration="3.3" data-track-index="10">
|
||||
<div class="header"><div class="kicker">停留时间</div></div>
|
||||
<div class="visual"><div class="orbit"></div><div class="mega">1693<span class="unit">小时 30 分钟</span></div></div>
|
||||
<p class="caption">有些时间没有被消耗,它们被一页一页地存了下来。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip" id="scene-03" data-label="03" data-start="7.1" data-duration="3.3" data-track-index="10">
|
||||
<div class="header"><div class="kicker">持续回到书里</div><h2>439 天,<br />我一次次回到书里</h2></div>
|
||||
<div class="visual"><div class="path-card"><svg viewBox="0 0 620 620" aria-hidden="true"><path d="M308 48 C148 164 150 270 292 320 C468 382 472 496 322 558" fill="none" stroke="rgba(101,183,130,.45)" stroke-width="4"/><g fill="var(--paper)" stroke="var(--ink-soft)" stroke-width="3"><circle cx="308" cy="48" r="9"/><circle cx="220" cy="212" r="9"/><circle cx="292" cy="320" r="9"/><circle cx="448" cy="420" r="9"/><circle cx="322" cy="558" r="9"/></g></svg><div class="mega">439<span class="unit">天</span></div></div></div>
|
||||
<p class="caption">不是每天都读很多,但每一次打开,都把生活往内心推近一点。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip gold" id="scene-04" data-label="04" data-start="10.4" data-duration="3.3" data-track-index="10">
|
||||
<div class="header"><div class="kicker">年度总览</div><h2>这一年,阅读变成了<br />可以翻看的积累。</h2></div>
|
||||
<div class="visual"><div class="kpi-grid"><div class="kpi-main"><span>阅读时长</span><b>1693小时<br />30分钟</b></div><div class="kpi"><em>有效阅读日</em><strong>439</strong></div><div class="kpi"><em>书架条目</em><strong>771</strong></div><div class="kpi"><em>笔记总量</em><strong>10950</strong></div><div class="kpi"><em>有笔记书籍</em><strong>42</strong></div><div class="kpi"><em>语义文本</em><strong>9900</strong></div></div></div>
|
||||
<p class="caption">数字不是结论,它们只是提醒我:很多思考已经悄悄留下。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip gold" id="scene-05" data-label="05" data-start="13.7" data-duration="3.2" data-track-index="10">
|
||||
<div class="header"><div class="kicker">阅读节律</div><h2>我的阅读节律</h2></div>
|
||||
<div class="visual"><div class="rhythm"><div class="month"><span>01</span><i style="--v:38;--c:var(--sage)"></i></div><div class="month"><span>02</span><i style="--v:72;--c:var(--gold)"></i></div><div class="month"><span>03</span><i style="--v:66;--c:var(--ink)"></i></div><div class="month"><span>04</span><i style="--v:78;--c:var(--weread)"></i></div><div class="month"><span>05</span><i style="--v:70;--c:var(--sage)"></i></div><div class="month"><span>06</span><i style="--v:68;--c:var(--ink)"></i></div><div class="month"><span>07</span><i style="--v:58;--c:var(--gold)"></i></div><div class="month"><span>08</span><i style="--v:74;--c:var(--weread)"></i></div><div class="month"><span>09</span><i style="--v:80;--c:var(--ink)"></i></div><div class="month"><span>10</span><i style="--v:84;--c:var(--gold)"></i></div><div class="month"><span>11</span><i style="--v:70;--c:var(--sage)"></i></div><div class="month"><span>12</span><i style="--v:46;--c:var(--weread)"></i></div><svg class="curve" viewBox="0 0 700 280"><path d="M10 210 C72 92 134 160 190 118 S315 74 368 148 S500 220 558 92 S646 120 690 58" fill="none" stroke="var(--ink)" stroke-width="4"/></svg></div></div>
|
||||
<p class="caption">高峰和低谷都在,但书页始终没有离开我的生活。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip gold" id="scene-06" data-label="06" data-start="16.9" data-duration="3.1" data-track-index="10">
|
||||
<div class="header"><div class="kicker">读得最久</div><h2>我读得最久的一本书</h2></div>
|
||||
<div class="visual"><div class="book-card"><div class="bookmark"></div></div></div>
|
||||
<p class="caption">《定位》停留得最久,也让“如何被记住”这件事反复出现。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip sage" id="scene-07" data-label="07" data-start="20" data-duration="3.3" data-track-index="10">
|
||||
<div class="header"><div class="kicker">兴趣地图</div><h2>我的阅读兴趣地图</h2></div>
|
||||
<div class="visual"><div class="map"><span class="topic" style="--x:50%;--y:43%;--s:72px;--d:230px;--c:var(--ink)">AI技术</span><span class="topic" style="--x:24%;--y:66%;--s:48px;--d:140px;--c:var(--gold)">创业</span><span class="topic" style="--x:76%;--y:66%;--s:44px;--d:160px;--c:var(--weread)">产品增长</span><span class="topic" style="--x:58%;--y:78%;--s:38px;--d:112px;--c:var(--brick)">商业化</span><span class="topic" style="--x:76%;--y:28%;--s:36px;--d:106px;--c:var(--sage)">系统思维</span><span class="topic" style="--x:26%;--y:28%;--s:34px;--d:100px;--c:var(--muted)">组织管理</span></div></div>
|
||||
<p class="caption">我更多在技术、商业和系统之间寻找答案。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip sage" id="scene-08" data-label="08" data-start="23.3" data-duration="3.2" data-track-index="10">
|
||||
<div class="header"><div class="kicker">阅读偏好</div><h2>我的阅读偏好</h2></div>
|
||||
<div class="visual"><div class="margin-notes"><div class="note" style="--x:0%;--y:40px;--w:350px;--c:var(--ink)">最高峰<b>AI 技术</b></div><div class="note" style="--x:54%;--y:145px;--w:330px;--c:var(--gold)">另一条主线<b>创业管理</b></div><div class="note" style="--x:10%;--y:320px;--w:320px;--c:var(--weread)">持续展开<b>产品增长</b></div><div class="note" style="--x:56%;--y:440px;--w:330px;--c:var(--sage)">底层方法<b>系统思维</b></div></div></div>
|
||||
<p class="caption">偏好不是标签,而是我反复追问同一类问题的路径。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip sage" id="scene-09" data-label="09" data-start="26.5" data-duration="3.2" data-track-index="10">
|
||||
<div class="header"><div class="kicker">书架资产</div><h2>我的书架资产</h2></div>
|
||||
<div class="visual"><div class="asset-number">771<small>书架条目</small></div><div class="shelves"><div class="shelf-row"><span>电子书</span><b>94.03%</b><i style="--h:54px;--w:94.03%;--c:var(--ink)"></i></div><div class="shelf-row"><span>有声 / 专辑</span><b>5.84%</b><i style="--h:24px;--w:5.84%;--min:42px;--c:var(--gold);--o:.72"></i></div><div class="shelf-row"><span>文章收藏</span><b>0.13%</b><i style="--h:10px;--w:.13%;--min:12px;--c:var(--weread);--o:.9"></i></div></div></div>
|
||||
<p class="caption">书架不是仓库,它更像一组长期问题的索引。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip sage" id="scene-10" data-label="10" data-start="29.7" data-duration="3.2" data-track-index="10">
|
||||
<div class="header"><div class="kicker">读完进度</div><h2>我和这些书的进度</h2></div>
|
||||
<div class="visual"><div class="pages"><div class="page-stack"><i style="--n:0;--c:var(--weread)"></i><i style="--n:1;--c:var(--gold)"></i><i style="--n:2;--c:var(--sage)"></i><i style="--n:3;--c:var(--ink)"></i><i style="--n:4;--c:var(--brick)"></i></div><div class="legend"><span style="--c:var(--weread)">已读完 70.52%</span><span style="--c:var(--ink)">未读完 23.64%</span><span style="--c:var(--sage)">连载 1.95%</span><span style="--c:var(--gold)">已完结专辑 3.89%</span></div><div class="progress"><i></i></div></div></div>
|
||||
<p class="caption">有些书已经合上,有些仍把书签夹在下一次打开的位置。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip brick" id="scene-11" data-label="11" data-start="32.9" data-duration="3.7" data-track-index="10">
|
||||
<div class="header"><div class="kicker">思考痕迹</div></div>
|
||||
<div class="visual"><div class="notes-scene"><div class="mega">10950<span class="unit">条笔记</span></div><div class="word-cloud"><span style="--x:50%;--y:46%;--r:-4deg;--s:62px;--c:var(--ink)">智能体</span><span style="--x:22%;--y:34%;--r:7deg;--s:40px;--c:var(--gold)">商业化</span><span style="--x:76%;--y:34%;--r:-7deg;--s:38px;--c:var(--weread)">系统思维</span><span style="--x:36%;--y:76%;--r:5deg;--s:34px;--c:var(--brick)">产品增长</span><span style="--x:74%;--y:76%;--r:4deg;--s:31px;--c:var(--muted)">创业</span></div><div class="annotation"><div style="--c:var(--ink)"><b>68.08%</b><span>划线,把重要句子留下</span></div><div style="--c:var(--brick)"><b>22.33%</b><span>想法,和作者短暂停顿</span></div><div style="--c:var(--weread)"><b>9.59%</b><span>书签,留给下一次打开</span></div></div></div></div>
|
||||
<p class="caption">真正留下来的,不只是读过,而是那些被我停下来标记的瞬间。</p>
|
||||
</section>
|
||||
|
||||
<section class="scene clip brick" id="scene-12" data-label="12" data-start="36.6" data-duration="4.2" data-track-index="10">
|
||||
<div class="header"><div class="kicker">阅读人格</div><h2>我的阅读人格</h2></div>
|
||||
<div class="visual"><div class="persona-card"><div><div class="persona">技术商业<br />建造者</div><div class="chips"><span>AI技术</span><span>创业</span><span>产品增长</span><span>商业化</span><span>系统思维</span><span>智能体</span></div></div></div></div>
|
||||
<div><p class="caption">我习惯从技术、产品和商业系统里寻找答案。</p><div class="share"><span><b>1693小时</b>阅读</span><span><b>10950条</b>笔记</span><span><b>42本</b>深度标记书籍</span></div></div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
window.__timelines = window.__timelines || {};
|
||||
var scenes = Array.from(document.querySelectorAll(".scene"));
|
||||
function showScene(index) {
|
||||
scenes.forEach(function (scene, i) {
|
||||
scene.style.visibility = i === index ? "visible" : "hidden";
|
||||
scene.style.opacity = i === index ? "1" : "0";
|
||||
});
|
||||
}
|
||||
|
||||
var tl = gsap.timeline({ paused: true });
|
||||
scenes.forEach(function (scene, index) {
|
||||
var start = Number(scene.dataset.start);
|
||||
var duration = Number(scene.dataset.duration);
|
||||
tl.set(scene, { autoAlpha: 1 }, start);
|
||||
tl.fromTo(scene, { y: 26 }, { y: 0, duration: 0.55, ease: "power3.out", immediateRender: false }, start);
|
||||
tl.from(scene.querySelectorAll(".kicker, h1, h2"), { autoAlpha: 0, y: 28, duration: 0.6, stagger: 0.08, ease: "power3.out", immediateRender: false }, start + 0.08);
|
||||
tl.from(scene.querySelectorAll(".visual > *"), { autoAlpha: 0, y: 34, duration: 0.72, stagger: 0.08, ease: "power3.out", immediateRender: false }, start + 0.35);
|
||||
tl.from(scene.querySelectorAll(".mega, .persona"), { autoAlpha: 0, y: 18, duration: 0.65, ease: "power3.out", immediateRender: false }, start + 0.45);
|
||||
tl.from(scene.querySelectorAll(".month i, .progress i, .shelf-row i"), { scaleX: 0, duration: 0.85, stagger: 0.04, ease: "power3.out", immediateRender: false }, start + 0.75);
|
||||
tl.from(scene.querySelectorAll(".topic, .note, .word-cloud span, .annotation div, .chips span, .kpi, .legend span"), { autoAlpha: 0, y: 14, duration: 0.48, stagger: 0.07, ease: "power2.out", immediateRender: false }, start + 0.68);
|
||||
tl.from(scene.querySelectorAll(".caption, .share, .badge"), { autoAlpha: 0, y: 16, duration: 0.55, ease: "power2.out", immediateRender: false }, start + Math.min(1.2, duration - 1.2));
|
||||
tl.to(scene, { y: -18, autoAlpha: 0, duration: 0.45, ease: "power2.inOut" }, start + duration - 0.46);
|
||||
tl.set(scene, { autoAlpha: 0 }, start + duration);
|
||||
});
|
||||
window.__timelines.main = tl;
|
||||
showScene(0);
|
||||
|
||||
var jumpTimes = [0, 3.8, 7.1, 10.4, 13.7, 16.9, 20, 23.3, 26.5, 29.7, 32.9, 36.6];
|
||||
window.addEventListener("keydown", function (event) {
|
||||
var keys = ["1","2","3","4","5","6","7","8","9","0","-","="];
|
||||
var index = keys.indexOf(event.key);
|
||||
if (index >= 0) {
|
||||
showScene(index);
|
||||
tl.pause(jumpTimes[index] + 0.8);
|
||||
}
|
||||
if (event.key.toLowerCase() === "r") {
|
||||
showScene(0);
|
||||
tl.restart();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
64
skills/weread-year-in-review-video-template/example.html
Normal file
64
skills/weread-year-in-review-video-template/example.html
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>WeRead Year in Review Video Template</title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
background: #eef0e8;
|
||||
color: #243649;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
.top {
|
||||
height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid rgba(36, 54, 73, 0.14);
|
||||
background: rgba(250, 249, 244, 0.92);
|
||||
letter-spacing: 0.03em;
|
||||
font-size: 12px;
|
||||
}
|
||||
.top b { color: #243649; }
|
||||
.top span { color: #6b766f; }
|
||||
.stage {
|
||||
height: calc(100% - 53px);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
min-height: 0;
|
||||
}
|
||||
.pane {
|
||||
min-width: 0;
|
||||
border-right: 1px solid rgba(36, 54, 73, 0.14);
|
||||
background: #f6f5ef;
|
||||
}
|
||||
.pane:last-child { border-right: 0; background: #111; }
|
||||
iframe, video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
display: block;
|
||||
}
|
||||
video { object-fit: contain; background: #000; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top">
|
||||
<b>WEREAD YEAR IN REVIEW · HYPERFRAMES VIDEO TEMPLATE</b>
|
||||
<span>Left: editable HTML template · Right: rendered MP4 showcase</span>
|
||||
</div>
|
||||
<div class="stage">
|
||||
<div class="pane">
|
||||
<iframe src="./assets/template.html" title="WeRead Year in Review template preview"></iframe>
|
||||
</div>
|
||||
<div class="pane">
|
||||
<video controls preload="metadata" src="./assets/default-showcase.mp4"></video>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# Checklist
|
||||
|
||||
## P0
|
||||
|
||||
- `assets/template.html` exists and opens directly in a browser.
|
||||
- `example.html` previews both the editable template and `assets/default-showcase.mp4`.
|
||||
- Skill frontmatter uses `od.mode: template`, `od.surface: video`, and `od.type: hyperframes`.
|
||||
- Composition is vertical 9:16, 1080x1920, with exactly 12 scenes.
|
||||
- Every scene has direct `class="scene clip"` plus explicit `data-start`, `data-duration`, and `data-track-index` attributes.
|
||||
- Rendered MP4 is not blank: contact sheet must show visible content in all 12 scenes.
|
||||
- No scene has text/component overlap at 1080x1920.
|
||||
- Timeline is deterministic: no unseeded randomness and no infinite repeats.
|
||||
- Template avoids sandbox-hostile APIs (`localStorage`, `sessionStorage`, `alert`, `confirm`, `prompt`).
|
||||
|
||||
## P1
|
||||
|
||||
- Motion feels like flipping through a reading journal: calm page reveals, highlight strokes, note cards, and bookmark accents.
|
||||
- Key stats remain legible after video compression on mobile social feeds.
|
||||
- Scene holds stay between 2.8 and 4.2 seconds by default.
|
||||
- The final persona card is strong enough to serve as a social sharing frame.
|
||||
|
||||
## P2
|
||||
|
||||
- Keyboard preview controls (`1`-`9`, `0`, `-`, `=`, `r`) jump to scenes locally.
|
||||
- The template can be adapted to non-WeRead reading data without changing the visual system.
|
||||
- Static fallback remains readable if GSAP fails to load.
|
||||
|
||||
Loading…
Reference in a new issue