dsh-drawai 0.4.1 → 0.4.3

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.
Files changed (365) hide show
  1. package/README.md +96 -253
  2. package/lib/client.js +28 -7
  3. package/lib/index.js +474 -97
  4. package/lib/motion/asset-pack.js +109 -50
  5. package/lib/motion/assets.js +291 -291
  6. package/lib/motion/demo-assets-lock.js +10 -0
  7. package/lib/motion/mgstyles/vendor/README.md +28 -0
  8. package/lib/motion/mgstyles/vendor/modules/d3/LICENSE +13 -0
  9. package/lib/motion/mgstyles/vendor/modules/d3/dist/d3.min.js +2 -0
  10. package/lib/motion/mgstyles/vendor/modules/opentype.js/LICENSE +20 -0
  11. package/lib/motion/mgstyles/vendor/modules/opentype.js/dist/opentype.mjs +14460 -0
  12. package/lib/motion/mgstyles/vendor/modules/simplex-noise/LICENSE +21 -0
  13. package/lib/motion/mgstyles/vendor/modules/simplex-noise/dist/esm/simplex-noise.js +466 -0
  14. package/lib/motion/mgstyles/vendor/modules/topojson-client/LICENSE +13 -0
  15. package/lib/motion/mgstyles/vendor/modules/topojson-client/dist/topojson-client.min.js +2 -0
  16. package/lib/motion/preview.js +10 -3
  17. package/lib/motion/render.js +19 -1
  18. package/lib/motion/shotcraft/upstream/SKILL.md +286 -286
  19. package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -54
  20. package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -200
  21. package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -45
  22. package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -20
  23. package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -65
  24. package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -151
  25. package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -129
  26. package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -75
  27. package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -40
  28. package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -11
  29. package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -10
  30. package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -49
  31. package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -210
  32. package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -423
  33. package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -170
  34. package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -157
  35. package/lib/motion/shotcraft/upstream/demos/README.md +120 -120
  36. package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -112
  37. package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -647
  38. package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -316
  39. package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -82
  40. package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -115
  41. package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -243
  42. package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +388 -388
  43. package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -250
  44. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -305
  45. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -246
  46. package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -390
  47. package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -138
  48. package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -542
  49. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -315
  50. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -299
  51. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -173
  52. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -348
  53. package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -366
  54. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -279
  55. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -184
  56. package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -390
  57. package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -155
  58. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -303
  59. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -290
  60. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -278
  61. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -307
  62. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -215
  63. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -299
  64. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -232
  65. package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -290
  66. package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -273
  67. package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -167
  68. package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -536
  69. package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -164
  70. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -175
  71. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -197
  72. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -241
  73. package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -279
  74. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -230
  75. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -345
  76. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -275
  77. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -229
  78. package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -312
  79. package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -222
  80. package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -295
  81. package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -329
  82. package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -315
  83. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -264
  84. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -260
  85. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -263
  86. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -123
  87. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -187
  88. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -175
  89. package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -305
  90. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -350
  91. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -352
  92. package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -218
  93. package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -297
  94. package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -157
  95. package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -218
  96. package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -202
  97. package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -265
  98. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -457
  99. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -446
  100. package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -249
  101. package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -278
  102. package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -332
  103. package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -358
  104. package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -201
  105. package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -200
  106. package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -208
  107. package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -341
  108. package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -389
  109. package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -293
  110. package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -183
  111. package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -245
  112. package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -222
  113. package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -223
  114. package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -217
  115. package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -343
  116. package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -357
  117. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -187
  118. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -333
  119. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -274
  120. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -270
  121. package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -430
  122. package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -252
  123. package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -106
  124. package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -288
  125. package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -362
  126. package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -168
  127. package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -310
  128. package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -261
  129. package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -459
  130. package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -294
  131. package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -161
  132. package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -248
  133. package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -359
  134. package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -227
  135. package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -162
  136. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -248
  137. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -186
  138. package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -355
  139. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -272
  140. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -262
  141. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -217
  142. package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -285
  143. package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -205
  144. package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -178
  145. package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -147
  146. package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -143
  147. package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -134
  148. package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -217
  149. package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -198
  150. package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -221
  151. package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -312
  152. package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -261
  153. package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -121
  154. package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -153
  155. package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -179
  156. package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -140
  157. package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -309
  158. package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -191
  159. package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -292
  160. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -135
  161. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -124
  162. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -255
  163. package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -173
  164. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -225
  165. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -141
  166. package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -137
  167. package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -147
  168. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -409
  169. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -280
  170. package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -271
  171. package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -385
  172. package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -312
  173. package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -303
  174. package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -77
  175. package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -311
  176. package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -307
  177. package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -349
  178. package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -255
  179. package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -244
  180. package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -217
  181. package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -652
  182. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -153
  183. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -238
  184. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -324
  185. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -354
  186. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -101
  187. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -129
  188. package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -297
  189. package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -57
  190. package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -155
  191. package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -175
  192. package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -153
  193. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -146
  194. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -226
  195. package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -1
  196. package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -193
  197. package/lib/motion/shotcraft/upstream/references/final-review.md +121 -121
  198. package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -199
  199. package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -183
  200. package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -257
  201. package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -382
  202. package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -111
  203. package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -50
  204. package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -95
  205. package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -41
  206. package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -52
  207. package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -39
  208. package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -39
  209. package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -57
  210. package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -51
  211. package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -46
  212. package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -52
  213. package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -43
  214. package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -42
  215. package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -48
  216. package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -52
  217. package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -45
  218. package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -46
  219. package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -44
  220. package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -63
  221. package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -54
  222. package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -58
  223. package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -35
  224. package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -53
  225. package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -42
  226. package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -50
  227. package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -46
  228. package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -56
  229. package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -49
  230. package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -50
  231. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -53
  232. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -53
  233. package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -55
  234. package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -52
  235. package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -60
  236. package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -57
  237. package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -51
  238. package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -41
  239. package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -53
  240. package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -60
  241. package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -55
  242. package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -57
  243. package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -47
  244. package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -37
  245. package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -54
  246. package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -36
  247. package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -56
  248. package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -56
  249. package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -40
  250. package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -60
  251. package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -57
  252. package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -73
  253. package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -87
  254. package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -55
  255. package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -50
  256. package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -59
  257. package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -38
  258. package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -38
  259. package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -59
  260. package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -39
  261. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -61
  262. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -52
  263. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -50
  264. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -66
  265. package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -43
  266. package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -38
  267. package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -38
  268. package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -56
  269. package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -44
  270. package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -38
  271. package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -63
  272. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -57
  273. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -63
  274. package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -58
  275. package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -45
  276. package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -55
  277. package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -49
  278. package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -42
  279. package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -42
  280. package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -45
  281. package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -48
  282. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -55
  283. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -43
  284. package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -41
  285. package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -42
  286. package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -59
  287. package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -55
  288. package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -65
  289. package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -42
  290. package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -64
  291. package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -64
  292. package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -54
  293. package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -91
  294. package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -51
  295. package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -66
  296. package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -38
  297. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -66
  298. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -58
  299. package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -61
  300. package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -64
  301. package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -45
  302. package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -41
  303. package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -51
  304. package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -42
  305. package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -63
  306. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -57
  307. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -75
  308. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -59
  309. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -67
  310. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -60
  311. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -66
  312. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -40
  313. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -45
  314. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -62
  315. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -55
  316. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -37
  317. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -55
  318. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -50
  319. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -43
  320. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -55
  321. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -51
  322. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -51
  323. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -56
  324. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -49
  325. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -57
  326. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -36
  327. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -64
  328. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -47
  329. package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -170
  330. package/lib/motion/shotcraft/upstream/references/workbench.md +157 -157
  331. package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -103
  332. package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -44
  333. package/lib/motion/shotcraft/upstream/template/package.json +20 -20
  334. package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -6
  335. package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -17
  336. package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -65
  337. package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -48
  338. package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -24
  339. package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -192
  340. package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -111
  341. package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -150
  342. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -158
  343. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -468
  344. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -552
  345. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -411
  346. package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -200
  347. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -324
  348. package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +388 -388
  349. package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -4
  350. package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -7
  351. package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -68
  352. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -1
  353. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -24
  354. package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -74
  355. package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -91
  356. package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -213
  357. package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -15
  358. package/lib/motion/style-frames.js +47 -12
  359. package/lib/motion-project.js +22 -3
  360. package/lib/motion-render-worker.js +31 -9
  361. package/lib/routing/router.js +12 -1
  362. package/lib/style-kernel.js +16 -6
  363. package/lib/video-trace-pool.js +128 -128
  364. package/package.json +1 -1
  365. package/LICENSE +0 -4175
