@biunow/agent-biuart 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/server.mjs +575 -0
- package/data/styles.json +533 -0
- package/engine/audit_clip.py +46 -0
- package/engine/clip.html +24 -0
- package/engine/clip.js +104 -0
- package/engine/clip_schema.json +19 -0
- package/engine/clips/t1_3b1b.js +203 -0
- package/engine/clips/t2_keynote_ui.js +347 -0
- package/engine/clips/t3_finance_chart.js +206 -0
- package/engine/clips/y1_kurzgesagt.js +183 -0
- package/engine/clips/y2_vox.js +150 -0
- package/engine/clips/y3_whiteboard.js +209 -0
- package/engine/clips/y4_storytime.js +194 -0
- package/engine/clips/y5_kinetic_type.js +134 -0
- package/engine/compare.py +19 -0
- package/engine/demos/_shared/hero/c1_0.png +0 -0
- package/engine/demos/_shared/hero/c1_1.png +0 -0
- package/engine/demos/_shared/hero/c1_2.png +0 -0
- package/engine/demos/_shared/hero/c3_line.png +0 -0
- package/engine/demos/_shared/hero.js +96 -0
- package/engine/demos/long_scroll/eras.js +23 -0
- package/engine/demos/long_scroll/frames/8bit_act/01.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/02.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/03.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/04.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/05.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/06.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/07.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/08.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_act/meta.json +69 -0
- package/engine/demos/long_scroll/frames/8bit_walk/01.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/02.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/03.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/04.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/05.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/06.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/07.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/08.png +0 -0
- package/engine/demos/long_scroll/frames/8bit_walk/meta.json +69 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/01.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/02.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/03.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/04.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/05.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/06.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/07.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/08.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_dodge/meta.json +69 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/01.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/02.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/03.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/04.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/05.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/06.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/07.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/08.png +0 -0
- package/engine/demos/long_scroll/frames/egypt_walk8/meta.json +69 -0
- package/engine/demos/long_scroll/frames/monet_throw/01.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/02.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/03.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/04.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/05.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/06.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/07.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/08.png +0 -0
- package/engine/demos/long_scroll/frames/monet_throw/meta.json +71 -0
- package/engine/demos/long_scroll/frames/monet_walk/01.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/02.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/03.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/04.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/05.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/06.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/07.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/08.png +0 -0
- package/engine/demos/long_scroll/frames/monet_walk/meta.json +71 -0
- package/engine/demos/long_scroll/lib/acts.js +87 -0
- package/engine/demos/long_scroll/lib/crossing.js +463 -0
- package/engine/demos/long_scroll/lib/world.js +143 -0
- package/engine/demos/long_scroll/lib/xing2_ding.js +42 -0
- package/engine/demos/long_scroll/lib/xing2_jia.js +114 -0
- package/engine/demos/long_scroll/lib/xing2_yi.js +133 -0
- package/engine/demos/long_scroll/segments/02_egypt.js +234 -0
- package/engine/demos/long_scroll/segments/14_8bit.js +118 -0
- package/engine/demos/long_scroll/segments/28_monet.js +86 -0
- package/engine/demos/t1_3b1b/eras.js +11 -0
- package/engine/demos/t1_3b1b/t1_s1.js +101 -0
- package/engine/demos/t1_3b1b/t1_s2.js +74 -0
- package/engine/demos/t1_3b1b/t1_s3.js +65 -0
- package/engine/demos/t2_keynote_ui/eras.js +10 -0
- package/engine/demos/t2_keynote_ui/t2_s1.js +57 -0
- package/engine/demos/t2_keynote_ui/t2_s2.js +70 -0
- package/engine/demos/t2_keynote_ui/t2_s3.js +61 -0
- package/engine/demos/t3_finance_chart/eras.js +11 -0
- package/engine/demos/t3_finance_chart/t3_s1.js +48 -0
- package/engine/demos/t3_finance_chart/t3_s2.js +42 -0
- package/engine/demos/t3_finance_chart/t3_s3.js +51 -0
- package/engine/demos/y1_kurzgesagt/eras.js +10 -0
- package/engine/demos/y1_kurzgesagt/kurzgesagt.js +347 -0
- package/engine/demos/y2_vox/eras.js +10 -0
- package/engine/demos/y2_vox/vox.js +240 -0
- package/engine/demos/y3_whiteboard/eras.js +10 -0
- package/engine/demos/y3_whiteboard/whiteboard.js +162 -0
- package/engine/demos/y4_storytime/eras.js +14 -0
- package/engine/demos/y4_storytime/s1_desk.js +18 -0
- package/engine/demos/y4_storytime/s2_screen.js +82 -0
- package/engine/demos/y4_storytime/s3_react.js +39 -0
- package/engine/demos/y4_storytime/s4_wide.js +16 -0
- package/engine/demos/y4_storytime/s5_close.js +18 -0
- package/engine/demos/y4_storytime/story.js +25 -0
- package/engine/demos/y4_storytime/vo_env.js +2 -0
- package/engine/demos/y4_storytime/world.js +73 -0
- package/engine/demos/y5_kinetic_type/eras.js +16 -0
- package/engine/demos/y5_kinetic_type/k1_title.js +38 -0
- package/engine/demos/y5_kinetic_type/k2_complete.js +55 -0
- package/engine/demos/y5_kinetic_type/k3_chat.js +47 -0
- package/engine/demos/y5_kinetic_type/k4_agent.js +49 -0
- package/engine/demos/y5_kinetic_type/kinetic.js +52 -0
- package/engine/engine.js +277 -0
- package/engine/eras.js +60 -0
- package/engine/eras_gallery.js +115 -0
- package/engine/eras_style_studies.js +20 -0
- package/engine/examples/assets/K/347/272/277/345/233/276_/346/250/252/345/261/217.png +0 -0
- package/engine/examples/assets//347/273/210/347/253/257_for/345/276/252/347/216/257/346/261/202/345/222/214.png +0 -0
- package/engine/examples/assets//347/273/210/347/253/257_sum/346/261/202/345/222/214.png +0 -0
- package/engine/examples/assets//350/220/245/346/224/266/345/233/276_/347/253/226/345/261/217.png +0 -0
- package/engine/examples/assets//350/264/242/347/273/217/345/233/276/350/241/250_/346/250/252/345/261/217.png +0 -0
- package/engine/examples/t1_3b1b.json +19 -0
- package/engine/examples/t2_fullbleed_pulse.json +15 -0
- package/engine/examples/t2_keynote_ui.json +15 -0
- package/engine/examples/t3_finance_chart.json +29 -0
- package/engine/examples/y1_kurzgesagt.json +16 -0
- package/engine/examples/y2_vox.json +14 -0
- package/engine/examples/y3_whiteboard.json +17 -0
- package/engine/examples/y4_storytime.json +52 -0
- package/engine/examples/y5_kinetic_type.json +14 -0
- package/engine/index.html +42 -0
- package/engine/lib/THREE_LICENSE.txt +21 -0
- package/engine/lib/brush.js +149 -0
- package/engine/lib/camera.js +99 -0
- package/engine/lib/chart.js +152 -0
- package/engine/lib/collage.js +97 -0
- package/engine/lib/diagram.js +264 -0
- package/engine/lib/finish.js +70 -0
- package/engine/lib/fonts/AlfaSlabOne-400.woff +0 -0
- package/engine/lib/fonts/Anton-400.woff +0 -0
- package/engine/lib/fonts/ArchivoBlack-400.woff +0 -0
- package/engine/lib/fonts/Bangers-400.woff +0 -0
- package/engine/lib/fonts/Caveat-600.woff +0 -0
- package/engine/lib/fonts/Cinzel-400.woff +0 -0
- package/engine/lib/fonts/Cinzel-700.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-500.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-500i.woff +0 -0
- package/engine/lib/fonts/CormorantGaramond-700.woff +0 -0
- package/engine/lib/fonts/EBGaramond-400.woff +0 -0
- package/engine/lib/fonts/EBGaramond-400i.woff +0 -0
- package/engine/lib/fonts/EBGaramond-600.woff +0 -0
- package/engine/lib/fonts/Exo2-800i.woff +0 -0
- package/engine/lib/fonts/GochiHand-400.woff +0 -0
- package/engine/lib/fonts/IMFellEnglish-400.woff +0 -0
- package/engine/lib/fonts/IMFellEnglish-400i.woff +0 -0
- package/engine/lib/fonts/Inter-var.woff +0 -0
- package/engine/lib/fonts/JosefinSans-700.woff +0 -0
- package/engine/lib/fonts/Kalam-700.woff +0 -0
- package/engine/lib/fonts/LICENSES.md +40 -0
- package/engine/lib/fonts/LXGWWenKai-500.woff +0 -0
- package/engine/lib/fonts/LibreBaskerville-400.woff +0 -0
- package/engine/lib/fonts/LibreBaskerville-700.woff +0 -0
- package/engine/lib/fonts/LilitaOne-400.woff +0 -0
- package/engine/lib/fonts/Marcellus-400.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-500.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-700.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-800.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-900.woff +0 -0
- package/engine/lib/fonts/NotoSansSC-sub.woff +0 -0
- package/engine/lib/fonts/NotoSerifJP-600.woff +0 -0
- package/engine/lib/fonts/NotoSerifSC-sub.woff +0 -0
- package/engine/lib/fonts/OFL.txt +94 -0
- package/engine/lib/fonts/PlayfairDisplay-400i.woff +0 -0
- package/engine/lib/fonts/PlayfairDisplay-700.woff +0 -0
- package/engine/lib/fonts/PlayfairDisplay-700i.woff +0 -0
- package/engine/lib/fonts/Poppins-600.woff +0 -0
- package/engine/lib/fonts/Poppins-700.woff +0 -0
- package/engine/lib/fonts/Poppins-800.woff +0 -0
- package/engine/lib/fonts/PressStart2P-400.woff +0 -0
- package/engine/lib/fonts/Righteous-400.woff +0 -0
- package/engine/lib/fonts/RobotoCondensed-var.woff +0 -0
- package/engine/lib/fonts/Rye-400.woff +0 -0
- package/engine/lib/fonts/UnifrakturMaguntia-400.woff +0 -0
- package/engine/lib/fonts/cmunrm.woff +0 -0
- package/engine/lib/fonts/cmunti.woff +0 -0
- package/engine/lib/fonts/index.json +1 -0
- package/engine/lib/fonts.js +56 -0
- package/engine/lib/kit.js +91 -0
- package/engine/lib/media.js +118 -0
- package/engine/lib/medium.js +258 -0
- package/engine/lib/motion.js +111 -0
- package/engine/lib/paint.js +200 -0
- package/engine/lib/palettes.js +57 -0
- package/engine/lib/post.js +108 -0
- package/engine/lib/render.js +189 -0
- package/engine/lib/rig.js +390 -0
- package/engine/lib/rig_huashu.js +171 -0
- package/engine/lib/three.min.js +7 -0
- package/engine/lib/toon.js +186 -0
- package/engine/lib/typo.js +136 -0
- package/engine/lib/ui.js +141 -0
- package/engine/lib/util.js +92 -0
- package/engine/render.py +157 -0
- package/engine/scenes/01_cave.js +364 -0
- package/engine/scenes/02_egypt.js +524 -0
- package/engine/scenes/03_greek.js +448 -0
- package/engine/scenes/04_roman.js +555 -0
- package/engine/scenes/05_gothic.js +522 -0
- package/engine/scenes/06_renaissance.js +338 -0
- package/engine/scenes/08_impressionism.js +206 -0
- package/engine/scenes/09_postimp.js +183 -0
- package/engine/scenes/10_nouveau.js +334 -0
- package/engine/scenes/11_cubism.js +265 -0
- package/engine/scenes/12_bauhaus.js +214 -0
- package/engine/scenes/13_pop.js +269 -0
- package/engine/scenes/14_8bit.js +238 -0
- package/engine/scenes/15_raytrace.js +300 -0
- package/engine/scenes/16_2026.js +565 -0
- package/engine/scenes/17_ink.js +273 -0
- package/engine/scenes/18_klimt.js +227 -0
- package/engine/scenes/19_munch.js +153 -0
- package/engine/scenes/20_dunhuang.js +215 -0
- package/engine/scenes/21_kusama.js +124 -0
- package/engine/scenes/22_constructivism.js +205 -0
- package/engine/scenes/23_dali.js +221 -0
- package/engine/scenes/24_hopper.js +150 -0
- package/engine/scenes/25_ghibli.js +251 -0
- package/engine/scenes/26_vaporwave.js +191 -0
- package/engine/scenes/27_kirby.js +255 -0
- package/engine/scenes/28_monet.js +176 -0
- package/engine/scenes/29_seurat.js +104 -0
- package/engine/scenes/30_matisse.js +151 -0
- package/engine/scenes/31_haring.js +109 -0
- package/engine/scenes/32_rembrandt.js +217 -0
- package/engine/scenes/33_rubberhose.js +219 -0
- package/engine/scenes/34_shadowpuppet.js +195 -0
- package/engine/scenes/35_shinkai.js +197 -0
- package/engine/scenes/36_picasso_blue.js +123 -0
- package/engine/scenes/38_giotto.js +133 -0
- package/engine/scenes/39_piero.js +53 -0
- package/engine/scenes/40_raphael.js +96 -0
- package/engine/scenes/41_michelangelo.js +112 -0
- package/engine/scenes/42_guardi.js +70 -0
- package/engine/scenes/43_lorenzetti.js +145 -0
- package/engine/scenes/44_cortona.js +86 -0
- package/engine/scenes/45_renoir.js +86 -0
- package/engine/scenes/46_pissarro.js +82 -0
- package/engine/scenes/47_sisley.js +94 -0
- package/engine/scenes/48_gauguin.js +107 -0
- package/engine/scenes/49_chagall.js +60 -0
- package/engine/scenes/50_ma_yuan.js +131 -0
- package/engine/scenes/51_persian_miniature.js +149 -0
- package/engine/scenes/52_south_park.js +105 -0
- package/engine/scenes/53_pixar.js +60 -0
- package/engine/scenes/54_ghibli_lab.js +68 -0
- package/engine/scenes/55_dunhuang.js +161 -0
- package/engine/scenes/index.js +28 -0
- package/engine/spec_assets.py +76 -0
- package/engine/transitions.js +929 -0
- package/engine//346/227/266/344/273/243/344/275/234/350/200/205/350/247/204/350/214/203.md +49 -0
- package/lib/host.mjs +754 -0
- package/lib/render-bridge.mjs +543 -0
- package/lib/render-cli.mjs +98 -0
- package/lib/storyboard-lint.mjs +54 -0
- package/manifest.json +52 -0
- package/package.json +8 -4
- package/runtime/package.json +8 -0
- package/skills/biuart/SKILL.md +154 -0
- package/skills/biuart/references/01-/346/213/206/350/247/243.md +55 -0
- package/skills/biuart/references/02-/346/234/272/345/210/266.md +41 -0
- package/skills/biuart/references/03-/344/270/200/345/270/247/345/205/210/350/241/214/345/233/233/346/235/241/350/267/257/347/272/277.md +39 -0
- package/skills/biuart/references/04-/347/272/257/344/273/243/347/240/201/347/273/230/345/210/266.md +92 -0
- package/skills/biuart/references/05-/350/212/202/345/245/217/344/270/216/351/205/215/344/271/220.md +19 -0
- package/skills/biuart/references/06-/345/217/243/346/222/255/351/251/261/345/212/250/347/232/204/350/211/272/346/234/257/347/237/255/347/211/207.md +31 -0
- package/skills/biuart/references/07-/346/255/243/351/235/242/347/273/217/351/252/214.md +196 -0
- package/skills/biuart/references/08-/351/243/216/346/240/274/344/275/234/350/200/205/350/247/204/350/214/203.md +61 -0
- package/skills/biuart/references/09-/350/247/206/351/242/221/345/212/250/347/224/273/350/257/255/346/263/225.md +382 -0
- package/skills/biuart/references/10-/350/247/222/350/211/262.md +34 -0
- package/skills/biuart/references/11-/351/225/277/345/215/267/347/251/277/350/266/212/347/211/207.md +43 -0
- package/skills/biuart/references/12-/345/217/243/346/222/255/346/225/264/347/211/207/344/270/216/347/273/217/351/252/214/345/233/236/346/265/201.md +25 -0
- package/skills/biuart/references/13-/345/217/243/346/222/255/344/270/216/350/257/255/351/237/263/345/244/215/345/210/273.md +7 -0
- package/skills/biuart/references/15-/350/267/250/345/234/272/346/231/257/351/243/216/346/240/274/346/217/220/347/202/274.md +48 -0
- package/skills/biuart/references/16-/351/243/216/346/240/274/346/274/224/347/244/27295/345/210/206/345/215/217/350/256/256.md +103 -0
- package/skills/biuart/references/about-author.md +99 -0
- package/skills/biuart/references/capabilities.md +91 -0
- package/skills/biuart/references/compatibility.md +34 -0
- package/skills/biuart/references/images.md +97 -0
- package/skills/biuart/references/voice-model-review.md +18 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t1_3b1b.md +122 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t2_keynote_ui.md +117 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/t3_finance_chart.md +116 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y1_kurzgesagt.md +193 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y2_vox.md +195 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y3_whiteboard.md +190 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y4_storytime.md +166 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y5_kinetic_type.md +158 -0
- package/skills/biuart/references//345/212/250/347/224/273/350/257/255/346/263/225/y6_presenter_explainer.md +24 -0
- package/skills/biuart/references//345/217/243/346/222/255API.md +125 -0
- package/skills/biuart/references//350/211/262/346/235/277.md +38 -0
- package/skills/biuart/references//350/247/222/350/211/262/347/262/276/347/273/206/345/272/246.md +61 -0
- package/skills/biuart/references//351/225/234/345/244/264/350/241/250/346/250/241/346/235/277.md +80 -0
- package/skills/biuart/references//351/225/234/345/244/264/350/257/255/350/250/200.md +73 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/01_cave.md +46 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/02_egypt.md +64 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/03_greek.md +50 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/04_roman.md +99 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/05_gothic.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/06_renaissance.md +41 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/08_impressionism.md +34 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/09_postimp.md +17 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/10_nouveau.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/11_cubism.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/12_bauhaus.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/13_pop.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/14_8bit.md +27 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/15_raytrace.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/16_2026.md +55 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/17_ink.md +50 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/18_klimt.md +37 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/19_munch.md +42 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/20_dunhuang.md +49 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/21_kusama.md +32 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/22_constructivism.md +35 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/23_dali.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/24_hopper.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/25_ghibli.md +55 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/26_vaporwave.md +27 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/27_kirby.md +30 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/28_monet.md +39 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/29_seurat.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/30_matisse.md +26 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/31_haring.md +22 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/32_rembrandt.md +29 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/33_rubberhose.md +31 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/34_shadowpuppet.md +40 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/35_shinkai.md +34 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/36_picasso_blue.md +25 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/37_rick_morty.md +48 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/38_giotto.md +67 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/39_piero.md +59 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/40_raphael.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/41_michelangelo.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/42_guardi.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/43_lorenzetti.md +69 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/44_cortona.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/45_renoir.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/46_pissarro.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/47_sisley.md +67 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/48_gauguin.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/49_chagall.md +59 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/50_ma_yuan.md +68 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/51_persian_miniature.md +66 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/52_south_park.md +65 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/53_pixar.md +61 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/55_dunhuang.md +41 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/INDEX.md +89 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/350/275/254/345/234/272_/350/277/201/347/247/273/346/265/213/350/257/225.md +53 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/351/207/215/345/201/232/350/277/233/345/272/246.md +37 -0
- package/skills/biuart/references//351/243/216/346/240/274/351/205/215/346/226/271/_/351/237/263/350/275/250_/350/211/272/346/234/257/345/217/262/351/200/237/351/200/232.md +135 -0
- package/studio/app.js +380 -0
- package/studio/assert-panel-permit.mjs +67 -0
- package/studio/composer.css +465 -0
- package/studio/composer.js +480 -0
- package/studio/index.html +97 -0
- package/studio/optimize-prompt.mjs +84 -0
- package/studio/optimize-prompt.test.mjs +47 -0
- package/studio/recipes.mjs +87 -0
- package/studio/select-menu.js +450 -0
- package/studio/styles.css +71 -0
- package/studio/to-english-prompt.mjs +149 -0
- package/studio/to-english-prompt.test.mjs +72 -0
- package/README.md +0 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
window.SCENE_LIBS=['lib/three.min.js'];window.PUNCH=0;window.ERAS=[
|
|
2
|
+
{id:"38_giotto",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("乔托",50,1034);c.restore();}}},
|
|
3
|
+
{id:"39_piero",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("皮耶罗",50,1034);c.restore();}}},
|
|
4
|
+
{id:"40_raphael",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("拉斐尔",50,1034);c.restore();}}},
|
|
5
|
+
{id:"41_michelangelo",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("米开朗基罗",50,1034);c.restore();}}},
|
|
6
|
+
{id:"42_guardi",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("瓜尔迪",50,1034);c.restore();}}},
|
|
7
|
+
{id:"43_lorenzetti",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("洛伦采蒂",50,1034);c.restore();}}},
|
|
8
|
+
{id:"44_cortona",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("科尔托纳",50,1034);c.restore();}}},
|
|
9
|
+
{id:"45_renoir",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("雷诺阿",50,1034);c.restore();}}},
|
|
10
|
+
{id:"46_pissarro",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("毕沙罗",50,1034);c.restore();}}},
|
|
11
|
+
{id:"47_sisley",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("西斯莱",50,1034);c.restore();}}},
|
|
12
|
+
{id:"48_gauguin",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("高更",50,1034);c.restore();}}},
|
|
13
|
+
{id:"49_chagall",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("夏加尔",50,1034);c.restore();}}},
|
|
14
|
+
{id:"50_ma_yuan",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("马远",50,1034);c.restore();}}},
|
|
15
|
+
{id:"51_persian_miniature",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("波斯细密画",50,1034);c.restore();}}},
|
|
16
|
+
{id:"52_south_park",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("南方公园",50,1034);c.restore();}}},
|
|
17
|
+
{id:"54_ghibli_lab",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("吉卜力方向",50,1034);c.restore();}}},
|
|
18
|
+
{id:"53_pixar",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("皮克斯方向",50,1034);c.restore();}}},
|
|
19
|
+
{id:"55_dunhuang",dur:6,counter:{draw(c){c.save();c.font='25px sans-serif';c.textAlign='left';c.fillStyle='rgba(25,28,23,.75)';c.fillRect(34,1002,230,46);c.fillStyle='#fff9e9';c.fillText("敦煌壁画",50,1034);c.restore();}}}
|
|
20
|
+
];
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/engine/examples/assets//350/220/245/346/224/266/345/233/276_/347/253/226/345/261/217.png
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "t1_3b1b",
|
|
3
|
+
"duration": 10,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "ink",
|
|
8
|
+
"cues": [
|
|
9
|
+
{ "at": 0.0, "kind": "line", "text": "损失 L(θ)", "data": { "values": [9, 5.8, 3.4, 1.8, 1.0, 0.8, 1.0, 1.8, 3.4, 5.8, 9], "color": "BLUE_C" } },
|
|
10
|
+
{ "at": 1.8, "kind": "equation", "data": { "tokens": [
|
|
11
|
+
{ "s": "L", "it": true, "col": "BLUE_C" }, { "s": "(", "gap": 4 }, { "s": "θ", "it": true, "col": "YELLOW", "gap": 4 }, { "s": ")" } ] } },
|
|
12
|
+
{ "at": 3.4, "kind": "equation", "data": { "tokens": [
|
|
13
|
+
{ "s": "θ", "it": true, "col": "YELLOW" }, { "s": "←", "gap": 18 }, { "s": "θ", "it": true, "col": "YELLOW", "gap": 14 },
|
|
14
|
+
{ "s": "−", "gap": 14 }, { "s": "η", "it": true, "col": "GREEN_C", "gap": 8 }, { "s": "∇", "gap": 4 }, { "s": "L", "it": true, "col": "BLUE_C" } ] } },
|
|
15
|
+
{ "at": 5.0, "kind": "point", "text": "沿坡度反方向走一小步" },
|
|
16
|
+
{ "at": 6.4, "kind": "line", "text": "训练中的损失", "data": { "values": [9, 6.2, 4.4, 3.2, 2.4, 1.9, 1.55, 1.3, 1.15, 1.05, 1.0], "color": "TEAL_C" } },
|
|
17
|
+
{ "at": 8.2, "kind": "highlight", "data": { "target": "equation" } }
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "t2_keynote_ui",
|
|
3
|
+
"duration": 8,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "ink",
|
|
8
|
+
"cues": [
|
|
9
|
+
{ "at": 0.0, "kind": "card", "text": "for 循环累加", "sub": "一百万个整数", "image": "assets/终端_for循环求和.png" },
|
|
10
|
+
{ "at": 1.4, "kind": "highlight", "text": "318 毫秒", "data": { "rect": [0.292, 0.212, 0.115, 0.07] } },
|
|
11
|
+
{ "at": 3.2, "kind": "card", "text": "换成 sum()", "image": "assets/终端_sum求和.png" },
|
|
12
|
+
{ "at": 4.3, "kind": "highlight", "text": "20.9 毫秒", "data": { "rect": [0.292, 0.153, 0.128, 0.07] } },
|
|
13
|
+
{ "at": 6.4, "kind": "number", "text": "同一件事快了", "data": { "value": 15.2, "decimals": 1, "suffix": " 倍", "over": true } }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "t2_keynote_ui",
|
|
3
|
+
"duration": 10,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "navy",
|
|
8
|
+
"cues": [
|
|
9
|
+
{ "at": 0.0, "kind": "card", "text": "一份 JSON 出的图", "sub": "数据:英伟达 10-K 年报", "image": "assets/财经图表_横屏.png" },
|
|
10
|
+
{ "at": 1.8, "kind": "highlight", "data": { "rect": [0.648, 0.245, 0.104, 0.105] } },
|
|
11
|
+
{ "at": 4.0, "kind": "card", "text": "竖屏换一套排版", "sub": "同一份数据", "image": "assets/营收图_竖屏.png" },
|
|
12
|
+
{ "at": 6.6, "kind": "number", "text": "可换的动画语法", "data": { "value": 8, "suffix": " 种" } },
|
|
13
|
+
{ "at": 8.0, "kind": "card", "text": "时长精确到帧", "sub": "帧数 = 时长 × 帧率", "data": { "icon": "clock" } }
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "t3_finance_chart",
|
|
3
|
+
"duration": 7,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "paper",
|
|
8
|
+
"data": {
|
|
9
|
+
"title": "英伟达营收涨到 7.8 倍",
|
|
10
|
+
"unit": "年营收,十亿美元(2021–2025 财年)",
|
|
11
|
+
"source": "来源:英伟达 2021–2025 财年 10-K 年报(财年截至次年 1 月)",
|
|
12
|
+
"chart": "bar",
|
|
13
|
+
"decimals": 1,
|
|
14
|
+
"series": [
|
|
15
|
+
{ "label": "FY2021", "value": 16.68 },
|
|
16
|
+
{ "label": "FY2022", "value": 26.91 },
|
|
17
|
+
{ "label": "FY2023", "value": 26.97 },
|
|
18
|
+
{ "label": "FY2024", "value": 60.92 },
|
|
19
|
+
{ "label": "FY2025", "value": 130.50 }
|
|
20
|
+
],
|
|
21
|
+
"highlight": { "index": 4, "text": "7.8 倍", "sub": "130.5 ÷ 16.7" }
|
|
22
|
+
},
|
|
23
|
+
"cues": [
|
|
24
|
+
{ "at": 0.3, "kind": "bar", "data": { "index": [0, 1, 2] } },
|
|
25
|
+
{ "at": 1.7, "kind": "bar", "data": { "index": 3 } },
|
|
26
|
+
{ "at": 2.7, "kind": "bar", "data": { "index": 4 } },
|
|
27
|
+
{ "at": 4.4, "kind": "highlight" }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "y1_kurzgesagt",
|
|
3
|
+
"duration": 8,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "navy",
|
|
8
|
+
"data": { "center": "一滴海水" },
|
|
9
|
+
"cues": [
|
|
10
|
+
{ "at": 0.3, "kind": "point", "text": "浮游生物" },
|
|
11
|
+
{ "at": 1.3, "kind": "enter", "text": "一只硅藻", "data": { "index": 0 } },
|
|
12
|
+
{ "at": 3.3, "kind": "point", "text": "硅质外壳" },
|
|
13
|
+
{ "at": 4.3, "kind": "point", "text": "叶绿体" },
|
|
14
|
+
{ "at": 5.6, "kind": "highlight", "data": { "index": 1 } }
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "y2_vox",
|
|
3
|
+
"duration": 9,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "wood",
|
|
8
|
+
"cues": [
|
|
9
|
+
{ "at": 0.0, "kind": "image", "image": "assets/K线图_横屏.png", "text": "日 K 线·示意数据" },
|
|
10
|
+
{ "at": 1.8, "kind": "highlight", "data": { "rect": [0.74, 0.22, 0.22, 0.11] } },
|
|
11
|
+
{ "at": 4.2, "kind": "image", "image": "assets/营收图_竖屏.png", "text": "同一图表的竖屏版" },
|
|
12
|
+
{ "at": 6.6, "kind": "title", "text": "两张图都是代码画的" }
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "y3_whiteboard",
|
|
3
|
+
"duration": 10,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "chalk",
|
|
8
|
+
"cues": [
|
|
9
|
+
{ "at": 0.0, "kind": "draw", "text": "25 分钟", "data": { "icon": "clock" } },
|
|
10
|
+
{ "at": 1.5, "kind": "point", "text": "这段时间只做一件事" },
|
|
11
|
+
{ "at": 2.8, "kind": "draw", "text": "不切换", "data": { "icon": "target" } },
|
|
12
|
+
{ "at": 4.1, "kind": "point", "text": "铃响就休息 5 分钟" },
|
|
13
|
+
{ "at": 5.4, "kind": "draw", "text": "换口气", "data": { "icon": "bulb" } },
|
|
14
|
+
{ "at": 6.8, "kind": "point", "text": "四轮后长休一次" },
|
|
15
|
+
{ "at": 8.2, "kind": "highlight", "data": { "target": "draw", "index": 0 } }
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "y4_storytime",
|
|
3
|
+
"duration": 8.5,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "snow",
|
|
8
|
+
"data": {
|
|
9
|
+
"character": {
|
|
10
|
+
"frames": {
|
|
11
|
+
"rest": "../../../角色帧库/<你的角色>/rest.png",
|
|
12
|
+
"talk": "../../../角色帧库/<你的角色>/talk.png",
|
|
13
|
+
"point": "../../../角色帧库/<你的角色>/point.png",
|
|
14
|
+
"shrug": "../../../角色帧库/<你的角色>/shrug.png"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"cues": [
|
|
19
|
+
{
|
|
20
|
+
"at": 0.1,
|
|
21
|
+
"kind": "insert",
|
|
22
|
+
"text": "3000行",
|
|
23
|
+
"sub": "帮我做个网站",
|
|
24
|
+
"data": {
|
|
25
|
+
"hit": 1.6,
|
|
26
|
+
"count": 3000,
|
|
27
|
+
"unit": "行"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"at": 2.8,
|
|
32
|
+
"kind": "react"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"at": 4.1,
|
|
36
|
+
"kind": "point",
|
|
37
|
+
"text": "第一次让 AI 写代码,",
|
|
38
|
+
"sub": "这些……贴哪儿?",
|
|
39
|
+
"data": {
|
|
40
|
+
"pose": "point"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"at": 6.6,
|
|
45
|
+
"kind": "highlight",
|
|
46
|
+
"data": {
|
|
47
|
+
"mark": "?"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"_note": "y4 必须用你自己的角色帧库(AI 生帧,见 references/10-角色.md 与 角色精细度.md)。把 <你的角色> 换成你的帧库;没有生图能力就别用 y4。"
|
|
52
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"grammar": "y5_kinetic_type",
|
|
3
|
+
"duration": 7.5,
|
|
4
|
+
"fps": 30,
|
|
5
|
+
"width": 1920,
|
|
6
|
+
"height": 1080,
|
|
7
|
+
"theme": "poster",
|
|
8
|
+
"cues": [
|
|
9
|
+
{ "at": 0.7, "kind": "number", "text": "一句话换来的代码", "data": { "value": 3000, "suffix": " 行" } },
|
|
10
|
+
{ "at": 2.6, "kind": "point", "text": "补全", "sub": "以前它补一行", "data": { "label": "从前", "key": "一行" } },
|
|
11
|
+
{ "at": 4.3, "kind": "point", "text": "代理", "sub": "现在它做完整件事", "data": { "label": "现在", "key": "整件事" } },
|
|
12
|
+
{ "at": 5.6, "kind": "highlight", "data": { "word": "代理" } }
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html><head><meta charset="utf-8"><title>Art History Speedrun · 复刻</title>
|
|
3
|
+
<style>
|
|
4
|
+
html,body{margin:0;background:#111;overflow:hidden}
|
|
5
|
+
canvas{display:block;width:100vw;height:auto;max-width:1920px}
|
|
6
|
+
#ui{position:fixed;left:8px;bottom:8px;color:#ddd;font:12px monospace}
|
|
7
|
+
body.render #ui{display:none}
|
|
8
|
+
</style></head>
|
|
9
|
+
<body>
|
|
10
|
+
<canvas id="c" width="1920" height="1080"></canvas>
|
|
11
|
+
<div id="ui"><input id="scrub" type="range" min="0" max="60" step="0.0166667" value="0" style="width:600px"> <span id="tt"></span> <button id="play">play</button></div>
|
|
12
|
+
<script src="lib/fonts.js"></script>
|
|
13
|
+
<script src="lib/util.js"></script>
|
|
14
|
+
<script src="lib/paint.js"></script>
|
|
15
|
+
<script src="lib/brush.js"></script>
|
|
16
|
+
<script src="lib/render.js"></script>
|
|
17
|
+
<script src="lib/post.js"></script>
|
|
18
|
+
<script src="lib/rig.js"></script>
|
|
19
|
+
<script src="lib/rig_huashu.js"></script>
|
|
20
|
+
<script src="lib/kit.js"></script>
|
|
21
|
+
<script src="lib/medium.js"></script>
|
|
22
|
+
<!-- YouTube 解说语法库(references/09):动效时间、相机、图解形变、文字、图表、发布会界面、拼贴、卡通 -->
|
|
23
|
+
<script src="lib/motion.js"></script>
|
|
24
|
+
<script src="lib/camera.js"></script>
|
|
25
|
+
<script src="lib/diagram.js"></script>
|
|
26
|
+
<script src="lib/typo.js"></script>
|
|
27
|
+
<script src="lib/chart.js"></script>
|
|
28
|
+
<script src="lib/ui.js"></script>
|
|
29
|
+
<script src="lib/collage.js"></script>
|
|
30
|
+
<script src="lib/media.js"></script>
|
|
31
|
+
<script src="lib/toon.js"></script>
|
|
32
|
+
<script>
|
|
33
|
+
// 选片子:默认 eras.js;?film=<名> → eras_<名>.js(如 ?film=gallery = 35 种风格样片);?film=demos/<名> → demos/<名>/eras.js(8 种 YouTube 语法示范)。
|
|
34
|
+
// render.py / qa.py 用 --film 传。
|
|
35
|
+
(() => { const f = new URLSearchParams(location.search).get('film');
|
|
36
|
+
const src = f && /^demos\/[a-z0-9_]+$/.test(f) ? `${f}/eras.js` : f && /^[a-z0-9_]+$/.test(f) ? `eras_${f}.js` : 'eras.js';
|
|
37
|
+
document.write(`<script src="${src}"><\/script>`); })();
|
|
38
|
+
</script>
|
|
39
|
+
<script src="transitions.js"></script>
|
|
40
|
+
<script src="scenes/index.js"></script>
|
|
41
|
+
<script src="engine.js"></script>
|
|
42
|
+
</body></html>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright © 2010-2023 three.js authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// 笔与水:毛笔飞白、两头尖单笔、墨晕晕染、长弯流线笔、水彩洗染、厚涂鬃毛笔、剪刀折线。全部挂在 PAINT(P)上。
|
|
2
|
+
// 来源:迁移测试 A(水墨/蒙克)、B(吉卜力)、C(马蒂斯)、D(伦勃朗)。确定性:所有随机都走种子。
|
|
3
|
+
// P.brush(c, pts, opt) 毛笔:笔压起收+湿笔芯+逐根笔毛飞白,可按 reveal 写出(水墨、书法、白描衣纹)
|
|
4
|
+
// P.leaf(c, x, y, ang, L, w) 两头尖的单笔(竹叶、兰叶、鸟翅、虾尾)
|
|
5
|
+
// P.inkWash(c, key, grow, fn, o) 墨晕:形状先画到 scratch,再「外晕+本体」两遍模糊 multiply 到纸上,grow 0→1 是洇开
|
|
6
|
+
// P.flowSeeds / P.flowLines 长弯流线笔:种子沿随时间扭动的方向场积分成 200–300px 的长笔(蒙克,不是梵高的短笔)
|
|
7
|
+
// P.deform / P.watercolor 水彩洗染:中点位移变形多边形 × 多层低 α multiply + 每层淡描边=水痕边(吉卜力背景)
|
|
8
|
+
// P.rectPts / P.ellipsePts 洗染常用的多边形点列
|
|
9
|
+
// P.impasto(c, pts, w, col, hi) 厚涂鬃毛笔:一笔=若干平行细鬃(伦勃朗高光、梵高厚涂补笔)
|
|
10
|
+
// P.cut(pts, seed, step, amp) 剪刀折线:沿轮廓每 step px 取点+抖动、直线相连(马蒂斯剪纸、剪影、木刻)
|
|
11
|
+
(() => {
|
|
12
|
+
let W = 1920, H = 1080; U.onStage((w, h) => { W = w; H = h; }); // 画布尺寸跟 U.setStage 走(默认 1920×1080)
|
|
13
|
+
const P = window.PAINT;
|
|
14
|
+
const { clamp, lerp, rng, ss } = U;
|
|
15
|
+
|
|
16
|
+
// ---------- 毛笔 ----------
|
|
17
|
+
// pts 控制点(会 Catmull-Rom 加密再按 4px 等弧长重采样——不重采样的话飞白噪声频率随笔画长短变)
|
|
18
|
+
// w 最大宽;tone 墨色透明度(焦 .9/浓 .8/重 .6/淡 .35/清 .15);dry 0..1 飞白程度(越到笔尾越干);reveal 0..1 写出比例
|
|
19
|
+
// head/tail 起笔/收笔占比;bristles 笔毛数;col 墨色 [r,g,b];per 加密倍数
|
|
20
|
+
// 坑:笔毛必须每根一条连续 path(butt 头);按小段单独 stroke+round 头,接头处会叠出一节节深点,像竹节/麻绳。
|
|
21
|
+
P.brush = (c, pts, { w = 10, tone = 0.85, dry = 0.45, seed = 1, reveal = 1, bristles = 8, col = [16, 14, 12], head = 0.12, tail = 0.4, per = 5 } = {}) => {
|
|
22
|
+
if (reveal <= 0) return;
|
|
23
|
+
const D = KIT.resample(KIT.densify(pts, per), 4), n = D.length, m = Math.max(2, Math.ceil(n * clamp(reveal)));
|
|
24
|
+
const r = rng(seed * 7919);
|
|
25
|
+
const prof = q => ss(0, head, q) * (1 - 0.7 * ss(1 - tail, 1, q)) * (0.85 + 0.15 * P.noise(seed * 3.3, q * 6)) + 0.08;
|
|
26
|
+
c.save(); c.lineCap = 'butt'; c.lineJoin = 'round';
|
|
27
|
+
const N = [];
|
|
28
|
+
for (let i = 0; i < n; i++) { const A = D[Math.max(0, i - 1)], B = D[Math.min(n - 1, i + 1)]; let dx = B[0] - A[0], dy = B[1] - A[1]; const d = Math.hypot(dx, dy) || 1; N.push([-dy / d, dx / d]); }
|
|
29
|
+
const core = q => w * prof(q) * (1 - dry * 0.85 * Math.pow(q, 0.8));
|
|
30
|
+
// 湿的笔芯:整笔都有,越往后越细越淡(墨在用完)
|
|
31
|
+
c.fillStyle = `rgba(${col[0]},${col[1]},${col[2]},${tone * 0.72})`; c.fill(KIT.ribbon(D.slice(0, m), (q, i) => core(i / (n - 1))));
|
|
32
|
+
// 笔毛:每根一条连续线,按噪声断开(飞白=笔毛之间露出的纸),越到笔尾断得越多
|
|
33
|
+
for (let k = 0; k < bristles; k++) {
|
|
34
|
+
const off = (k / (bristles - 1) - 0.5) * 0.95, bw = w / bristles * (0.9 + r() * 0.9), ph = r() * 50;
|
|
35
|
+
c.strokeStyle = `rgba(${col[0]},${col[1]},${col[2]},${tone * (0.45 + r() * 0.35)})`; c.lineWidth = Math.max(0.7, bw);
|
|
36
|
+
c.beginPath(); let on = false;
|
|
37
|
+
for (let i = 0; i < m; i++) {
|
|
38
|
+
const q = i / (n - 1), dryness = dry * Math.pow(q, 1.2);
|
|
39
|
+
const vis = P.noise(k * 1.9 + ph, i * 0.09) * 0.5 + 0.5 > dryness * 0.95 + 0.05;
|
|
40
|
+
const o = off * w * prof(q), x = D[i][0] + N[i][0] * o, y = D[i][1] + N[i][1] * o;
|
|
41
|
+
if (vis) { on ? c.lineTo(x, y) : c.moveTo(x, y); on = true; } else on = false;
|
|
42
|
+
}
|
|
43
|
+
c.stroke();
|
|
44
|
+
}
|
|
45
|
+
c.restore();
|
|
46
|
+
};
|
|
47
|
+
// 两头尖的单笔(个字竹叶、兰叶描、鸟翅):沿 ang 方向长 L,最宽 wmax,微弯
|
|
48
|
+
P.leaf = (c, x, y, ang, L, wmax, tone = 0.88, col = [16, 14, 12]) => {
|
|
49
|
+
if (!Array.isArray(col)) col = [16, 14, 12];
|
|
50
|
+
const pts = []; for (let i = 0; i <= 10; i++) { const q = i / 10, bend = Math.sin(q * Math.PI) * 0.08 * L; pts.push([x + Math.cos(ang) * L * q - Math.sin(ang) * bend, y + Math.sin(ang) * L * q + Math.cos(ang) * bend]); }
|
|
51
|
+
c.fillStyle = `rgba(${col[0]},${col[1]},${col[2]},${tone})`; c.fill(KIT.ribbon(pts, q => wmax * Math.pow(Math.sin(Math.PI * Math.min(1, q * 1.1)), 0.7) + 0.6));
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// ---------- 墨晕 / 晕染层 ----------
|
|
55
|
+
// fn(g) 在 scratch 上画形状(实色即可);grow 0..1 控制洇开:外晕 blur 随 grow 变宽,本体 blur 随 grow 收紧。
|
|
56
|
+
// halo 外晕模糊半径、haloA 外晕透明度、blur 本体模糊、alpha 整体透明度。返回 scratch(可再拿来做留白挖洞)。
|
|
57
|
+
// 坑:multiply 是透明的,背后的墨线会透过晕染(窗台线透过猫耳)。先在剪影里补一层纸色(clip 后 drawImage 纸)再上晕染=「先留出这块地方」。
|
|
58
|
+
P.inkWash = (c, key, grow, fn, { blur = 2, halo = 10, haloA = 0.22, alpha = 1 } = {}) => {
|
|
59
|
+
const S = P.scratch('inkw_' + key), g = S.getContext('2d'); g.reset(); fn(g);
|
|
60
|
+
c.save(); c.globalCompositeOperation = 'multiply';
|
|
61
|
+
if (grow > 0) {
|
|
62
|
+
c.globalAlpha = haloA * alpha * grow; c.filter = `blur(${(halo * (0.4 + grow)).toFixed(2)}px)`; c.drawImage(S, 0, 0);
|
|
63
|
+
c.globalAlpha = alpha * ss(0, 0.6, grow); c.filter = `blur(${(blur * (1.6 - grow * 0.6)).toFixed(2)}px)`; c.drawImage(S, 0, 0);
|
|
64
|
+
}
|
|
65
|
+
c.filter = 'none'; c.restore();
|
|
66
|
+
return S;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// ---------- 长弯流线笔(蒙克《呐喊》式表现主义) ----------
|
|
70
|
+
// 种子:cell 抖动网格,每个种子带两个随机数 [x, y, r1, r2]
|
|
71
|
+
P.flowSeeds = (cell = 24, seed = 5) => { const r = rng(seed), o = []; for (let y = -10; y < H + 10; y += cell) for (let x = -10; x < W + 10; x += cell) o.push([x + (r() - .5) * cell, y + (r() - .5) * cell, r(), r()]); return o; };
|
|
72
|
+
// 每个种子:region(x,y,t) 判区 → 取该区参数 params[reg] = [steps, step, width, alpha] → 沿 angle(x,y,t,reg) 积分;越出本区就停(区域边界干净)。
|
|
73
|
+
// color(reg, sx, sy, r1, t) 返回 [r,g,b]。不描边、半透明叠色——蒙克是薄涂长笔;照搬梵高的深色描边会变成一节节毛毛虫短笔。
|
|
74
|
+
// 底下先铺同色系平涂,笔缝里露出的是同色而不是黑。长度:steps 26–42、step 6–8,一根笔走 200–300px。
|
|
75
|
+
P.flowLines = (c, seeds, { t = 0, region, angle, color, params, extraSteps = 8 }) => {
|
|
76
|
+
c.lineCap = 'round'; c.lineJoin = 'round';
|
|
77
|
+
for (const [sx, sy, r1, r2] of seeds) {
|
|
78
|
+
const reg = region(sx, sy, t); const pr = params[reg]; if (!pr) continue; const [steps, step, width, alpha] = pr;
|
|
79
|
+
const col = color(reg, sx, sy, r1, t);
|
|
80
|
+
let x = sx, y = sy; c.beginPath(); c.moveTo(x, y);
|
|
81
|
+
const n = steps + ((r2 * extraSteps) | 0);
|
|
82
|
+
for (let i = 0; i < n; i++) { const a = angle(x, y, t, reg); x += Math.cos(a) * step; y += Math.sin(a) * step; if (region(x, y, t) !== reg) break; c.lineTo(x, y); }
|
|
83
|
+
c.strokeStyle = P.rgb(col, alpha); c.lineWidth = width * (0.7 + r2 * 0.6); c.stroke();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// ---------- 水彩洗染(吉卜力式背景美术) ----------
|
|
88
|
+
// 中点位移:每轮在每条边中点沿法向推一个近似高斯量(3 个均匀数相加),幅度与边长成比例,每轮 amp×0.6
|
|
89
|
+
P.deform = (pts, depth, amp, r) => {
|
|
90
|
+
let out = pts;
|
|
91
|
+
for (let d = 0; d < depth; d++) {
|
|
92
|
+
const n = [];
|
|
93
|
+
for (let i = 0; i < out.length; i++) {
|
|
94
|
+
const a = out[i], b = out[(i + 1) % out.length], len = Math.hypot(b[0] - a[0], b[1] - a[1]);
|
|
95
|
+
const g = (r() + r() + r() - 1.5) * amp * Math.min(1, len / 80), nx = -(b[1] - a[1]) / (len || 1), ny = (b[0] - a[0]) / (len || 1);
|
|
96
|
+
n.push(a, [(a[0] + b[0]) / 2 + nx * g, (a[1] + b[1]) / 2 + ny * g]);
|
|
97
|
+
}
|
|
98
|
+
out = n; amp *= 0.6;
|
|
99
|
+
}
|
|
100
|
+
return out;
|
|
101
|
+
};
|
|
102
|
+
const fillPts = (g, pts) => { g.beginPath(); pts.forEach((q, i) => i ? g.lineTo(q[0], q[1]) : g.moveTo(q[0], q[1])); g.closePath(); };
|
|
103
|
+
// 一次洗染:基形 deform 3 轮;每层再 deform 2 轮、低 α 填(multiply = 透明颜料叠色)、α=edge 描 1.6px 同色边(颜料在边缘沉积 = 水痕边)。
|
|
104
|
+
// fill 可传渐变;不透明的白(窗框、云、桌布)用 blend:'source-over'、alpha .9。
|
|
105
|
+
// 常用:大墙 layers5 α.4 amp12;色晕 layers3 α.045 amp40;木板 layers3 α.5 amp3 edge.14。
|
|
106
|
+
// 坑:暗部用大幅变形多边形(amp 60),别用矩形拼——矩形接缝处会出硬边。色晕 α 别超 .05×3 层,否则房间像发霉的羊皮纸。
|
|
107
|
+
P.watercolor = (g, pts, color, { layers = 7, alpha = 0.13, amp = 10, seed = 1, edge = 0.1, blend = 'multiply', fill } = {}) => {
|
|
108
|
+
const r = rng(seed * 7919 + 13), base = P.deform(pts, 3, amp, r);
|
|
109
|
+
g.save(); g.globalCompositeOperation = blend; g.lineJoin = 'round';
|
|
110
|
+
for (let k = 0; k < layers; k++) {
|
|
111
|
+
const q = P.deform(base, 2, amp * 0.55, r);
|
|
112
|
+
fillPts(g, q); g.globalAlpha = alpha; g.fillStyle = fill || color; g.fill();
|
|
113
|
+
if (edge) { g.globalAlpha = edge; g.strokeStyle = color; g.lineWidth = 1.6; g.stroke(); }
|
|
114
|
+
}
|
|
115
|
+
g.restore();
|
|
116
|
+
};
|
|
117
|
+
P.rectPts = (x, y, w, h) => [[x, y], [x + w, y], [x + w, y + h], [x, y + h]];
|
|
118
|
+
P.ellipsePts = (cx, cy, rx, ry, n = 18) => Array.from({ length: n }, (_, i) => [cx + Math.cos(i / n * Math.PI * 2) * rx, cy + Math.sin(i / n * Math.PI * 2) * ry]);
|
|
119
|
+
|
|
120
|
+
// ---------- 厚涂鬃毛笔 ----------
|
|
121
|
+
// 一笔 = round(w/1.3) 条平行细鬃(亮度各自 ±17 抖、两端随机缩 0–25%)+下侧一条淡投影+上侧零星亮点 → 读成「被刷开的一坨厚颜料」。
|
|
122
|
+
// 只用在受光处(金发、领口、瓷器、珍珠、白毛)。坑:画成「暗影+主笔+亮脊」三条整齐的线会读成白色贴纸/创可贴。
|
|
123
|
+
P.impasto = (c, pts, w, col, hi) => {
|
|
124
|
+
const base = col.startsWith('#') ? P.hex(col) : [240, 230, 210];
|
|
125
|
+
const A = pts[0], B = pts[pts.length - 1], ang = Math.atan2(B[1] - A[1], B[0] - A[0]), nx = -Math.sin(ang), ny = Math.cos(ang);
|
|
126
|
+
const r = rng((A[0] * 13 + A[1] * 7) | 0), nb = Math.max(3, Math.round(w / 1.3));
|
|
127
|
+
c.save(); c.lineCap = 'round';
|
|
128
|
+
c.strokeStyle = 'rgba(40,18,6,.28)'; c.lineWidth = w * 0.9; c.beginPath(); pts.forEach((p, i) => i ? c.lineTo(p[0] + nx * w * 0.45 + 1, p[1] + ny * w * 0.45 + 1.5) : c.moveTo(p[0] + nx * w * 0.45 + 1, p[1] + ny * w * 0.45 + 1.5)); c.stroke();
|
|
129
|
+
for (let k = 0; k < nb; k++) {
|
|
130
|
+
const o = (k / (nb - 1) - 0.5) * w, s0 = r() * 0.25, s1 = 1 - r() * 0.25, sh = (r() - 0.5) * 34 + (k < nb / 2 ? 14 : -10);
|
|
131
|
+
c.strokeStyle = P.rgb([base[0] + sh, base[1] + sh, base[2] + sh * 0.8], 0.55 + r() * 0.4); c.lineWidth = 1.4 + r() * 1.2; c.beginPath();
|
|
132
|
+
const n = pts.length - 1; for (let i = 0; i <= 8; i++) { const q = lerp(s0, s1, i / 8), j = Math.min(n - 1, Math.floor(q * n)), f = q * n - j, x = lerp(pts[j][0], pts[j + 1][0], f) + nx * o, y = lerp(pts[j][1], pts[j + 1][1], f) + ny * o; i ? c.lineTo(x, y) : c.moveTo(x, y); }
|
|
133
|
+
c.stroke();
|
|
134
|
+
}
|
|
135
|
+
c.fillStyle = hi || 'rgba(255,250,232,.7)'; for (let k = 0; k < 2 + w / 3; k++) { const q = r(), x = lerp(A[0], B[0], q) - nx * w * 0.3, y = lerp(A[1], B[1], q) - ny * w * 0.3; c.beginPath(); c.arc(x, y, 0.9 + r(), 0, Math.PI * 2); c.fill(); }
|
|
136
|
+
c.restore();
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// ---------- 剪刀折线 ----------
|
|
140
|
+
// 把一圈(闭合)点列按 step 重采样,每点加 ±amp 种子抖动,直线相连 → 手剪纸的边。RIG 部件可用 path.pts 喂进来重剪。
|
|
141
|
+
P.cut = (pts, seed, step = 18, amp = 2.5) => {
|
|
142
|
+
const r = rng(seed), out = [];
|
|
143
|
+
for (let i = 0; i < pts.length; i++) {
|
|
144
|
+
const a = pts[i], b = pts[(i + 1) % pts.length], L = Math.hypot(b[0] - a[0], b[1] - a[1]), n = Math.max(1, Math.round(L / step));
|
|
145
|
+
for (let k = 0; k < n; k++) { const q = k / n; out.push([lerp(a[0], b[0], q) + (r() - 0.5) * amp * 2, lerp(a[1], b[1], q) + (r() - 0.5) * amp * 2]); }
|
|
146
|
+
}
|
|
147
|
+
return U.poly(out);
|
|
148
|
+
};
|
|
149
|
+
})();
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// 世界相机 CAM:解说片不是「一段段画+转场」,而是「一张连续的世界画布+一台相机」。
|
|
2
|
+
// 铁律:相机只由全片时间(或本段时间)算出来,场景每帧按相机矢量重画——缩放转场永远清楚,不会把 1920 的位图放大 20 倍糊掉;
|
|
3
|
+
// 引擎在转场窗口里会把上一段继续按 t 画进 A 缓冲,所以「上一镜的相机继续推」天然成立(live 推进)。
|
|
4
|
+
// cam = { x, y, z, r }:世界点 (x,y) 落在画面中心,缩放 z(>1 推近),绕中心旋转 r(弧度)。缺省 x=960,y=540,z=1,r=0。
|
|
5
|
+
(() => {
|
|
6
|
+
let W = 1920, H = 1080; U.onStage((w, h) => { W = w; H = h; }); // 画布尺寸跟 U.setStage 走(默认 1920×1080)
|
|
7
|
+
const { clamp, lerp } = U;
|
|
8
|
+
const CAM = window.CAM = {};
|
|
9
|
+
const n = cam => ({ x: cam.x ?? W / 2, y: cam.y ?? H / 2, z: cam.z ?? 1, r: cam.r || 0 });
|
|
10
|
+
|
|
11
|
+
// 把相机变换作用到 c 上(不 save/restore,调用方负责)
|
|
12
|
+
CAM.apply = (c, cam) => { const k = n(cam); c.translate(W / 2, H / 2); if (k.r) c.rotate(k.r); c.scale(k.z, k.z); c.translate(-k.x, -k.y); };
|
|
13
|
+
// 在相机下画 fn(c),自动 save/restore
|
|
14
|
+
CAM.with = (c, cam, fn) => { c.save(); CAM.apply(c, cam); fn(c); c.restore(); };
|
|
15
|
+
// 世界 → 屏幕 / 屏幕 → 世界
|
|
16
|
+
CAM.toScreen = (cam, x, y) => { const k = n(cam); let dx = (x - k.x) * k.z, dy = (y - k.y) * k.z; if (k.r) { const cs = Math.cos(k.r), sn = Math.sin(k.r); [dx, dy] = [dx * cs - dy * sn, dx * sn + dy * cs]; } return [W / 2 + dx, H / 2 + dy]; };
|
|
17
|
+
CAM.toWorld = (cam, sx, sy) => { const k = n(cam); let dx = sx - W / 2, dy = sy - H / 2; if (k.r) { const cs = Math.cos(-k.r), sn = Math.sin(-k.r); [dx, dy] = [dx * cs - dy * sn, dx * sn + dy * cs]; } return [k.x + dx / k.z, k.y + dy / k.z]; };
|
|
18
|
+
|
|
19
|
+
// ---------- 缩放 ----------
|
|
20
|
+
// 对数插值:z0→z1 每帧放大同样的倍数,观众感到「匀速穿越尺度」;线性插值会前慢后猛。所有推拉缩放都用它。
|
|
21
|
+
CAM.zlerp = (z0, z1, e) => z0 * Math.pow(z1 / z0, e);
|
|
22
|
+
// 「从一个半径 r 的圆形开口穿进去,开口要在转场结束前盖满屏」需要的最小放大倍数 = 开口中心到最远屏幕角的距离 / r。
|
|
23
|
+
// 开口在画面中心时 ≈ 1101/r(卡片里写的「放大倍数 ≥ 1100/半径」)。小了,最后一帧开口没盖满会跳。
|
|
24
|
+
CAM.coverZoom = (r, cx = W / 2, cy = H / 2) => Math.max(Math.hypot(cx, cy), Math.hypot(W - cx, cy), Math.hypot(cx, H - cy), Math.hypot(W - cx, H - cy)) / r;
|
|
25
|
+
// 让世界点 (wx,wy) 在缩放 z 下出现在屏幕 (sx,sy):返回相机。推近某物时让它平滑移到画面中心就靠它。
|
|
26
|
+
CAM.anchor = (wx, wy, z, sx, sy) => ({ x: wx - (sx - W / 2) / z, y: wy - (sy - H / 2) / z, z });
|
|
27
|
+
// 推进某个世界点:从 base 相机出发,缩放按对数插值到 Z(进度 e);该点在屏幕上从原位置移向画面中心(进度 k,默认 = e;k=0 = 绕它原地推)。
|
|
28
|
+
// 用于「钻进镜头」(y1)、「推满照片再硬切」(y2)、「推进最新数据点」(t3,k=0)。
|
|
29
|
+
CAM.pushTo = (base, wx, wy, Z, e, k = e, to = [W / 2, H / 2]) => {
|
|
30
|
+
const s0 = CAM.toScreen(base, wx, wy), z = CAM.zlerp(n(base).z, Z, e);
|
|
31
|
+
return CAM.anchor(wx, wy, z, lerp(s0[0], to[0], k), lerp(s0[1], to[1], k));
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// ---------- 关键帧 ----------
|
|
35
|
+
// keys = [{t, x, y, z, r, ease}];ease 作用在「从上一键到这一键」,默认 cubicInOut;z 用对数插值。
|
|
36
|
+
// 沿路径平移(Vox 桌面、白板上的平移/甩镜)就是一串关键帧:平滑移动用 sineInOut,远跳用 cubicInOut+运动模糊,沿线追用 MO.longTail。
|
|
37
|
+
CAM.at = (keys, t) => {
|
|
38
|
+
if (t <= keys[0].t) return { ...keys[0] };
|
|
39
|
+
for (let i = 1; i < keys.length; i++) {
|
|
40
|
+
const a = keys[i - 1], b = keys[i];
|
|
41
|
+
if (t <= b.t) { const e = (b.ease || MO.cubicInOut)(MO.seg(t, a.t, b.t));
|
|
42
|
+
return { x: lerp(a.x, b.x, e), y: lerp(a.y, b.y, e), z: CAM.zlerp(a.z, b.z, e), r: lerp(a.r || 0, b.r || 0, e), v: e }; }
|
|
43
|
+
}
|
|
44
|
+
return { ...keys[keys.length - 1] };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// ---------- 镜头动作表(解说片用它;什么时候用哪一种见 references/镜头语言.md) ----------
|
|
48
|
+
// 默认是过渡类动作:缓推 push、找下一件 glide、拉远 pull(0.6–1.5s,sineInOut / 长尾);重音类:快推 punch、快移 pan、砸入 slam,
|
|
49
|
+
// 留给揭晓、数字、反转。时长在 MO.PULSE。一支片子里推近要有来有回:推进去之后用 pull、glide 或硬切换开,别一镜接一镜只往里推。
|
|
50
|
+
// CAM.track(base, events, t) → cam:base 是起始相机 {x, y, z};events 是按时间排的镜头动作,相机只由 t 算出来(确定性,可跳帧)。
|
|
51
|
+
// 每个动作从「上一个动作结束时的相机」出发,到 at + dur 落定;两个动作挨太近(上一个没走完下一个就开始)时,下一个从上一个此刻的位置接着走。
|
|
52
|
+
// {at, kind: 'push', k?, x?, y?, dur?} 缓推(不写 kind 就是它):z 乘以 (1+k)(k 默认 0.2),0.9s sineInOut;给 x, y 就同时把这个世界点移到画面中心。
|
|
53
|
+
// {at, kind: 'pull', k?, x?, y?, z?, dur?} 拉远:z 乘以 (1+k)(k 默认 -1/6,正好抵消一次默认缓推;回全貌最稳是写 z: base.z),1.1s 长尾。推进去之后回到全貌、段落收束用它。
|
|
54
|
+
// {at, kind: 'glide', x, y, dur?} 找下一件:缩放不变,画面中心平滑移到世界点 (x, y),0.7s sineInOut。同一面墙上从一件移到下一件。
|
|
55
|
+
// {at, kind: 'to', x?, y?, z?, dur?, ease?} 推到指定相机(推近截图上的一块:z 用 MD.zoomFor 算);默认 0.9s sineInOut,写 dur: MO.PULSE.punch 就是重音。
|
|
56
|
+
// {at, kind: 'punch', k?, x?, y?, dur?} 快推(重音):0.28s cubicInOut,k 默认 0.25(0.18–0.32)。k 可以写负数(快拉)。
|
|
57
|
+
// {at, kind: 'pan', x, y, dur?} 快移(重音):同倍率 0.30s。视线突然转移、喜剧节奏用。
|
|
58
|
+
// {at, kind: 'slam', dur?, from?} 整帧砸入:z 额外乘 MO.slamK(1.55→0.94→1.0,0.17s)。大字、数字、盖章落下那一帧用。
|
|
59
|
+
// {at, kind: 'shake', amp?, dur?} 震镜:dur(默认 4 帧 ≈ 0.13s)内上下抖 amp 像素(默认 14),和砸入、盖章同帧用,一支片子别超过两次。
|
|
60
|
+
// {at, kind: 'cut', x?, y?, z?} 硬切到这台相机(不过渡)。换景别不一定要运镜,跳近一档就是硬切。
|
|
61
|
+
// 返回的 cam 带 moving: true/false(这一刻是否在运动),给运动模糊、标签显隐用。
|
|
62
|
+
CAM.track = (base, events, t) => {
|
|
63
|
+
let cam = { x: base.x ?? W / 2, y: base.y ?? H / 2, z: base.z ?? 1 }, zMul = 1, dy = 0, moving = false;
|
|
64
|
+
const evs = [...events].sort((a, b) => a.at - b.at);
|
|
65
|
+
for (const e of evs) {
|
|
66
|
+
if (t < e.at) break;
|
|
67
|
+
const P = MO.PULSE, kind = e.kind || 'push';
|
|
68
|
+
if (kind === 'cut') { cam = { x: e.x ?? cam.x, y: e.y ?? cam.y, z: e.z ?? cam.z }; continue; }
|
|
69
|
+
if (kind === 'slam') { const d = e.dur || P.slam, k = (t - e.at) / d; if (k < 1) { zMul *= MO.slamK(k, e.from); moving = true; } continue; }
|
|
70
|
+
if (kind === 'shake') { const d = e.dur || 4 / 30, k = (t - e.at) / d; if (k < 1) { dy += (e.amp ?? 14) * Math.sin(k * Math.PI * 4) * (1 - k) / cam.z; moving = true; } continue; }
|
|
71
|
+
const D = { pan: P.pan, punch: P.punch, glide: P.glide, pull: P.pull, push: P.push, to: P.push }[kind] ?? P.push;
|
|
72
|
+
const E = kind === 'punch' || kind === 'pan' || (e.dur && e.dur <= 0.35) ? MO.cubicInOut : kind === 'pull' ? MO.longTail : MO.sineInOut; // 写了重音时长的 to 也用快推的曲线
|
|
73
|
+
const d = e.dur || D, p = (e.ease || E)(clamp((t - e.at) / d));
|
|
74
|
+
let to;
|
|
75
|
+
if (kind === 'pan' || kind === 'glide') to = { x: e.x ?? cam.x, y: e.y ?? cam.y, z: cam.z };
|
|
76
|
+
else if (kind === 'to') to = { x: e.x ?? cam.x, y: e.y ?? cam.y, z: e.z ?? cam.z };
|
|
77
|
+
else if (kind === 'pull') to = { x: e.x ?? cam.x, y: e.y ?? cam.y, z: e.z ?? cam.z * (1 + (e.k ?? -1 / 6)) }; // 默认 ×5/6,正好抵消一次默认缓推(×1.2)
|
|
78
|
+
else to = { x: e.x ?? cam.x, y: e.y ?? cam.y, z: cam.z * (1 + (e.k ?? (kind === 'push' ? 0.2 : P.k))) };
|
|
79
|
+
if (p < 1) moving = true;
|
|
80
|
+
cam = { x: lerp(cam.x, to.x, p), y: lerp(cam.y, to.y, p), z: CAM.zlerp(cam.z, to.z, p) };
|
|
81
|
+
}
|
|
82
|
+
return { x: cam.x, y: cam.y + dy, z: cam.z * zMul, moving };
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// ---------- 视差 ----------
|
|
86
|
+
// d=1 是主体平面,d<1 远、d>1 近。远层位移按 d 线性、缩放按 z^d:深推时远景几乎不动,这就是景深感(Kurzgesagt 5 层视差)。
|
|
87
|
+
CAM.layer = (c, cam, d, fn) => { const k = n(cam); c.save(); CAM.apply(c, { x: lerp(W / 2, k.x, d), y: lerp(H / 2, k.y, d), z: Math.pow(k.z, d) }); fn(c); c.restore(); };
|
|
88
|
+
|
|
89
|
+
// ---------- 运动 ----------
|
|
90
|
+
// 相机在屏幕上的瞬时速度(像素/帧,60fps):camFn(t) → cam。给 motionBlur 用。
|
|
91
|
+
CAM.velocity = (camFn, t, dt = 1 / 60) => { const a = camFn(t), b = camFn(t - dt); const z = n(a).z; return [(n(a).x - n(b).x) * z, (n(a).y - n(b).y) * z]; };
|
|
92
|
+
// 动态模糊:沿速度方向把整帧叠 n 次(快摇/甩镜用;速度 <1.5px 自动退化成一次绘制)。模糊长度应短于相机位移(PremiumBeat)。
|
|
93
|
+
CAM.motionBlur = (c, src, vx, vy, k = 7) => {
|
|
94
|
+
const sp = Math.hypot(vx, vy); if (sp < 1.5) { c.drawImage(src, 0, 0); return; }
|
|
95
|
+
c.save(); for (let i = 0; i < k; i++) { const q = i / (k - 1) - 0.5; c.globalAlpha = i === 0 ? 1 : 1 / (i + 1); c.drawImage(src, -vx * q, -vy * q); } c.restore();
|
|
96
|
+
};
|
|
97
|
+
// 手持感微漂:两路不同周期的正弦(连续时间,不闪),返回 [dx, dy] 像素。只给艺术风格画面和纯氛围镜头;解说镜头停住时就停住,不加微漂
|
|
98
|
+
CAM.drift = (t, amp = 6, seed = 0) => [amp * Math.sin(t * 0.9 + seed) + amp * 0.4 * Math.sin(t * 2.3 + seed * 2), amp * 0.7 * Math.sin(t * 1.1 + seed * 3)];
|
|
99
|
+
})();
|