@@ -1,358 +1,358 @@
1
- /**
2
- * DatavizLandscapeOpen — 暗场支流线束地景开场
3
- * 配方卡: references/shots/opening/dataviz-landscape-open.md
4
- *
5
- * 第二轮重设计(石墨 · 荧光黄绿 · 真透视地景):
6
- * - look = lime。不再是平面 SVG 横移:整片线束画在一张真透视的地平面上(针孔投影,相机高 220、焦距 1100),
7
- * 一条荧光黄绿主干从镜头脚下蜿蜒奔向画面右 1/3 处的消失点(汇点),11 条灰绿支流从两侧画外切向汇入。
8
- * 景深 / 视差 / 雾全部由投影深度算出来:近处线条又宽又虚(按深度分进模糊层)、中景锐利、远处变细隐入地平线。
9
- * - 相机低空沿河道前飞 + 横向缓移(dolly + truck),整段 bezier 减速:开场即在飞、收尾缓停接字标,不急刹。
10
- * - 中景支流上钉 6 枚 video-shotcraft 镜头标签(立杆图钉 + 等宽镜头号胶囊 + 运镜名),随透视逐渐变大、向两侧散开;
11
- * 隐喻:每条支流是一个镜头,汇成主干这一支成片;
12
- * 生长完成后沿线有亮脉冲低速流向汇点(数据在流)。
13
- * - 收尾:消失点亮起一团黄绿光(交棒亮部),天空里落一行大标题「Every shot, / one film.」(眉题 video-shotcraft 字标小写),
14
- * 结尾帧是完整的海报。
15
- *
16
- * 时间表(30fps,共 180f):
17
- * 0–10 从深场浮出(地平线光带首帧就在)
18
- * 0–36 主干由近及远 draw-on(out-cubic),笔尖光点
19
- * 8–70 支流错峰生长(每条 4–6f,近处先),笔尖光点
20
- * 44–104 标签非均匀错峰立起(图钉过冲 → 立杆 → 胶囊去模糊),104f 后不再新增
21
- * 60–180 流动脉冲;相机全程前飞,140f 后明显减速
22
- * 104–140 标题:眉题 + 两行逐词升起;汇点光 120f 起升亮
23
- * 140–180 hold:相机缓停、脉冲流动,海报落定
24
- */
25
- import React from 'react';
26
- import {AbsoluteFill, useCurrentFrame} from 'remotion';
27
- import {EASE, FONT, bezier, mix, ramp} from '../../_fixtures/Polish';
28
- import {Dust, LOOKS, Stage, TextReveal, alpha, type} from '../../_fixtures/Look';
29
- import {BRAND} from '../../_fixtures/Brand';
30
-
31
- const DUR = 180; // 6s @30fps
32
- export const DATAVIZ_LANDSCAPE_OPEN_DURATION = DUR;
33
-
34
- const L = LOOKS.lime;
35
- const HY = 420; // 地平线(屏幕 y)
36
- const F = 1100; // 焦距
37
- const CAM_H = 220; // 相机离地高度
38
- const SLOPE = 0.29; // 主干总体走向(dX/dZ)→ 消失点 x = 960 + F*SLOPE ≈ 1279(右 1/3)
39
- const VPX = 960 + F * SLOPE;
40
-
41
- // ───────────── 相机 ─────────────
42
- const camPath = bezier(0.3, 0.3, 0.55, 1); // 匀速起步、尾段减速缓停
43
- const CAM_DIST = 950;
44
- const camAt = (frame: number) => {
45
- const t = Math.min(1, Math.max(0, frame / (DUR - 1)));
46
- const z = CAM_DIST * camPath(t);
47
- const lat = mix(-140, 110, EASE.smooth(t)); // 横向缓移:近远景相对错动 = 视差
48
- return {z, x: SLOPE * z + lat};
49
- };
50
-
51
- type P3 = {x: number; z: number};
52
- const project = (p: P3, cam: {x: number; z: number}) => {
53
- const zr = p.z - cam.z;
54
- return {sx: 960 + (F * (p.x - cam.x)) / zr, sy: HY + (F * CAM_H) / zr, zr};
55
- };
56
-
57
- // ───────────── 世界几何(地平面 X/Z)─────────────
58
- const trunkX = (z: number) => SLOPE * z - 160 + 150 * Math.sin(z / 950);
59
- const trunkDX = (z: number) => SLOPE + (150 / 950) * Math.cos(z / 950);
60
-
61
- // 主干:-300 → 14000,近密远疏采样
62
- const TRUNK: P3[] = Array.from({length: 261}, (_, i) => {
63
- const z = -300 + Math.pow(i / 260, 1.7) * 14300;
64
- return {x: trunkX(z), z};
65
- });
66
-
67
- // 三次贝塞尔按弧长等距重采样
68
- const bez = (a: P3, b: P3, c: P3, d: P3, t: number): P3 => {
69
- const u = 1 - t;
70
- return {
71
- x: u * u * u * a.x + 3 * u * u * t * b.x + 3 * u * t * t * c.x + t * t * t * d.x,
72
- z: u * u * u * a.z + 3 * u * u * t * b.z + 3 * u * t * t * c.z + t * t * t * d.z,
73
- };
74
- };
75
- const resample = (at: (t: number) => P3, n: number) => {
76
- const raw = Array.from({length: 241}, (_, i) => at(i / 240));
77
- const cum = [0];
78
- for (let i = 1; i < raw.length; i++) cum.push(cum[i - 1] + Math.hypot(raw[i].x - raw[i - 1].x, raw[i].z - raw[i - 1].z));
79
- const total = cum[cum.length - 1];
80
- const out: P3[] = [];
81
- let j = 1;
82
- for (let k = 0; k <= n; k++) {
83
- const target = (k / n) * total;
84
- while (j < raw.length - 1 && cum[j] < target) j++;
85
- const f = (target - cum[j - 1]) / Math.max(1e-6, cum[j] - cum[j - 1]);
86
- out.push({x: mix(raw[j - 1].x, raw[j].x, f), z: mix(raw[j - 1].z, raw[j].z, f)});
87
- }
88
- return out;
89
- };
90
-
91
- // 支流:起点在两侧画外,切向汇入主干(汇入点切线 = 主干切线)
92
- type TribSpec = {side: number; z0: number; off: number; zm: number; lm: number; grow: number; w: number};
93
- const TRIB_SPECS: TribSpec[] = [
94
- {side: -1, z0: -260, off: 700, zm: 1500, lm: 520, grow: 8, w: 5},
95
- {side: 1, z0: -120, off: 900, zm: 2100, lm: 640, grow: 11, w: 5},
96
- {side: -1, z0: 500, off: 1500, zm: 2700, lm: 760, grow: 16, w: 4.4},
97
- {side: 1, z0: 800, off: 1800, zm: 3300, lm: 820, grow: 20, w: 4.4},
98
- {side: -1, z0: 1400, off: 2300, zm: 3900, lm: 900, grow: 25, w: 4.2},
99
- {side: 1, z0: 1700, off: 2500, zm: 4600, lm: 980, grow: 29, w: 4.2},
100
- {side: -1, z0: 2500, off: 2900, zm: 5300, lm: 1050, grow: 34, w: 4.2},
101
- {side: 1, z0: 3100, off: 3200, zm: 6100, lm: 1150, grow: 38, w: 4.2},
102
- {side: -1, z0: 4100, off: 3600, zm: 7100, lm: 1250, grow: 43, w: 4.2},
103
- {side: 1, z0: 5000, off: 3900, zm: 8200, lm: 1350, grow: 47, w: 4.2},
104
- {side: 1, z0: -420, off: 260, zm: 980, lm: 380, grow: 4, w: 6}, // 贴着镜头右下方掠过的近景支流(大虚焦)
105
- ];
106
- const TRIBS = TRIB_SPECS.map((s) => {
107
- const end: P3 = {x: trunkX(s.zm), z: s.zm};
108
- const dx = trunkDX(s.zm);
109
- const dl = Math.hypot(dx, 1);
110
- const p2: P3 = {x: end.x - (dx / dl) * s.lm, z: end.z - (1 / dl) * s.lm};
111
- const p0: P3 = {x: trunkX(s.z0) + s.side * s.off, z: s.z0};
112
- const p1: P3 = {x: p0.x + (end.x - p0.x) * 0.12, z: p0.z + (end.z - p0.z) * 0.5};
113
- return {...s, pts: resample((t) => bez(p0, p1, p2, end, t), 90)};
114
- });
115
-
116
- // ───────────── 线段渲染:按深度分层(近虚 / 中实 / 远雾)─────────────
117
- const smooth01 = (a: number, b: number, x: number) => {
118
- const t = Math.min(1, Math.max(0, (x - a) / (b - a)));
119
- return t * t * (3 - 2 * t);
120
- };
121
- type Seg = {x1: number; y1: number; x2: number; y2: number; w: number; o: number; c: string};
122
-
123
- const emitLine = (
124
- pts: P3[], g: number, cam: {x: number; z: number}, opts: {w: number; color: string; base: number; ramp?: boolean; pulse: (u: number) => number},
125
- sharp: Seg[], near: Seg[],
126
- ) => {
127
- const n = pts.length - 1;
128
- const reach = g * n;
129
- const kMax = Math.min(n, Math.ceil(reach));
130
- for (let k = 0; k < kMax; k++) {
131
- const a = pts[k];
132
- const b0 = pts[k + 1];
133
- const f = Math.min(1, reach - k);
134
- const b = f < 1 ? {x: mix(a.x, b0.x, f), z: mix(a.z, b0.z, f)} : b0;
135
- if (a.z - cam.z < 70 || b.z - cam.z < 70) continue;
136
- const pa = project(a, cam);
137
- const pb = project(b, cam);
138
- if ((pa.sx < -200 && pb.sx < -200) || (pa.sx > 2120 && pb.sx > 2120) || (pa.sy > 1300 && pb.sy > 1300)) continue;
139
- const zr = (pa.zr + pb.zr) / 2;
140
- const u = (k + 0.5 * f) / n;
141
- const fog = 1 - smooth01(2600, 11000, zr); // 远处雾化
142
- const lift = opts.ramp ? 0.3 + 0.7 * Math.pow(u, 0.8) : 1; // 支流:源头淡、汇入处亮
143
- // 脉冲只在中远景显形:近处一段线在屏幕上很长,逐段明暗会读成台阶
144
- const pv = opts.pulse(u);
145
- const o = opts.base * fog * lift * mix(1, pv, smooth01(500, 1400, zr));
146
- if (o < 0.01) continue;
147
- const w = Math.max(0.9, Math.min(46, (opts.w * F) / zr));
148
- const nearW = 1 - smooth01(420, 1050, zr); // 近景权重 → 进模糊层
149
- const seg = {x1: pa.sx, y1: pa.sy, x2: pb.sx, y2: pb.sy, w, c: opts.color};
150
- if (nearW < 0.98) sharp.push({...seg, o: o * (1 - nearW)});
151
- if (nearW > 0.02) near.push({...seg, w: w * 1.3, o: o * nearW * 0.7});
152
- }
153
- // 笔尖
154
- if (g > 0 && g < 1) {
155
- const k = Math.min(n - 1, Math.floor(reach));
156
- const f = reach - k;
157
- const tip = {x: mix(pts[k].x, pts[k + 1].x, f), z: mix(pts[k].z, pts[k + 1].z, f)};
158
- if (tip.z - cam.z > 70) return project(tip, cam);
159
- }
160
- return null;
161
- };
162
-
163
- // ───────────── 标签(中景,video-shotcraft 的镜头号 + 运镜名;字数与原 issue 标签相当,投影位置不变)─────────────
164
- // 位置按投影逐帧核过:起止两端都错开(不叠、不压汇点、不出画),近处一枚随前飞明显变大
165
- type LabelSpec = {trib: number; u: number; id: string; note: string; appear: number};
166
- const LABELS: LabelSpec[] = [
167
- {trib: 2, u: 0.6, id: 'SHOT-01', note: 'dolly in', appear: 44},
168
- {trib: 1, u: 0.75, id: 'SHOT-02', note: 'crash zoom', appear: 53},
169
- {trib: 3, u: 0.6, id: 'SHOT-03', note: 'whip pan', appear: 62},
170
- {trib: 6, u: 0.3, id: 'SHOT-04', note: 'beat cut', appear: 73},
171
- {trib: 7, u: 0.45, id: 'SHOT-05', note: 'tilt up', appear: 84},
172
- {trib: 8, u: 0.45, id: 'SHOT-06', note: 'lockup', appear: 96},
173
- ];
174
- const LABEL_PTS = LABELS.map((l) => {
175
- const pts = TRIBS[l.trib].pts;
176
- return {p: pts[Math.round(l.u * (pts.length - 1))]};
177
- });
178
-
179
- const Label: React.FC<{spec: LabelSpec; at: P3; frame: number; cam: {x: number; z: number}}> = ({spec, at, frame, cam}) => {
180
- const pr = project(at, cam);
181
- if (pr.zr < 200) return null;
182
- const k = Math.min(1.7, Math.max(0.7, 1500 / pr.zr)); // 透视缩放(近大远小),钳住可读区间
183
- const fog = 1 - smooth01(3600, 8000, pr.zr);
184
- const pin = ramp(frame, spec.appear, 10, EASE.overshoot);
185
- const pinOp = ramp(frame, spec.appear, 4, EASE.out);
186
- const stem = ramp(frame, spec.appear + 2, 12, EASE.snappy);
187
- const tag = ramp(frame, spec.appear + 6, 14, EASE.snappy);
188
- // 立杆世界高度远低于相机高度 → 标签落在地平线以下、按深度上下错开(杆高≈相机高时所有标签都投影到地平线上挤成一排)
189
- const stemH = 44 * k;
190
- const fs = 25 * k;
191
- return (
192
- <div style={{position: 'absolute', left: 0, top: 0, opacity: fog}}>
193
- {/* 图钉(落在线上) */}
194
- <div style={{
195
- position: 'absolute', left: pr.sx - 6 * k, top: pr.sy - 6 * k, width: 12 * k, height: 12 * k, borderRadius: 2.5 * k,
196
- background: L.accent, opacity: pinOp, transform: `scale(${pin})`,
197
- boxShadow: `0 0 0 ${3 * k}px ${alpha(L.bg[2], 0.9)}, 0 0 ${18 * k}px ${alpha(L.accent, 0.7)}`,
198
- }} />
199
- {/* 立杆 */}
200
- <div style={{
201
- position: 'absolute', left: pr.sx - 0.75, top: pr.sy - 8 * k - stemH * stem, width: 1.5, height: stemH * stem,
202
- background: `linear-gradient(0deg, ${alpha(L.accent, 0.7)}, ${alpha(L.ink, 0.25)})`,
203
- }} />
204
- {/* ID 胶囊 */}
205
- <div style={{
206
- position: 'absolute', left: pr.sx - 2 * k, top: pr.sy - 8 * k - stemH - 46 * k + (1 - tag) * 14 * k,
207
- height: 46 * k, padding: `0 ${14 * k}px 0 ${12 * k}px`, borderRadius: 10 * k, boxSizing: 'border-box',
208
- display: 'flex', alignItems: 'center', gap: 10 * k, whiteSpace: 'nowrap',
209
- background: alpha('#141711', 0.82), border: `1px solid ${alpha(L.ink, 0.12)}`,
210
- boxShadow: `inset 0 1px 0 ${alpha('#ffffff', 0.06)}, 0 ${10 * k}px ${28 * k}px ${alpha('#000000', 0.5)}`,
211
- opacity: tag, filter: tag < 0.98 ? `blur(${((1 - tag) * 6).toFixed(2)}px)` : undefined,
212
- }}>
213
- <div style={{width: 7 * k, height: 7 * k, borderRadius: 4 * k, background: L.accent}} />
214
- <span style={{fontFamily: FONT.mono, fontSize: fs, fontWeight: 600, color: L.ink, letterSpacing: '0.02em'}}>{spec.id}</span>
215
- <span style={{fontFamily: FONT.sans, fontSize: fs * 0.82, fontWeight: 500, color: L.ink3}}>{spec.note}</span>
216
- </div>
217
- </div>
218
- );
219
- };
220
-
221
- // ───────────── 组件 ─────────────
222
- export const DatavizLandscapeOpen: React.FC = () => {
223
- const frame = useCurrentFrame();
224
- const cam = camAt(frame);
225
- const fadeUp = ramp(frame, 0, 12, EASE.out);
226
-
227
- const sharp: Seg[] = [];
228
- const near: Seg[] = [];
229
- const tips: {sx: number; sy: number; zr: number; trunk: boolean}[] = [];
230
-
231
- // 流动脉冲:生长完后沿线流向汇点的亮脉冲(窄峰,低速)
232
- const flowIn = (end: number) => ramp(frame, end, 24, EASE.smooth);
233
- const pulseFn = (end: number, n: number, speed: number, seed: number) => {
234
- const on = flowIn(end);
235
- return (u: number) => {
236
- const ph = u * n - frame * speed + seed;
237
- const c = Math.cos(ph * Math.PI * 2);
238
- return 0.7 + on * 0.55 * Math.pow(Math.max(0, c), 4);
239
- };
240
- };
241
-
242
- const trunkG = ramp(frame, 0, 36, EASE.out);
243
- TRIBS.forEach((t, i) => {
244
- const g = ramp(frame, t.grow, 34, EASE.out);
245
- const tip = emitLine(t.pts, g, cam, {w: t.w, color: L.ink2, base: 0.62, ramp: true, pulse: pulseFn(t.grow + 34, 2.2, 0.018, i * 0.37)}, sharp, near);
246
- if (tip) tips.push({...tip, trunk: false});
247
- });
248
- const tTip = emitLine(TRUNK, trunkG, cam, {w: 11, color: L.accent, base: 0.95, pulse: pulseFn(36, 4, 0.022, 0)}, sharp, near);
249
- if (tTip) tips.push({...tTip, trunk: true});
250
- const trunkSegs = sharp.filter((s) => s.c === L.accent);
251
-
252
- // 地面点阵:与世界锁定的网格,前飞时从远处涌来
253
- const dots: {x: number; y: number; r: number; o: number}[] = [];
254
- const STEP = 420;
255
- const zStart = Math.ceil((cam.z + 300) / STEP) * STEP;
256
- for (let z = zStart; z < cam.z + 9000; z += STEP) {
257
- for (let x = Math.floor((cam.x - 5200) / STEP) * STEP; x < cam.x + 5200; x += STEP) {
258
- const pr = project({x, z}, cam);
259
- if (pr.sx < -20 || pr.sx > 1940 || pr.sy > 1100) continue;
260
- const o = 0.28 * (1 - smooth01(2000, 9000, pr.zr)) * smooth01(300, 900, pr.zr);
261
- if (o < 0.01) continue;
262
- dots.push({x: pr.sx, y: pr.sy, r: Math.max(0.8, Math.min(3.2, 2400 / pr.zr)), o});
263
- }
264
- }
265
-
266
- const handoff = ramp(frame, 118, 50, EASE.swift);
267
- const lineRender = (s: Seg, i: number) => (
268
- <line key={i} x1={s.x1} y1={s.y1} x2={s.x2} y2={s.y2} stroke={s.c} strokeWidth={s.w} strokeOpacity={s.o} strokeLinecap="butt" />
269
- );
270
-
271
- return (
272
- <AbsoluteFill style={{background: L.bg[2], overflow: 'hidden'}}>
273
- <AbsoluteFill style={{opacity: 0.35 + 0.65 * fadeUp}}>
274
- <Stage look={L} keyLight={{x: VPX / 1920, y: HY / 1080}} fill={{x: 0.12, y: 0.95}} horizon={HY / 1080} intensity={0.55} grain={0.1} vignette={0.6}>
275
- {/* 天空里的极淡浮尘 */}
276
- <div style={{position: 'absolute', left: 0, right: 0, top: 0, height: HY, overflow: 'hidden'}}>
277
- <Dust look={L} count={26} seed={7} drift={0.12} opacity={0.35} color={L.ink2} />
278
- </div>
279
- {/* 地面:地平线以下略亮一档的冷灰绿,向近处压暗 */}
280
- <div style={{
281
- position: 'absolute', left: 0, right: 0, top: HY, bottom: 0,
282
- background: `linear-gradient(180deg, ${alpha('#2a3122', 0.55)} 0%, ${alpha('#141811', 0.3)} 30%, ${alpha('#050604', 0)} 100%)`,
283
- }} />
284
- {/* 地平线发丝线 */}
285
- <div style={{
286
- position: 'absolute', left: 0, right: 0, top: HY - 0.5, height: 1,
287
- background: `linear-gradient(90deg, ${alpha(L.ink, 0)} 0%, ${alpha(L.ink, 0.16)} 40%, ${alpha(L.accent, 0.35)} 66%, ${alpha(L.ink, 0.12)} 85%, ${alpha(L.ink, 0)} 100%)`,
288
- }} />
289
- </Stage>
290
-
291
- <svg width={1920} height={1080} style={{position: 'absolute', inset: 0}}>
292
- <defs>
293
- <filter id="dv-near" x="-20%" y="-20%" width="140%" height="140%"><feGaussianBlur stdDeviation="11" /></filter>
294
- <filter id="dv-glow" x="-10%" y="-10%" width="120%" height="120%"><feGaussianBlur stdDeviation="7" /></filter>
295
- <radialGradient id="dv-tip">
296
- <stop offset="0" stopColor="#ffffff" stopOpacity={0.9} />
297
- <stop offset="0.3" stopColor={L.accent} stopOpacity={0.35} />
298
- <stop offset="1" stopColor={L.accent} stopOpacity={0} />
299
- </radialGradient>
300
- </defs>
301
- {dots.map((d, i) => <circle key={i} cx={d.x} cy={d.y} r={d.r} fill={L.ink2} fillOpacity={d.o} />)}
302
- {/* 主干泛光(只给主角) */}
303
- <g filter="url(#dv-glow)" opacity={0.75}>
304
- {trunkSegs.map((s, i) => <line key={i} x1={s.x1} y1={s.y1} x2={s.x2} y2={s.y2} stroke={L.accent} strokeWidth={s.w * 3} strokeOpacity={s.o * 0.45} strokeLinecap="butt" />)}
305
- </g>
306
- {sharp.map(lineRender)}
307
- {tips.map((t, i) => {
308
- const r = Math.max(3, Math.min(18, (t.trunk ? 7000 : 4200) / t.zr));
309
- return (
310
- <g key={i}>
311
- <circle cx={t.sx} cy={t.sy} r={r * 5} fill="url(#dv-tip)" />
312
- <circle cx={t.sx} cy={t.sy} r={r * 0.6} fill="#ffffff" />
313
- </g>
314
- );
315
- })}
316
- </svg>
317
-
318
- {/* 汇点交棒亮部:消失点一团黄绿光,收尾升亮 */}
319
- <div style={{
320
- position: 'absolute', left: VPX - 520, top: HY - 260, width: 1040, height: 520, pointerEvents: 'none',
321
- background: `radial-gradient(50% 50% at 50% 50%, ${alpha('#f4ffd6', 0.55)} 0%, ${alpha(L.accent, 0.22)} 22%, ${alpha(L.accent, 0)} 70%)`,
322
- opacity: 0.25 + 0.75 * handoff, mixBlendMode: 'screen',
323
- }} />
324
- <div style={{
325
- position: 'absolute', left: VPX - 4, top: HY - 4, width: 8, height: 8, borderRadius: 4, background: '#f6ffe0',
326
- boxShadow: `0 0 18px 6px ${alpha(L.accent, 0.6)}`, opacity: 0.4 + 0.6 * handoff,
327
- }} />
328
-
329
- {/* 远的先画、近的后画:近处胶囊正确遮住远处图钉 */}
330
- {LABELS.map((l, i) => ({l, p: LABEL_PTS[i].p}))
331
- .sort((a, b) => b.p.z - a.p.z)
332
- .map(({l, p}) => (frame >= l.appear ? <Label key={l.id} spec={l} at={p} frame={frame} cam={cam} /> : null))}
333
-
334
- {/* 近景大虚焦层(在标签之上:前景掠过) */}
335
- <svg width={1920} height={1080} style={{position: 'absolute', inset: 0}}>
336
- <g filter="url(#dv-near)">{near.map(lineRender)}</g>
337
- </svg>
338
- </AbsoluteFill>
339
-
340
- {/* 标题:天空左上,收尾落字 */}
341
- <div style={{position: 'absolute', left: 120, top: 128}}>
342
- {/* 眉题:品牌名按字标规范全小写(不走大写科技字标) */}
343
- <div style={{
344
- fontFamily: FONT.mono, fontSize: 28, fontWeight: 600, color: L.accent, letterSpacing: '0.12em',
345
- opacity: ramp(frame, 104, 14, EASE.out), transform: `translateY(${(1 - ramp(frame, 104, 18, EASE.snappy)) * 12}px)`,
346
- }}>
347
- {BRAND.name} · shot recipes
348
- </div>
349
- <div style={{...type(108, 650), color: L.ink, marginTop: 26}}>
350
- <TextReveal text="Every shot," by="word" variant="rise" start={110} each={20} gap={5} />
351
- </div>
352
- <div style={{...type(108, 650), color: L.accent, marginTop: 4}}>
353
- <TextReveal text="one film." by="word" variant="rise" start={121} each={20} gap={5} />
354
- </div>
355
- </div>
356
- </AbsoluteFill>
357
- );
358
- };
1
+ /**
2
+ * DatavizLandscapeOpen — 暗场支流线束地景开场
3
+ * 配方卡: references/shots/opening/dataviz-landscape-open.md
4
+ *
5
+ * 第二轮重设计(石墨 · 荧光黄绿 · 真透视地景):
6
+ * - look = lime。不再是平面 SVG 横移:整片线束画在一张真透视的地平面上(针孔投影,相机高 220、焦距 1100),
7
+ * 一条荧光黄绿主干从镜头脚下蜿蜒奔向画面右 1/3 处的消失点(汇点),11 条灰绿支流从两侧画外切向汇入。
8
+ * 景深 / 视差 / 雾全部由投影深度算出来:近处线条又宽又虚(按深度分进模糊层)、中景锐利、远处变细隐入地平线。
9
+ * - 相机低空沿河道前飞 + 横向缓移(dolly + truck),整段 bezier 减速:开场即在飞、收尾缓停接字标,不急刹。
10
+ * - 中景支流上钉 6 枚 video-shotcraft 镜头标签(立杆图钉 + 等宽镜头号胶囊 + 运镜名),随透视逐渐变大、向两侧散开;
11
+ * 隐喻:每条支流是一个镜头,汇成主干这一支成片;
12
+ * 生长完成后沿线有亮脉冲低速流向汇点(数据在流)。
13
+ * - 收尾:消失点亮起一团黄绿光(交棒亮部),天空里落一行大标题「Every shot, / one film.」(眉题 video-shotcraft 字标小写),
14
+ * 结尾帧是完整的海报。
15
+ *
16
+ * 时间表(30fps,共 180f):
17
+ * 0–10 从深场浮出(地平线光带首帧就在)
18
+ * 0–36 主干由近及远 draw-on(out-cubic),笔尖光点
19
+ * 8–70 支流错峰生长(每条 4–6f,近处先),笔尖光点
20
+ * 44–104 标签非均匀错峰立起(图钉过冲 → 立杆 → 胶囊去模糊),104f 后不再新增
21
+ * 60–180 流动脉冲;相机全程前飞,140f 后明显减速
22
+ * 104–140 标题:眉题 + 两行逐词升起;汇点光 120f 起升亮
23
+ * 140–180 hold:相机缓停、脉冲流动,海报落定
24
+ */
25
+ import React from 'react';
26
+ import {AbsoluteFill, useCurrentFrame} from 'remotion';
27
+ import {EASE, FONT, bezier, mix, ramp} from '../../_fixtures/Polish';
28
+ import {Dust, LOOKS, Stage, TextReveal, alpha, type} from '../../_fixtures/Look';
29
+ import {BRAND} from '../../_fixtures/Brand';
30
+
31
+ const DUR = 180; // 6s @30fps
32
+ export const DATAVIZ_LANDSCAPE_OPEN_DURATION = DUR;
33
+
34
+ const L = LOOKS.lime;
35
+ const HY = 420; // 地平线(屏幕 y)
36
+ const F = 1100; // 焦距
37
+ const CAM_H = 220; // 相机离地高度
38
+ const SLOPE = 0.29; // 主干总体走向(dX/dZ)→ 消失点 x = 960 + F*SLOPE ≈ 1279(右 1/3)
39
+ const VPX = 960 + F * SLOPE;
40
+
41
+ // ───────────── 相机 ─────────────
42
+ const camPath = bezier(0.3, 0.3, 0.55, 1); // 匀速起步、尾段减速缓停
43
+ const CAM_DIST = 950;
44
+ const camAt = (frame: number) => {
45
+ const t = Math.min(1, Math.max(0, frame / (DUR - 1)));
46
+ const z = CAM_DIST * camPath(t);
47
+ const lat = mix(-140, 110, EASE.smooth(t)); // 横向缓移:近远景相对错动 = 视差
48
+ return {z, x: SLOPE * z + lat};
49
+ };
50
+
51
+ type P3 = {x: number; z: number};
52
+ const project = (p: P3, cam: {x: number; z: number}) => {
53
+ const zr = p.z - cam.z;
54
+ return {sx: 960 + (F * (p.x - cam.x)) / zr, sy: HY + (F * CAM_H) / zr, zr};
55
+ };
56
+
57
+ // ───────────── 世界几何(地平面 X/Z)─────────────
58
+ const trunkX = (z: number) => SLOPE * z - 160 + 150 * Math.sin(z / 950);
59
+ const trunkDX = (z: number) => SLOPE + (150 / 950) * Math.cos(z / 950);
60
+
61
+ // 主干:-300 → 14000,近密远疏采样
62
+ const TRUNK: P3[] = Array.from({length: 261}, (_, i) => {
63
+ const z = -300 + Math.pow(i / 260, 1.7) * 14300;
64
+ return {x: trunkX(z), z};
65
+ });
66
+
67
+ // 三次贝塞尔按弧长等距重采样
68
+ const bez = (a: P3, b: P3, c: P3, d: P3, t: number): P3 => {
69
+ const u = 1 - t;
70
+ return {
71
+ x: u * u * u * a.x + 3 * u * u * t * b.x + 3 * u * t * t * c.x + t * t * t * d.x,
72
+ z: u * u * u * a.z + 3 * u * u * t * b.z + 3 * u * t * t * c.z + t * t * t * d.z,
73
+ };
74
+ };
75
+ const resample = (at: (t: number) => P3, n: number) => {
76
+ const raw = Array.from({length: 241}, (_, i) => at(i / 240));
77
+ const cum = [0];
78
+ for (let i = 1; i < raw.length; i++) cum.push(cum[i - 1] + Math.hypot(raw[i].x - raw[i - 1].x, raw[i].z - raw[i - 1].z));
79
+ const total = cum[cum.length - 1];
80
+ const out: P3[] = [];
81
+ let j = 1;
82
+ for (let k = 0; k <= n; k++) {
83
+ const target = (k / n) * total;
84
+ while (j < raw.length - 1 && cum[j] < target) j++;
85
+ const f = (target - cum[j - 1]) / Math.max(1e-6, cum[j] - cum[j - 1]);
86
+ out.push({x: mix(raw[j - 1].x, raw[j].x, f), z: mix(raw[j - 1].z, raw[j].z, f)});
87
+ }
88
+ return out;
89
+ };
90
+
91
+ // 支流:起点在两侧画外,切向汇入主干(汇入点切线 = 主干切线)
92
+ type TribSpec = {side: number; z0: number; off: number; zm: number; lm: number; grow: number; w: number};
93
+ const TRIB_SPECS: TribSpec[] = [
94
+ {side: -1, z0: -260, off: 700, zm: 1500, lm: 520, grow: 8, w: 5},
95
+ {side: 1, z0: -120, off: 900, zm: 2100, lm: 640, grow: 11, w: 5},
96
+ {side: -1, z0: 500, off: 1500, zm: 2700, lm: 760, grow: 16, w: 4.4},
97
+ {side: 1, z0: 800, off: 1800, zm: 3300, lm: 820, grow: 20, w: 4.4},
98
+ {side: -1, z0: 1400, off: 2300, zm: 3900, lm: 900, grow: 25, w: 4.2},
99
+ {side: 1, z0: 1700, off: 2500, zm: 4600, lm: 980, grow: 29, w: 4.2},
100
+ {side: -1, z0: 2500, off: 2900, zm: 5300, lm: 1050, grow: 34, w: 4.2},
101
+ {side: 1, z0: 3100, off: 3200, zm: 6100, lm: 1150, grow: 38, w: 4.2},
102
+ {side: -1, z0: 4100, off: 3600, zm: 7100, lm: 1250, grow: 43, w: 4.2},
103
+ {side: 1, z0: 5000, off: 3900, zm: 8200, lm: 1350, grow: 47, w: 4.2},
104
+ {side: 1, z0: -420, off: 260, zm: 980, lm: 380, grow: 4, w: 6}, // 贴着镜头右下方掠过的近景支流(大虚焦)
105
+ ];
106
+ const TRIBS = TRIB_SPECS.map((s) => {
107
+ const end: P3 = {x: trunkX(s.zm), z: s.zm};
108
+ const dx = trunkDX(s.zm);
109
+ const dl = Math.hypot(dx, 1);
110
+ const p2: P3 = {x: end.x - (dx / dl) * s.lm, z: end.z - (1 / dl) * s.lm};
111
+ const p0: P3 = {x: trunkX(s.z0) + s.side * s.off, z: s.z0};
112
+ const p1: P3 = {x: p0.x + (end.x - p0.x) * 0.12, z: p0.z + (end.z - p0.z) * 0.5};
113
+ return {...s, pts: resample((t) => bez(p0, p1, p2, end, t), 90)};
114
+ });
115
+
116
+ // ───────────── 线段渲染:按深度分层(近虚 / 中实 / 远雾)─────────────
117
+ const smooth01 = (a: number, b: number, x: number) => {
118
+ const t = Math.min(1, Math.max(0, (x - a) / (b - a)));
119
+ return t * t * (3 - 2 * t);
120
+ };
121
+ type Seg = {x1: number; y1: number; x2: number; y2: number; w: number; o: number; c: string};
122
+
123
+ const emitLine = (
124
+ pts: P3[], g: number, cam: {x: number; z: number}, opts: {w: number; color: string; base: number; ramp?: boolean; pulse: (u: number) => number},
125
+ sharp: Seg[], near: Seg[],
126
+ ) => {
127
+ const n = pts.length - 1;
128
+ const reach = g * n;
129
+ const kMax = Math.min(n, Math.ceil(reach));
130
+ for (let k = 0; k < kMax; k++) {
131
+ const a = pts[k];
132
+ const b0 = pts[k + 1];
133
+ const f = Math.min(1, reach - k);
134
+ const b = f < 1 ? {x: mix(a.x, b0.x, f), z: mix(a.z, b0.z, f)} : b0;
135
+ if (a.z - cam.z < 70 || b.z - cam.z < 70) continue;
136
+ const pa = project(a, cam);
137
+ const pb = project(b, cam);
138
+ if ((pa.sx < -200 && pb.sx < -200) || (pa.sx > 2120 && pb.sx > 2120) || (pa.sy > 1300 && pb.sy > 1300)) continue;
139
+ const zr = (pa.zr + pb.zr) / 2;
140
+ const u = (k + 0.5 * f) / n;
141
+ const fog = 1 - smooth01(2600, 11000, zr); // 远处雾化
142
+ const lift = opts.ramp ? 0.3 + 0.7 * Math.pow(u, 0.8) : 1; // 支流:源头淡、汇入处亮
143
+ // 脉冲只在中远景显形:近处一段线在屏幕上很长,逐段明暗会读成台阶
144
+ const pv = opts.pulse(u);
145
+ const o = opts.base * fog * lift * mix(1, pv, smooth01(500, 1400, zr));
146
+ if (o < 0.01) continue;
147
+ const w = Math.max(0.9, Math.min(46, (opts.w * F) / zr));
148
+ const nearW = 1 - smooth01(420, 1050, zr); // 近景权重 → 进模糊层
149
+ const seg = {x1: pa.sx, y1: pa.sy, x2: pb.sx, y2: pb.sy, w, c: opts.color};
150
+ if (nearW < 0.98) sharp.push({...seg, o: o * (1 - nearW)});
151
+ if (nearW > 0.02) near.push({...seg, w: w * 1.3, o: o * nearW * 0.7});
152
+ }
153
+ // 笔尖
154
+ if (g > 0 && g < 1) {
155
+ const k = Math.min(n - 1, Math.floor(reach));
156
+ const f = reach - k;
157
+ const tip = {x: mix(pts[k].x, pts[k + 1].x, f), z: mix(pts[k].z, pts[k + 1].z, f)};
158
+ if (tip.z - cam.z > 70) return project(tip, cam);
159
+ }
160
+ return null;
161
+ };
162
+
163
+ // ───────────── 标签(中景,video-shotcraft 的镜头号 + 运镜名;字数与原 issue 标签相当,投影位置不变)─────────────
164
+ // 位置按投影逐帧核过:起止两端都错开(不叠、不压汇点、不出画),近处一枚随前飞明显变大
165
+ type LabelSpec = {trib: number; u: number; id: string; note: string; appear: number};
166
+ const LABELS: LabelSpec[] = [
167
+ {trib: 2, u: 0.6, id: 'SHOT-01', note: 'dolly in', appear: 44},
168
+ {trib: 1, u: 0.75, id: 'SHOT-02', note: 'crash zoom', appear: 53},
169
+ {trib: 3, u: 0.6, id: 'SHOT-03', note: 'whip pan', appear: 62},
170
+ {trib: 6, u: 0.3, id: 'SHOT-04', note: 'beat cut', appear: 73},
171
+ {trib: 7, u: 0.45, id: 'SHOT-05', note: 'tilt up', appear: 84},
172
+ {trib: 8, u: 0.45, id: 'SHOT-06', note: 'lockup', appear: 96},
173
+ ];
174
+ const LABEL_PTS = LABELS.map((l) => {
175
+ const pts = TRIBS[l.trib].pts;
176
+ return {p: pts[Math.round(l.u * (pts.length - 1))]};
177
+ });
178
+
179
+ const Label: React.FC<{spec: LabelSpec; at: P3; frame: number; cam: {x: number; z: number}}> = ({spec, at, frame, cam}) => {
180
+ const pr = project(at, cam);
181
+ if (pr.zr < 200) return null;
182
+ const k = Math.min(1.7, Math.max(0.7, 1500 / pr.zr)); // 透视缩放(近大远小),钳住可读区间
183
+ const fog = 1 - smooth01(3600, 8000, pr.zr);
184
+ const pin = ramp(frame, spec.appear, 10, EASE.overshoot);
185
+ const pinOp = ramp(frame, spec.appear, 4, EASE.out);
186
+ const stem = ramp(frame, spec.appear + 2, 12, EASE.snappy);
187
+ const tag = ramp(frame, spec.appear + 6, 14, EASE.snappy);
188
+ // 立杆世界高度远低于相机高度 → 标签落在地平线以下、按深度上下错开(杆高≈相机高时所有标签都投影到地平线上挤成一排)
189
+ const stemH = 44 * k;
190
+ const fs = 25 * k;
191
+ return (
192
+ <div style={{position: 'absolute', left: 0, top: 0, opacity: fog}}>
193
+ {/* 图钉(落在线上) */}
194
+ <div style={{
195
+ position: 'absolute', left: pr.sx - 6 * k, top: pr.sy - 6 * k, width: 12 * k, height: 12 * k, borderRadius: 2.5 * k,
196
+ background: L.accent, opacity: pinOp, transform: `scale(${pin})`,
197
+ boxShadow: `0 0 0 ${3 * k}px ${alpha(L.bg[2], 0.9)}, 0 0 ${18 * k}px ${alpha(L.accent, 0.7)}`,
198
+ }} />
199
+ {/* 立杆 */}
200
+ <div style={{
201
+ position: 'absolute', left: pr.sx - 0.75, top: pr.sy - 8 * k - stemH * stem, width: 1.5, height: stemH * stem,
202
+ background: `linear-gradient(0deg, ${alpha(L.accent, 0.7)}, ${alpha(L.ink, 0.25)})`,
203
+ }} />
204
+ {/* ID 胶囊 */}
205
+ <div style={{
206
+ position: 'absolute', left: pr.sx - 2 * k, top: pr.sy - 8 * k - stemH - 46 * k + (1 - tag) * 14 * k,
207
+ height: 46 * k, padding: `0 ${14 * k}px 0 ${12 * k}px`, borderRadius: 10 * k, boxSizing: 'border-box',
208
+ display: 'flex', alignItems: 'center', gap: 10 * k, whiteSpace: 'nowrap',
209
+ background: alpha('#141711', 0.82), border: `1px solid ${alpha(L.ink, 0.12)}`,
210
+ boxShadow: `inset 0 1px 0 ${alpha('#ffffff', 0.06)}, 0 ${10 * k}px ${28 * k}px ${alpha('#000000', 0.5)}`,
211
+ opacity: tag, filter: tag < 0.98 ? `blur(${((1 - tag) * 6).toFixed(2)}px)` : undefined,
212
+ }}>
213
+ <div style={{width: 7 * k, height: 7 * k, borderRadius: 4 * k, background: L.accent}} />
214
+ <span style={{fontFamily: FONT.mono, fontSize: fs, fontWeight: 600, color: L.ink, letterSpacing: '0.02em'}}>{spec.id}</span>
215
+ <span style={{fontFamily: FONT.sans, fontSize: fs * 0.82, fontWeight: 500, color: L.ink3}}>{spec.note}</span>
216
+ </div>
217
+ </div>
218
+ );
219
+ };
220
+
221
+ // ───────────── 组件 ─────────────
222
+ export const DatavizLandscapeOpen: React.FC = () => {
223
+ const frame = useCurrentFrame();
224
+ const cam = camAt(frame);
225
+ const fadeUp = ramp(frame, 0, 12, EASE.out);
226
+
227
+ const sharp: Seg[] = [];
228
+ const near: Seg[] = [];
229
+ const tips: {sx: number; sy: number; zr: number; trunk: boolean}[] = [];
230
+
231
+ // 流动脉冲:生长完后沿线流向汇点的亮脉冲(窄峰,低速)
232
+ const flowIn = (end: number) => ramp(frame, end, 24, EASE.smooth);
233
+ const pulseFn = (end: number, n: number, speed: number, seed: number) => {
234
+ const on = flowIn(end);
235
+ return (u: number) => {
236
+ const ph = u * n - frame * speed + seed;
237
+ const c = Math.cos(ph * Math.PI * 2);
238
+ return 0.7 + on * 0.55 * Math.pow(Math.max(0, c), 4);
239
+ };
240
+ };
241
+
242
+ const trunkG = ramp(frame, 0, 36, EASE.out);
243
+ TRIBS.forEach((t, i) => {
244
+ const g = ramp(frame, t.grow, 34, EASE.out);
245
+ const tip = emitLine(t.pts, g, cam, {w: t.w, color: L.ink2, base: 0.62, ramp: true, pulse: pulseFn(t.grow + 34, 2.2, 0.018, i * 0.37)}, sharp, near);
246
+ if (tip) tips.push({...tip, trunk: false});
247
+ });
248
+ const tTip = emitLine(TRUNK, trunkG, cam, {w: 11, color: L.accent, base: 0.95, pulse: pulseFn(36, 4, 0.022, 0)}, sharp, near);
249
+ if (tTip) tips.push({...tTip, trunk: true});
250
+ const trunkSegs = sharp.filter((s) => s.c === L.accent);
251
+
252
+ // 地面点阵:与世界锁定的网格,前飞时从远处涌来
253
+ const dots: {x: number; y: number; r: number; o: number}[] = [];
254
+ const STEP = 420;
255
+ const zStart = Math.ceil((cam.z + 300) / STEP) * STEP;
256
+ for (let z = zStart; z < cam.z + 9000; z += STEP) {
257
+ for (let x = Math.floor((cam.x - 5200) / STEP) * STEP; x < cam.x + 5200; x += STEP) {
258
+ const pr = project({x, z}, cam);
259
+ if (pr.sx < -20 || pr.sx > 1940 || pr.sy > 1100) continue;
260
+ const o = 0.28 * (1 - smooth01(2000, 9000, pr.zr)) * smooth01(300, 900, pr.zr);
261
+ if (o < 0.01) continue;
262
+ dots.push({x: pr.sx, y: pr.sy, r: Math.max(0.8, Math.min(3.2, 2400 / pr.zr)), o});
263
+ }
264
+ }
265
+
266
+ const handoff = ramp(frame, 118, 50, EASE.swift);
267
+ const lineRender = (s: Seg, i: number) => (
268
+ <line key={i} x1={s.x1} y1={s.y1} x2={s.x2} y2={s.y2} stroke={s.c} strokeWidth={s.w} strokeOpacity={s.o} strokeLinecap="butt" />
269
+ );
270
+
271
+ return (
272
+ <AbsoluteFill style={{background: L.bg[2], overflow: 'hidden'}}>
273
+ <AbsoluteFill style={{opacity: 0.35 + 0.65 * fadeUp}}>
274
+ <Stage look={L} keyLight={{x: VPX / 1920, y: HY / 1080}} fill={{x: 0.12, y: 0.95}} horizon={HY / 1080} intensity={0.55} grain={0.1} vignette={0.6}>
275
+ {/* 天空里的极淡浮尘 */}
276
+ <div style={{position: 'absolute', left: 0, right: 0, top: 0, height: HY, overflow: 'hidden'}}>
277
+ <Dust look={L} count={26} seed={7} drift={0.12} opacity={0.35} color={L.ink2} />
278
+ </div>
279
+ {/* 地面:地平线以下略亮一档的冷灰绿,向近处压暗 */}
280
+ <div style={{
281
+ position: 'absolute', left: 0, right: 0, top: HY, bottom: 0,
282
+ background: `linear-gradient(180deg, ${alpha('#2a3122', 0.55)} 0%, ${alpha('#141811', 0.3)} 30%, ${alpha('#050604', 0)} 100%)`,
283
+ }} />
284
+ {/* 地平线发丝线 */}
285
+ <div style={{
286
+ position: 'absolute', left: 0, right: 0, top: HY - 0.5, height: 1,
287
+ background: `linear-gradient(90deg, ${alpha(L.ink, 0)} 0%, ${alpha(L.ink, 0.16)} 40%, ${alpha(L.accent, 0.35)} 66%, ${alpha(L.ink, 0.12)} 85%, ${alpha(L.ink, 0)} 100%)`,
288
+ }} />
289
+ </Stage>
290
+
291
+ <svg width={1920} height={1080} style={{position: 'absolute', inset: 0}}>
292
+ <defs>
293
+ <filter id="dv-near" x="-20%" y="-20%" width="140%" height="140%"><feGaussianBlur stdDeviation="11" /></filter>
294
+ <filter id="dv-glow" x="-10%" y="-10%" width="120%" height="120%"><feGaussianBlur stdDeviation="7" /></filter>
295
+ <radialGradient id="dv-tip">
296
+ <stop offset="0" stopColor="#ffffff" stopOpacity={0.9} />
297
+ <stop offset="0.3" stopColor={L.accent} stopOpacity={0.35} />
298
+ <stop offset="1" stopColor={L.accent} stopOpacity={0} />
299
+ </radialGradient>
300
+ </defs>
301
+ {dots.map((d, i) => <circle key={i} cx={d.x} cy={d.y} r={d.r} fill={L.ink2} fillOpacity={d.o} />)}
302
+ {/* 主干泛光(只给主角) */}
303
+ <g filter="url(#dv-glow)" opacity={0.75}>
304
+ {trunkSegs.map((s, i) => <line key={i} x1={s.x1} y1={s.y1} x2={s.x2} y2={s.y2} stroke={L.accent} strokeWidth={s.w * 3} strokeOpacity={s.o * 0.45} strokeLinecap="butt" />)}
305
+ </g>
306
+ {sharp.map(lineRender)}
307
+ {tips.map((t, i) => {
308
+ const r = Math.max(3, Math.min(18, (t.trunk ? 7000 : 4200) / t.zr));
309
+ return (
310
+ <g key={i}>
311
+ <circle cx={t.sx} cy={t.sy} r={r * 5} fill="url(#dv-tip)" />
312
+ <circle cx={t.sx} cy={t.sy} r={r * 0.6} fill="#ffffff" />
313
+ </g>
314
+ );
315
+ })}
316
+ </svg>
317
+
318
+ {/* 汇点交棒亮部:消失点一团黄绿光,收尾升亮 */}
319
+ <div style={{
320
+ position: 'absolute', left: VPX - 520, top: HY - 260, width: 1040, height: 520, pointerEvents: 'none',
321
+ background: `radial-gradient(50% 50% at 50% 50%, ${alpha('#f4ffd6', 0.55)} 0%, ${alpha(L.accent, 0.22)} 22%, ${alpha(L.accent, 0)} 70%)`,
322
+ opacity: 0.25 + 0.75 * handoff, mixBlendMode: 'screen',
323
+ }} />
324
+ <div style={{
325
+ position: 'absolute', left: VPX - 4, top: HY - 4, width: 8, height: 8, borderRadius: 4, background: '#f6ffe0',
326
+ boxShadow: `0 0 18px 6px ${alpha(L.accent, 0.6)}`, opacity: 0.4 + 0.6 * handoff,
327
+ }} />
328
+
329
+ {/* 远的先画、近的后画:近处胶囊正确遮住远处图钉 */}
330
+ {LABELS.map((l, i) => ({l, p: LABEL_PTS[i].p}))
331
+ .sort((a, b) => b.p.z - a.p.z)
332
+ .map(({l, p}) => (frame >= l.appear ? <Label key={l.id} spec={l} at={p} frame={frame} cam={cam} /> : null))}
333
+
334
+ {/* 近景大虚焦层(在标签之上:前景掠过) */}
335
+ <svg width={1920} height={1080} style={{position: 'absolute', inset: 0}}>
336
+ <g filter="url(#dv-near)">{near.map(lineRender)}</g>
337
+ </svg>
338
+ </AbsoluteFill>
339
+
340
+ {/* 标题:天空左上,收尾落字 */}
341
+ <div style={{position: 'absolute', left: 120, top: 128}}>
342
+ {/* 眉题:品牌名按字标规范全小写(不走大写科技字标) */}
343
+ <div style={{
344
+ fontFamily: FONT.mono, fontSize: 28, fontWeight: 600, color: L.accent, letterSpacing: '0.12em',
345
+ opacity: ramp(frame, 104, 14, EASE.out), transform: `translateY(${(1 - ramp(frame, 104, 18, EASE.snappy)) * 12}px)`,
346
+ }}>
347
+ {BRAND.name} · shot recipes
348
+ </div>
349
+ <div style={{...type(108, 650), color: L.ink, marginTop: 26}}>
350
+ <TextReveal text="Every shot," by="word" variant="rise" start={110} each={20} gap={5} />
351
+ </div>
352
+ <div style={{...type(108, 650), color: L.accent, marginTop: 4}}>
353
+ <TextReveal text="one film." by="word" variant="rise" start={121} each={20} gap={5} />
354
+ </div>
355
+ </div>
356
+ </AbsoluteFill>
357
+ );
358
+ };