dsh-drawai 0.4.2 → 0.4.4

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 (379) hide show
  1. package/README.md +7 -5
  2. package/lib/client.js +142 -16
  3. package/lib/index.js +7945 -7719
  4. package/lib/motion/asset-pack.js +394 -394
  5. package/lib/motion/assets.js +291 -291
  6. package/lib/motion/demo-assets-lock.js +10 -10
  7. package/lib/motion/mgstyles/briefs/23-ink-wash.md +147 -0
  8. package/lib/motion/mgstyles/catalog.d/23-ink-wash.json +28 -0
  9. package/lib/motion/mgstyles/catalog.json +127 -14
  10. package/lib/motion/mgstyles/upstream/demos/23-ink-wash/brush.js +149 -0
  11. package/lib/motion/mgstyles/upstream/demos/23-ink-wash/film.js +202 -0
  12. package/lib/motion/mgstyles/upstream/manifest.json +28 -3
  13. package/lib/motion/mgstyles/upstream/prompts/23-ink-wash.md +59 -0
  14. package/lib/motion/mgstyles/vendor/README.md +28 -28
  15. package/lib/motion/mgstyles/vendor/modules/d3/LICENSE +13 -13
  16. package/lib/motion/mgstyles/vendor/modules/d3/dist/d3.min.js +2 -2
  17. package/lib/motion/mgstyles/vendor/modules/opentype.js/LICENSE +20 -20
  18. package/lib/motion/mgstyles/vendor/modules/opentype.js/dist/opentype.mjs +14460 -14460
  19. package/lib/motion/mgstyles/vendor/modules/simplex-noise/LICENSE +21 -21
  20. package/lib/motion/mgstyles/vendor/modules/simplex-noise/dist/esm/simplex-noise.js +465 -465
  21. package/lib/motion/mgstyles/vendor/modules/topojson-client/LICENSE +13 -13
  22. package/lib/motion/mgstyles/vendor/modules/topojson-client/dist/topojson-client.min.js +2 -2
  23. package/lib/motion/project.js +5 -1
  24. package/lib/motion/qa.js +116 -6
  25. package/lib/motion/render.js +179 -179
  26. package/lib/motion/scene-kit.js +1 -1
  27. package/lib/motion/shotcraft/upstream/SKILL.md +286 -286
  28. package/lib/motion/shotcraft/upstream/assets/lib/Caption.tsx +54 -54
  29. package/lib/motion/shotcraft/upstream/assets/lib/ClipCard.tsx +200 -200
  30. package/lib/motion/shotcraft/upstream/assets/lib/DigitRoll.tsx +45 -45
  31. package/lib/motion/shotcraft/upstream/assets/lib/FlashCut.tsx +20 -20
  32. package/lib/motion/shotcraft/upstream/assets/lib/FlatPanel.tsx +65 -65
  33. package/lib/motion/shotcraft/upstream/assets/lib/PageCam.tsx +151 -151
  34. package/lib/motion/shotcraft/upstream/assets/lib/VerticalTicker.tsx +129 -129
  35. package/lib/motion/shotcraft/upstream/assets/lib/helpers/camera.tsx +75 -75
  36. package/lib/motion/shotcraft/upstream/assets/lib/helpers/motion.ts +40 -40
  37. package/lib/motion/shotcraft/upstream/assets/lib/helpers/rand.ts +11 -11
  38. package/lib/motion/shotcraft/upstream/assets/lib/helpers/shake.ts +10 -10
  39. package/lib/motion/shotcraft/upstream/assets/scripts/build-readme-cover.mjs +49 -49
  40. package/lib/motion/shotcraft/upstream/assets/scripts/capture-template.mjs +210 -210
  41. package/lib/motion/shotcraft/upstream/assets/scripts/sfx-source.py +423 -423
  42. package/lib/motion/shotcraft/upstream/assets/scripts/smoke-render-demos.py +170 -170
  43. package/lib/motion/shotcraft/upstream/assets/scripts/test_sfx_source.py +157 -157
  44. package/lib/motion/shotcraft/upstream/demos/README.md +120 -120
  45. package/lib/motion/shotcraft/upstream/demos/_fixtures/Brand.tsx +112 -112
  46. package/lib/motion/shotcraft/upstream/demos/_fixtures/Fixtures.tsx +647 -647
  47. package/lib/motion/shotcraft/upstream/demos/_fixtures/Look.tsx +316 -316
  48. package/lib/motion/shotcraft/upstream/demos/_fixtures/Motion.tsx +82 -82
  49. package/lib/motion/shotcraft/upstream/demos/_fixtures/PageCam2D.tsx +115 -115
  50. package/lib/motion/shotcraft/upstream/demos/_fixtures/Polish.tsx +243 -243
  51. package/lib/motion/shotcraft/upstream/demos/_textures/live-layout.json +388 -388
  52. package/lib/motion/shotcraft/upstream/demos/camera/basic-3d-scene/Basic3DScene.tsx +250 -250
  53. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashImpactReal.tsx +305 -305
  54. package/lib/motion/shotcraft/upstream/demos/camera/crash-zoom-punch/CrashZoomReal.tsx +246 -246
  55. package/lib/motion/shotcraft/upstream/demos/camera/cursor-flyover/CursorFlyover.tsx +390 -390
  56. package/lib/motion/shotcraft/upstream/demos/camera/depth-layer-moves/MultiplaneReal.tsx +138 -138
  57. package/lib/motion/shotcraft/upstream/demos/camera/graze-face-tour/GrazeFaceTour.tsx +542 -542
  58. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/OverheadTabletopDrop.tsx +315 -315
  59. package/lib/motion/shotcraft/upstream/demos/camera/overhead-camera-moves/TiltReveal.tsx +299 -299
  60. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/DroneDiveLanding.tsx +173 -173
  61. package/lib/motion/shotcraft/upstream/demos/camera/space-camera-moves/ExplodedView.tsx +348 -348
  62. package/lib/motion/shotcraft/upstream/demos/camera/steep-tilt-glide/SteepTiltGlide.tsx +366 -366
  63. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/BulletTimeFreezeOrbit.tsx +279 -279
  64. package/lib/motion/shotcraft/upstream/demos/camera/tension-camera-moves/PullBackIsolation.tsx +184 -184
  65. package/lib/motion/shotcraft/upstream/demos/camera/terminal-3d/Terminal3D.tsx +390 -390
  66. package/lib/motion/shotcraft/upstream/demos/data/before-after-slider-scrub/BeforeAfterSliderScrub.tsx +155 -155
  67. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/AxisRescaleShockV2.tsx +303 -303
  68. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/OscilloscopeStreamV2.tsx +290 -290
  69. package/lib/motion/shotcraft/upstream/demos/data/chart-live-moves/UnitDotSwarmRegroupV2.tsx +278 -278
  70. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/NeedleSweepSelftest.tsx +307 -307
  71. package/lib/motion/shotcraft/upstream/demos/data/gauge-readout-moves/TapeScrollFixedPointer.tsx +215 -215
  72. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/BrakeReticleLock.tsx +299 -299
  73. package/lib/motion/shotcraft/upstream/demos/data/scroll-brake-moves/ChangelogScrollBrake.tsx +232 -232
  74. package/lib/motion/shotcraft/upstream/demos/data/timeline-travel/TimelineTravel.tsx +290 -290
  75. package/lib/motion/shotcraft/upstream/demos/effects/assemble-then-type-flyin/AssembleThenTypeFlyin.tsx +273 -273
  76. package/lib/motion/shotcraft/upstream/demos/effects/aurora-bloom-bg-flip/AuroraBloomBgFlip.tsx +167 -167
  77. package/lib/motion/shotcraft/upstream/demos/effects/brand-frame-snap/BrandFrameSnap.tsx +536 -536
  78. package/lib/motion/shotcraft/upstream/demos/effects/fui-hud-moves/ReticleLockOn.tsx +164 -164
  79. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/FlylineArc.tsx +175 -175
  80. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/GlowOrbAmbient.tsx +197 -197
  81. package/lib/motion/shotcraft/upstream/demos/effects/glow-flyline-moves/OrbFlylineRelay.tsx +241 -241
  82. package/lib/motion/shotcraft/upstream/demos/effects/icon-performance-moves/AttentionBounce.tsx +279 -279
  83. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/AnimeImpact.tsx +230 -230
  84. package/lib/motion/shotcraft/upstream/demos/effects/impact-feedback/HitCounter.tsx +345 -345
  85. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SheenSweepRetry.tsx +275 -275
  86. package/lib/motion/shotcraft/upstream/demos/effects/light-play-moves/SpotlightSweepReveal.tsx +229 -229
  87. package/lib/motion/shotcraft/upstream/demos/effects/radial-ripple-phone-chips/RadialRipplePhoneChips.tsx +312 -312
  88. package/lib/motion/shotcraft/upstream/demos/effects/riso-print-hits/RisoMisregistrationHit.tsx +222 -222
  89. package/lib/motion/shotcraft/upstream/demos/effects/scan-bracket-sweep/ScanBracketSweep.tsx +295 -295
  90. package/lib/motion/shotcraft/upstream/demos/effects/scanline-annotate-focus/ScanlineAnnotateFocus.tsx +329 -329
  91. package/lib/motion/shotcraft/upstream/demos/effects/scanline-assemble-flyin/ScanlineAssembleFlyin.tsx +315 -315
  92. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ImpactBurstKit.tsx +264 -264
  93. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/KanadaPerspectiveSnap.tsx +260 -260
  94. package/lib/motion/shotcraft/upstream/demos/effects/slam-entrance-moves/ScoreSlam.tsx +263 -263
  95. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/CornerSpotlightReveal.tsx +123 -123
  96. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/GlowWakeSleepPanel.tsx +187 -187
  97. package/lib/motion/shotcraft/upstream/demos/effects/spotlight-sweep-moves/SlideSpotlightPan.tsx +175 -175
  98. package/lib/motion/shotcraft/upstream/demos/interaction/autolayout-gap-dial/AutolayoutGapDial.tsx +305 -305
  99. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/DiagramCascadeBuild.tsx +350 -350
  100. package/lib/motion/shotcraft/upstream/demos/interaction/canvas-materialize-moves/PanelToCanvasMaterialize.tsx +352 -352
  101. package/lib/motion/shotcraft/upstream/demos/interaction/chip-grid-single-select-blackout/ChipGridSingleSelectBlackout.tsx +218 -218
  102. package/lib/motion/shotcraft/upstream/demos/interaction/collab-cursor-moves/CursorCastEnsemble.tsx +297 -297
  103. package/lib/motion/shotcraft/upstream/demos/interaction/glass-pill-dictation-typing/GlassPillDictationTyping.tsx +157 -157
  104. package/lib/motion/shotcraft/upstream/demos/interaction/hashtag-to-pill-materialize/HashtagToPillMaterialize.tsx +218 -218
  105. package/lib/motion/shotcraft/upstream/demos/interaction/picker-carousel-feature-cycle/PickerCarouselFeatureCycle.tsx +202 -202
  106. package/lib/motion/shotcraft/upstream/demos/interaction/segmented-thumb-hero/SegmentedThumbHero.tsx +265 -265
  107. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/PaletteThemeRipple.tsx +457 -457
  108. package/lib/motion/shotcraft/upstream/demos/interaction/theme-switch-moves/ThemeSweepToggle.tsx +446 -446
  109. package/lib/motion/shotcraft/upstream/demos/interaction/type-and-filter/TypeAndFilter.tsx +249 -249
  110. package/lib/motion/shotcraft/upstream/demos/interaction/voice-waveform-live/VoiceWaveformLive.tsx +278 -278
  111. package/lib/motion/shotcraft/upstream/demos/opening/crane-rise-reveal/CraneRiseReveal.tsx +332 -332
  112. package/lib/motion/shotcraft/upstream/demos/opening/dataviz-landscape-open/DatavizLandscapeOpen.tsx +358 -358
  113. package/lib/motion/shotcraft/upstream/demos/opening/fracture/Fracture.tsx +201 -201
  114. package/lib/motion/shotcraft/upstream/demos/opening/icon-field-colorize/IconFieldColorize.tsx +200 -200
  115. package/lib/motion/shotcraft/upstream/demos/opening/letterspace-materialize/LetterspaceMaterialize.tsx +208 -208
  116. package/lib/motion/shotcraft/upstream/demos/opening/magician-card-flourish/MagicianCardFlourish.tsx +341 -341
  117. package/lib/motion/shotcraft/upstream/demos/opening/orbit-ring-title-open/OrbitRingTitleOpen.tsx +389 -389
  118. package/lib/motion/shotcraft/upstream/demos/opening/spotlight-hero-card/SpotlightHeroCard.tsx +293 -293
  119. package/lib/motion/shotcraft/upstream/demos/opening/stroke-segment-build/StrokeSegmentBuild.tsx +183 -183
  120. package/lib/motion/shotcraft/upstream/demos/opening/text-as-mask/TextAsMask.tsx +245 -245
  121. package/lib/motion/shotcraft/upstream/demos/outro/grain-dissolve/GrainDissolve.tsx +222 -222
  122. package/lib/motion/shotcraft/upstream/demos/outro/logo-shrink-wordmark-lockup/LogoShrinkWordmarkLockup.tsx +223 -223
  123. package/lib/motion/shotcraft/upstream/demos/outro/neon-triple-marquee/NeonTripleMarquee.tsx +217 -217
  124. package/lib/motion/shotcraft/upstream/demos/outro/outro-group-photo-launch/OutroGroupPhotoLaunch.tsx +343 -343
  125. package/lib/motion/shotcraft/upstream/demos/outro/ui-strip-away-outro/UiStripAwayOutro.tsx +357 -357
  126. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/IconFlipBloomLogo.tsx +187 -187
  127. package/lib/motion/shotcraft/upstream/demos/outro/ui-to-brand-morph/InputMorphsIntoLogo.tsx +333 -333
  128. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-cut-moves/PaparazziFlash.tsx +274 -274
  129. package/lib/motion/shotcraft/upstream/demos/rhythm/beat-step-list-theme-cycle/BeatStepListThemeCycle.tsx +270 -270
  130. package/lib/motion/shotcraft/upstream/demos/rhythm/panel-grid-moves/ComicPanelSplit.tsx +430 -430
  131. package/lib/motion/shotcraft/upstream/demos/rhythm/quad-split-parallel-scenes/QuadSplitParallelScenes.tsx +252 -252
  132. package/lib/motion/shotcraft/upstream/demos/rhythm/rhythm-interrupt-moves/JumpCutPunchIn.tsx +106 -106
  133. package/lib/motion/shotcraft/upstream/demos/rhythm/sakuga-timing-shift/SakugaTimingShift.tsx +288 -288
  134. package/lib/motion/shotcraft/upstream/demos/rhythm/speed-ramp-freeze/FreezeAnnotateReal.tsx +362 -362
  135. package/lib/motion/shotcraft/upstream/demos/rhythm/trailer-grammar-moves/TrailerBumper.tsx +168 -168
  136. package/lib/motion/shotcraft/upstream/demos/transition/bottom-push-stack-wipe/BottomPushStackWipe.tsx +310 -310
  137. package/lib/motion/shotcraft/upstream/demos/transition/card-flip-reveal/CardFlipReveal.tsx +261 -261
  138. package/lib/motion/shotcraft/upstream/demos/transition/card-flock-tumble/CardFlockTumble.tsx +459 -459
  139. package/lib/motion/shotcraft/upstream/demos/transition/circle-match-iris/CircleMatchIris.tsx +294 -294
  140. package/lib/motion/shotcraft/upstream/demos/transition/gradient-transition/GradientTransition.tsx +161 -161
  141. package/lib/motion/shotcraft/upstream/demos/transition/line-carry-transition/LineCarryTransition.tsx +248 -248
  142. package/lib/motion/shotcraft/upstream/demos/transition/mosaic-reframe/MosaicReframe.tsx +359 -359
  143. package/lib/motion/shotcraft/upstream/demos/transition/page-turn-transitions/BarnDoorSplit.tsx +227 -227
  144. package/lib/motion/shotcraft/upstream/demos/transition/print-texture-transitions/InkBleedReveal.tsx +162 -162
  145. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/PortalWipeV2.tsx +248 -248
  146. package/lib/motion/shotcraft/upstream/demos/transition/shot-transitions/WhipBrakeReal.tsx +186 -186
  147. package/lib/motion/shotcraft/upstream/demos/transition/tear-streak-transitions/GlitchDisplace.tsx +355 -355
  148. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/InvisibleCut.tsx +272 -272
  149. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/LightLeakBurn.tsx +262 -262
  150. package/lib/motion/shotcraft/upstream/demos/transition/transition-hidden-cut/VersusSlam.tsx +217 -217
  151. package/lib/motion/shotcraft/upstream/demos/transition/transition-travel/LetterformZoom.tsx +285 -285
  152. package/lib/motion/shotcraft/upstream/demos/transition/white-flash-logo-simplify-cut/WhiteFlashLogoSimplifyCut.tsx +205 -205
  153. package/lib/motion/shotcraft/upstream/demos/transition/wipe-transitions/BlindsSlice.tsx +178 -178
  154. package/lib/motion/shotcraft/upstream/demos/typography/blur-slide/BlurSlide.tsx +147 -147
  155. package/lib/motion/shotcraft/upstream/demos/typography/brace-expand/BraceExpand.tsx +143 -143
  156. package/lib/motion/shotcraft/upstream/demos/typography/brand-ink-open/BrandInkOpen.tsx +134 -134
  157. package/lib/motion/shotcraft/upstream/demos/typography/countdown-arc-scatter/CountdownArcScatter.tsx +217 -217
  158. package/lib/motion/shotcraft/upstream/demos/typography/flying-words/FlyingWords.tsx +198 -198
  159. package/lib/motion/shotcraft/upstream/demos/typography/glitch-cycle/GlitchCycle.tsx +221 -221
  160. package/lib/motion/shotcraft/upstream/demos/typography/gradient-word-sweep/GradientWordSweep.tsx +312 -312
  161. package/lib/motion/shotcraft/upstream/demos/typography/lead-word-zoom-assemble/LeadWordZoomAssemble.tsx +261 -261
  162. package/lib/motion/shotcraft/upstream/demos/typography/marker-underline-title/MarkerUnderlineTitle.tsx +121 -121
  163. package/lib/motion/shotcraft/upstream/demos/typography/outline-word-fill/OutlineWordFill.tsx +153 -153
  164. package/lib/motion/shotcraft/upstream/demos/typography/paper-title-card/PaperTitleCard.tsx +179 -179
  165. package/lib/motion/shotcraft/upstream/demos/typography/pill-chip-slot-cycle-handled/PillChipSlotCycleHandled.tsx +140 -140
  166. package/lib/motion/shotcraft/upstream/demos/typography/pill-slot-cycle/PillSlotCycle.tsx +309 -309
  167. package/lib/motion/shotcraft/upstream/demos/typography/text-column-converge/TextColumnConverge.tsx +191 -191
  168. package/lib/motion/shotcraft/upstream/demos/typography/title-demote-to-label/TitleDemoteToLabel.tsx +292 -292
  169. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/LetterformDriftAssembly.tsx +135 -135
  170. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/SplitTextStagger.tsx +124 -124
  171. package/lib/motion/shotcraft/upstream/demos/typography/type-assembly-moves/TextOnPath.tsx +255 -255
  172. package/lib/motion/shotcraft/upstream/demos/typography/type-entrance-moves/LetterDropPhysics.tsx +173 -173
  173. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/FontWeightPump.tsx +225 -225
  174. package/lib/motion/shotcraft/upstream/demos/typography/type-rhythm-sync/KaraokeFillSync.tsx +141 -141
  175. package/lib/motion/shotcraft/upstream/demos/typography/typewriter-moves/TypewriterErrorRetype.tsx +137 -137
  176. package/lib/motion/shotcraft/upstream/demos/typography/vertical-word-roll-blur-cycle/VerticalWordRollBlurCycle.tsx +147 -147
  177. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-filmstrip/WordRelayFilmstrip.tsx +409 -409
  178. package/lib/motion/shotcraft/upstream/demos/typography/word-relay-geometry/WordRelayGeometry.tsx +280 -280
  179. package/lib/motion/shotcraft/upstream/demos/ui-entrance/avatar-bracket-carousel/AvatarBracketCarousel.tsx +271 -271
  180. package/lib/motion/shotcraft/upstream/demos/ui-entrance/bezier-source-converge-merge/BezierSourceConvergeMerge.tsx +385 -385
  181. package/lib/motion/shotcraft/upstream/demos/ui-entrance/card-stack/CardStack.tsx +312 -312
  182. package/lib/motion/shotcraft/upstream/demos/ui-entrance/carousel-3d/Carousel3D.tsx +303 -303
  183. package/lib/motion/shotcraft/upstream/demos/ui-entrance/clipcard-looping/ClipCardLooping.tsx +77 -77
  184. package/lib/motion/shotcraft/upstream/demos/ui-entrance/cloner-depth-echo/ClonerDepthEcho.tsx +311 -311
  185. package/lib/motion/shotcraft/upstream/demos/ui-entrance/deck-deal-flyin/DeckDealFlyin.tsx +307 -307
  186. package/lib/motion/shotcraft/upstream/demos/ui-entrance/doc-park-left-pill-deal/DocParkLeftPillDeal.tsx +349 -349
  187. package/lib/motion/shotcraft/upstream/demos/ui-entrance/document-typewriter-reveal/DocumentTypewriterReveal.tsx +255 -255
  188. package/lib/motion/shotcraft/upstream/demos/ui-entrance/draw-svg-trace/DrawSvgTrace.tsx +244 -244
  189. package/lib/motion/shotcraft/upstream/demos/ui-entrance/element-body-moves/ContactShadowLift.tsx +217 -217
  190. package/lib/motion/shotcraft/upstream/demos/ui-entrance/integration-hub-map/IntegrationHubMap.tsx +652 -652
  191. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-reveal/ListReveal.tsx +153 -153
  192. package/lib/motion/shotcraft/upstream/demos/ui-entrance/list-stack-press/ListStackPress.tsx +238 -238
  193. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-forerun/NeonFrameForerun.tsx +324 -324
  194. package/lib/motion/shotcraft/upstream/demos/ui-entrance/neon-frame-orbit-drop/NeonFrameForerunOrbit.tsx +354 -354
  195. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/PageWaterfallWall.tsx +101 -101
  196. package/lib/motion/shotcraft/upstream/demos/ui-entrance/page-waterfall-wall/VerticalTicker.tsx +129 -129
  197. package/lib/motion/shotcraft/upstream/demos/ui-entrance/product-card-progressive-assemble/ProductCardProgressiveAssemble.tsx +297 -297
  198. package/lib/motion/shotcraft/upstream/demos/ui-entrance/radial-wave/RadialWave.tsx +57 -57
  199. package/lib/motion/shotcraft/upstream/demos/ui-entrance/research-card-stack-scroll/ResearchCardStackScroll.tsx +155 -155
  200. package/lib/motion/shotcraft/upstream/demos/ui-entrance/row-embed/RowEmbed.tsx +175 -175
  201. package/lib/motion/shotcraft/upstream/demos/ui-entrance/value-stagger-gradient/ValueStaggerGradient.tsx +153 -153
  202. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/BentoLightUp.tsx +146 -146
  203. package/lib/motion/shotcraft/upstream/demos/ui-entrance/wall-reveal-moves/WireframeDrawOn.tsx +226 -226
  204. package/lib/motion/shotcraft/upstream/gallery/api/library.json +1 -1
  205. package/lib/motion/shotcraft/upstream/references/aesthetic-rules.md +193 -193
  206. package/lib/motion/shotcraft/upstream/references/final-review.md +121 -121
  207. package/lib/motion/shotcraft/upstream/references/guided-free-creation.md +199 -199
  208. package/lib/motion/shotcraft/upstream/references/jianying-export.md +183 -183
  209. package/lib/motion/shotcraft/upstream/references/music-beat-sync.md +257 -257
  210. package/lib/motion/shotcraft/upstream/references/pipeline.md +382 -382
  211. package/lib/motion/shotcraft/upstream/references/publish-upload-post.md +111 -111
  212. package/lib/motion/shotcraft/upstream/references/sequences/promo-energy-arc.md +50 -50
  213. package/lib/motion/shotcraft/upstream/references/sfx-sourcing.md +95 -95
  214. package/lib/motion/shotcraft/upstream/references/shots/camera/basic-3d-scene.md +41 -41
  215. package/lib/motion/shotcraft/upstream/references/shots/camera/crash-zoom-punch.md +52 -52
  216. package/lib/motion/shotcraft/upstream/references/shots/camera/cursor-flyover.md +39 -39
  217. package/lib/motion/shotcraft/upstream/references/shots/camera/depth-layer-moves.md +39 -39
  218. package/lib/motion/shotcraft/upstream/references/shots/camera/graze-face-tour.md +57 -57
  219. package/lib/motion/shotcraft/upstream/references/shots/camera/overhead-camera-moves.md +51 -51
  220. package/lib/motion/shotcraft/upstream/references/shots/camera/space-camera-moves.md +46 -46
  221. package/lib/motion/shotcraft/upstream/references/shots/camera/steep-tilt-glide.md +52 -52
  222. package/lib/motion/shotcraft/upstream/references/shots/camera/tension-camera-moves.md +43 -43
  223. package/lib/motion/shotcraft/upstream/references/shots/camera/terminal-3d.md +42 -42
  224. package/lib/motion/shotcraft/upstream/references/shots/data/before-after-slider-scrub.md +48 -48
  225. package/lib/motion/shotcraft/upstream/references/shots/data/chart-live-moves.md +52 -52
  226. package/lib/motion/shotcraft/upstream/references/shots/data/gauge-readout-moves.md +45 -45
  227. package/lib/motion/shotcraft/upstream/references/shots/data/scroll-brake-moves.md +46 -46
  228. package/lib/motion/shotcraft/upstream/references/shots/data/timeline-travel.md +44 -44
  229. package/lib/motion/shotcraft/upstream/references/shots/effects/assemble-then-type-flyin.md +63 -63
  230. package/lib/motion/shotcraft/upstream/references/shots/effects/aurora-bloom-bg-flip.md +54 -54
  231. package/lib/motion/shotcraft/upstream/references/shots/effects/brand-frame-snap.md +58 -58
  232. package/lib/motion/shotcraft/upstream/references/shots/effects/fui-hud-moves.md +35 -35
  233. package/lib/motion/shotcraft/upstream/references/shots/effects/glow-flyline-moves.md +53 -53
  234. package/lib/motion/shotcraft/upstream/references/shots/effects/icon-performance-moves.md +42 -42
  235. package/lib/motion/shotcraft/upstream/references/shots/effects/impact-feedback.md +50 -50
  236. package/lib/motion/shotcraft/upstream/references/shots/effects/light-play-moves.md +46 -46
  237. package/lib/motion/shotcraft/upstream/references/shots/effects/radial-ripple-phone-chips.md +56 -56
  238. package/lib/motion/shotcraft/upstream/references/shots/effects/riso-print-hits.md +49 -49
  239. package/lib/motion/shotcraft/upstream/references/shots/effects/scan-bracket-sweep.md +50 -50
  240. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-annotate-focus.md +53 -53
  241. package/lib/motion/shotcraft/upstream/references/shots/effects/scanline-assemble-flyin.md +53 -53
  242. package/lib/motion/shotcraft/upstream/references/shots/effects/slam-entrance-moves.md +55 -55
  243. package/lib/motion/shotcraft/upstream/references/shots/effects/spotlight-sweep-moves.md +52 -52
  244. package/lib/motion/shotcraft/upstream/references/shots/interaction/autolayout-gap-dial.md +60 -60
  245. package/lib/motion/shotcraft/upstream/references/shots/interaction/canvas-materialize-moves.md +57 -57
  246. package/lib/motion/shotcraft/upstream/references/shots/interaction/chip-grid-single-select-blackout.md +51 -51
  247. package/lib/motion/shotcraft/upstream/references/shots/interaction/collab-cursor-moves.md +41 -41
  248. package/lib/motion/shotcraft/upstream/references/shots/interaction/glass-pill-dictation-typing.md +53 -53
  249. package/lib/motion/shotcraft/upstream/references/shots/interaction/hashtag-to-pill-materialize.md +60 -60
  250. package/lib/motion/shotcraft/upstream/references/shots/interaction/picker-carousel-feature-cycle.md +55 -55
  251. package/lib/motion/shotcraft/upstream/references/shots/interaction/segmented-thumb-hero.md +57 -57
  252. package/lib/motion/shotcraft/upstream/references/shots/interaction/theme-switch-moves.md +47 -47
  253. package/lib/motion/shotcraft/upstream/references/shots/interaction/type-and-filter.md +37 -37
  254. package/lib/motion/shotcraft/upstream/references/shots/interaction/voice-waveform-live.md +54 -54
  255. package/lib/motion/shotcraft/upstream/references/shots/opening/brand-ink-open.md +36 -36
  256. package/lib/motion/shotcraft/upstream/references/shots/opening/crane-rise-reveal.md +56 -56
  257. package/lib/motion/shotcraft/upstream/references/shots/opening/dataviz-landscape-open.md +56 -56
  258. package/lib/motion/shotcraft/upstream/references/shots/opening/fracture.md +40 -40
  259. package/lib/motion/shotcraft/upstream/references/shots/opening/icon-field-colorize.md +60 -60
  260. package/lib/motion/shotcraft/upstream/references/shots/opening/letterspace-materialize.md +57 -57
  261. package/lib/motion/shotcraft/upstream/references/shots/opening/magician-card-flourish.md +73 -73
  262. package/lib/motion/shotcraft/upstream/references/shots/opening/orbit-ring-title-open.md +87 -87
  263. package/lib/motion/shotcraft/upstream/references/shots/opening/spotlight-hero-card.md +55 -55
  264. package/lib/motion/shotcraft/upstream/references/shots/opening/stroke-segment-build.md +50 -50
  265. package/lib/motion/shotcraft/upstream/references/shots/opening/text-as-mask.md +59 -59
  266. package/lib/motion/shotcraft/upstream/references/shots/outro/grain-dissolve.md +38 -38
  267. package/lib/motion/shotcraft/upstream/references/shots/outro/logo-shrink-wordmark-lockup.md +38 -38
  268. package/lib/motion/shotcraft/upstream/references/shots/outro/neon-triple-marquee.md +59 -59
  269. package/lib/motion/shotcraft/upstream/references/shots/outro/outro-group-photo-launch.md +39 -39
  270. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-strip-away-outro.md +61 -61
  271. package/lib/motion/shotcraft/upstream/references/shots/outro/ui-to-brand-morph.md +52 -52
  272. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-cut-moves.md +50 -50
  273. package/lib/motion/shotcraft/upstream/references/shots/rhythm/beat-step-list-theme-cycle.md +66 -66
  274. package/lib/motion/shotcraft/upstream/references/shots/rhythm/panel-grid-moves.md +43 -43
  275. package/lib/motion/shotcraft/upstream/references/shots/rhythm/quad-split-parallel-scenes.md +38 -38
  276. package/lib/motion/shotcraft/upstream/references/shots/rhythm/rhythm-interrupt-moves.md +38 -38
  277. package/lib/motion/shotcraft/upstream/references/shots/rhythm/sakuga-timing-shift.md +56 -56
  278. package/lib/motion/shotcraft/upstream/references/shots/rhythm/speed-ramp-freeze.md +44 -44
  279. package/lib/motion/shotcraft/upstream/references/shots/rhythm/trailer-grammar-moves.md +38 -38
  280. package/lib/motion/shotcraft/upstream/references/shots/transition/bottom-push-stack-wipe.md +63 -63
  281. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flip-reveal.md +57 -57
  282. package/lib/motion/shotcraft/upstream/references/shots/transition/card-flock-tumble.md +63 -63
  283. package/lib/motion/shotcraft/upstream/references/shots/transition/circle-match-iris.md +58 -58
  284. package/lib/motion/shotcraft/upstream/references/shots/transition/gradient-transition.md +45 -45
  285. package/lib/motion/shotcraft/upstream/references/shots/transition/line-carry-transition.md +55 -55
  286. package/lib/motion/shotcraft/upstream/references/shots/transition/mosaic-reframe.md +49 -49
  287. package/lib/motion/shotcraft/upstream/references/shots/transition/page-turn-transitions.md +42 -42
  288. package/lib/motion/shotcraft/upstream/references/shots/transition/print-texture-transitions.md +42 -42
  289. package/lib/motion/shotcraft/upstream/references/shots/transition/shot-transitions.md +45 -45
  290. package/lib/motion/shotcraft/upstream/references/shots/transition/tear-streak-transitions.md +48 -48
  291. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-hidden-cut.md +55 -55
  292. package/lib/motion/shotcraft/upstream/references/shots/transition/transition-travel.md +43 -43
  293. package/lib/motion/shotcraft/upstream/references/shots/transition/white-flash-logo-simplify-cut.md +41 -41
  294. package/lib/motion/shotcraft/upstream/references/shots/transition/wipe-transitions.md +42 -42
  295. package/lib/motion/shotcraft/upstream/references/shots/typography/blur-slide.md +59 -59
  296. package/lib/motion/shotcraft/upstream/references/shots/typography/brace-expand.md +55 -55
  297. package/lib/motion/shotcraft/upstream/references/shots/typography/countdown-arc-scatter.md +65 -65
  298. package/lib/motion/shotcraft/upstream/references/shots/typography/document-typewriter-reveal.md +42 -42
  299. package/lib/motion/shotcraft/upstream/references/shots/typography/flying-words.md +64 -64
  300. package/lib/motion/shotcraft/upstream/references/shots/typography/glitch-cycle.md +64 -64
  301. package/lib/motion/shotcraft/upstream/references/shots/typography/gradient-word-sweep.md +54 -54
  302. package/lib/motion/shotcraft/upstream/references/shots/typography/lead-word-zoom-assemble.md +91 -91
  303. package/lib/motion/shotcraft/upstream/references/shots/typography/marker-underline-title.md +51 -51
  304. package/lib/motion/shotcraft/upstream/references/shots/typography/outline-word-fill.md +66 -66
  305. package/lib/motion/shotcraft/upstream/references/shots/typography/paper-title-card.md +38 -38
  306. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-chip-slot-cycle-handled.md +66 -66
  307. package/lib/motion/shotcraft/upstream/references/shots/typography/pill-slot-cycle.md +58 -58
  308. package/lib/motion/shotcraft/upstream/references/shots/typography/text-column-converge.md +61 -61
  309. package/lib/motion/shotcraft/upstream/references/shots/typography/title-demote-to-label.md +64 -64
  310. package/lib/motion/shotcraft/upstream/references/shots/typography/type-assembly-moves.md +45 -45
  311. package/lib/motion/shotcraft/upstream/references/shots/typography/type-entrance-moves.md +41 -41
  312. package/lib/motion/shotcraft/upstream/references/shots/typography/type-rhythm-sync.md +51 -51
  313. package/lib/motion/shotcraft/upstream/references/shots/typography/typewriter-moves.md +42 -42
  314. package/lib/motion/shotcraft/upstream/references/shots/typography/vertical-word-roll-blur-cycle.md +63 -63
  315. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-filmstrip.md +57 -57
  316. package/lib/motion/shotcraft/upstream/references/shots/typography/word-relay-geometry.md +75 -75
  317. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/avatar-bracket-carousel.md +59 -59
  318. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/bezier-source-converge-merge.md +67 -67
  319. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/card-stack.md +60 -60
  320. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/carousel-3d.md +66 -66
  321. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/cloner-depth-echo.md +40 -40
  322. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/deck-deal-flyin.md +45 -45
  323. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/doc-park-left-pill-deal.md +62 -62
  324. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/draw-svg-trace.md +55 -55
  325. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/element-body-moves.md +37 -37
  326. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/integration-hub-map.md +55 -55
  327. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-reveal.md +50 -50
  328. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/list-stack-press.md +43 -43
  329. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-forerun.md +55 -55
  330. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/neon-frame-orbit-drop.md +51 -51
  331. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/page-waterfall-wall.md +51 -51
  332. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/product-card-progressive-assemble.md +56 -56
  333. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/radial-wave.md +49 -49
  334. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/research-card-stack-scroll.md +57 -57
  335. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/row-embed.md +36 -36
  336. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/value-stagger-gradient.md +64 -64
  337. package/lib/motion/shotcraft/upstream/references/shots/ui-entrance/wall-reveal-moves.md +47 -47
  338. package/lib/motion/shotcraft/upstream/references/sound-design.md +170 -170
  339. package/lib/motion/shotcraft/upstream/references/workbench.md +157 -157
  340. package/lib/motion/shotcraft/upstream/template/TEMPLATE.md +103 -103
  341. package/lib/motion/shotcraft/upstream/template/THEMES.md +44 -44
  342. package/lib/motion/shotcraft/upstream/template/package.json +20 -20
  343. package/lib/motion/shotcraft/upstream/template/remotion.config.ts +6 -6
  344. package/lib/motion/shotcraft/upstream/template/src/Root.tsx +17 -17
  345. package/lib/motion/shotcraft/upstream/template/src/aifl/Caption.tsx +65 -65
  346. package/lib/motion/shotcraft/upstream/template/src/aifl/DigitRoll.tsx +48 -48
  347. package/lib/motion/shotcraft/upstream/template/src/aifl/FlashCut.tsx +24 -24
  348. package/lib/motion/shotcraft/upstream/template/src/aifl/Main.tsx +192 -192
  349. package/lib/motion/shotcraft/upstream/template/src/aifl/PaperTitleCard.tsx +111 -111
  350. package/lib/motion/shotcraft/upstream/template/src/aifl/live/PageCam.tsx +150 -150
  351. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneDetail.tsx +158 -158
  352. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneFlyIn.tsx +468 -468
  353. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOpen.tsx +552 -552
  354. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneOutroLive.tsx +411 -411
  355. package/lib/motion/shotcraft/upstream/template/src/aifl/live/ScenePapers.tsx +200 -200
  356. package/lib/motion/shotcraft/upstream/template/src/aifl/live/SceneWbr.tsx +324 -324
  357. package/lib/motion/shotcraft/upstream/template/src/aifl/live-layout.json +388 -388
  358. package/lib/motion/shotcraft/upstream/template/src/index.ts +4 -4
  359. package/lib/motion/shotcraft/upstream/template/src/themes/ThemedFilm.tsx +7 -7
  360. package/lib/motion/shotcraft/upstream/template/src/themes/manifest.tsx +68 -68
  361. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.json +1 -1
  362. package/lib/motion/shotcraft/upstream/template/src/themes/palette-assets.ts +24 -24
  363. package/lib/motion/shotcraft/upstream/template/src/themes/palettes.json +74 -74
  364. package/lib/motion/shotcraft/upstream/template/src/themes/visual-theme.tsx +91 -91
  365. package/lib/motion/shotcraft/upstream/template/src/workbench.ts +213 -213
  366. package/lib/motion/shotcraft/upstream/template/tsconfig.json +15 -15
  367. package/lib/motion/style-frames.js +306 -306
  368. package/lib/motion/sync.js +214 -214
  369. package/lib/motion-library.js +1 -1
  370. package/lib/motion-project.js +105 -105
  371. package/lib/motion-render-worker.js +174 -174
  372. package/lib/routing/router.js +222 -222
  373. package/lib/routing/vendor/README.md +96 -96
  374. package/lib/routing/vendor/libavoid-routing.js +753 -753
  375. package/lib/routing/vendor/libavoid.min.js +59 -59
  376. package/lib/svg-export.js +1344 -0
  377. package/lib/video-trace-pool.js +128 -128
  378. package/package.json +3 -2
  379. package/LICENSE +0 -4175
@@ -1,652 +1,652 @@
1
- // integration-hub-map v5 —— 批次 14 单点节奏修正:
2
- // 用户意见(逐字)"动作对了,但是需要翻的时候很快,最后快完成的时候变慢下来"
3
- // → rotateY 0→180° 改为快翻+尾段减速:强 ease-out(cubic),前 ~40% 时间
4
- // 完成 ~80% 角度,尾段明显减速缓着陆;仍一次连贯完成、无分段停顿
5
- // (判例:"匀速"=无停顿≠字面 linear,本条已被用户亲自纠正为快翻尾缓)。
6
- // 90° 侧棱时刻随之提前到 ~f28,白热爆发峰值同步前移对齐。其余全保留。
7
- // —— 以下为 v3 说明(结构沿用):
8
- // ① 开头不是"转一个角度",而是页面整个 rotateY 翻转 180° 翻到背面,
9
- // 得到一张新的页面(双面卡:正面=近景旧页,背面=翻正后的新中枢页),
10
- // 翻到侧棱(~90°)时白热爆发吞没画面(对应截图 3/4)。
11
- // ② 五图标光管连上后有"输送感":亮脉冲沿管线方向(图标→中枢)持续
12
- // 循环流动,直到片尾不停。
13
- // 运动结构对照截图:S1 近景正视可读 → S2 翻转中+拉远+泛光起 →
14
- // S3/S4 侧棱白热爆发+图标浮现 → S5/S6 新页转正、光管连入 → S7/S8 稳定输送。
15
- // —— 质感层(改版):
16
- // · 相机推拉/平移从 4 段关键帧(每段 inOut,关键帧处速度归零)改为一条连续曲线,前摇缓、无顿点
17
- // · 面板推拉改走 CSS zoom(布局级缩放),2.05x 近景与落定 1x 文字都按原生分辨率栅格化(Q2);正面旧页换成出版级文档
18
- // · 图标瓷贴弹现带一次过冲、连通后染上本管末端色的霓虹余光;品牌轮把五枚第三方 logo 换成 video-shotcraft 的五种输入
19
- // (页面实拍 / 代码仓库 / 镜头配方卡 / 配乐 / 音效库)线性图标
20
- // · 光管:彩虹管体收细 + 白热芯 + 生长头火花,输送脉冲改成"亮头+拖尾"彗星形;管口接入瞬间一圈小涟漪
21
- // · 背景霓虹框去掉闪烁、减细减淡并随相机做弱视差,颗粒 + 暗角压住大面积暗场
22
- import React, { useId } from 'react';
23
- import { AbsoluteFill, useCurrentFrame, interpolate, Easing } from 'remotion';
24
- import { Grain, Vignette, bezier } from '../../_fixtures/Polish';
25
- import { ShotcraftWordmark } from '../../_fixtures/Brand';
26
-
27
- export const INTEGRATION_HUB_MAP_DURATION = 150; // 前摇 0.5s + 快翻 1.2s + 两拍接入 0.7s + 输送呼吸 ~2.6s
28
-
29
- const mulberry32 = (a: number) => () => {
30
- let t = (a += 0x6d2b79f5);
31
- t = Math.imul(t ^ (t >>> 15), t | 1);
32
- t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
33
- return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
34
- };
35
- const rand = mulberry32(20260718);
36
- const NOISE: number[] = Array.from({ length: 200 }, () => rand());
37
-
38
- const FONT = '-apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", Inter, Arial, sans-serif';
39
- const INK = '#1d1e25', INK2 = '#5f616b', INK3 = '#a0a2ab', HAIR = 'rgba(20,22,28,0.08)';
40
- const ACC = '#5b55c8';
41
-
42
- // 面板推拉走 CSS zoom(布局级缩放)而非 transform scale:任意推拉量下文字都按显示尺寸原生栅格化(Q2)
43
- const PW = 820, PH = 520;
44
-
45
- // ---------- 中枢面板(video-shotcraft 工作区:版式对照截图 1/7,内容换成镜头/渲染的世界) ----------
46
- const LIST: { icon: string; title: string; sub: string }[] = [
47
- { icon: '#4a9fd8', title: 'Launch Film v3', sub: 'Storyboard · 12 shots · 0:45' },
48
- { icon: '#4a9fd8', title: 'Shot 04 · Crash Zoom Punch', sub: 'Recipe card · Camera · 36f' },
49
- { icon: '#34a853', title: 'Pricing Page Captures', sub: 'Page capture · 2x' },
50
- { icon: '#a259ff', title: 'Hero Frame Design', sub: 'Design File · Last Edited' },
51
- { icon: '#f2c744', title: 'Beat Grid · Soundtrack', sub: 'Audio · 120 BPM' },
52
- { icon: '#9a9a98', title: 'Render Archive', sub: 'Archived · In Launch Film' },
53
- { icon: '#c8c8c6', title: 'Render launch film - 1080p', sub: 'In Progress · In Render Queue · Yesterday' },
54
- ];
55
-
56
- // 面板外观:发丝线 + 顶部受光沿 + 投在暗场上的深影 + 一圈随 glow 增强的冷紫环境光(只给主角)
57
- const panelShell = (glow: number): React.CSSProperties => ({
58
- width: PW,
59
- height: PH,
60
- background: 'linear-gradient(180deg, #fdfdfc 0%, #f7f7f5 100%)',
61
- borderRadius: 14,
62
- boxSizing: 'border-box',
63
- fontFamily: FONT,
64
- overflow: 'hidden',
65
- boxShadow: [
66
- 'inset 0 1px 0 rgba(255,255,255,1)',
67
- '0 0 0 1px rgba(255,255,255,0.55)',
68
- '0 2px 6px rgba(0,0,0,0.35)',
69
- '0 40px 90px -24px rgba(0,0,0,0.75)',
70
- `0 0 ${50 + glow * 90}px rgba(236,226,255,${(0.10 + glow * 0.45).toFixed(3)})`,
71
- `0 0 ${150 + glow * 120}px rgba(176,110,255,${(0.16 + glow * 0.28).toFixed(3)})`,
72
- ].join(', '),
73
- });
74
-
75
- const HubPanel: React.FC<{ glow: number }> = ({ glow }) => (
76
- <div style={{ ...panelShell(glow), padding: '26px 30px', display: 'flex', gap: 26 }}>
77
- <div style={{ flex: 2 }}>
78
- {/* 工作区标题 = 产品字标(亮底反色版标志) */}
79
- <ShotcraftWordmark size={25} tone="light" color={INK} markScale={1.3} gap={10} style={{ height: 32 }} />
80
- <div style={{ display: 'flex', gap: 16, marginTop: 12, borderBottom: `1px solid ${HAIR}`, paddingBottom: 8 }}>
81
- {['All', 'Shots', 'Cards', 'Storyboards', 'Renders', 'Audio', 'Captures', 'Exports'].map((t, i) => (
82
- <div key={t} style={{ fontSize: 12, color: i === 0 ? ACC : '#8e9099', fontWeight: i === 0 ? 650 : 450, position: 'relative' }}>
83
- {t}
84
- {i === 0 && <div style={{ position: 'absolute', left: 0, right: 0, bottom: -9, height: 2, borderRadius: 1, background: ACC }} />}
85
- </div>
86
- ))}
87
- </div>
88
- <div style={{ fontSize: 11, color: INK3, marginTop: 14, letterSpacing: '0.04em', fontWeight: 600 }}>RECENT</div>
89
- {LIST.map((it, i) => (
90
- <div key={i} style={{ display: 'flex', gap: 11, alignItems: 'center', marginTop: 12 }}>
91
- <div
92
- style={{
93
- width: 22, height: 22, borderRadius: 6,
94
- background: `linear-gradient(160deg, ${it.icon}, ${it.icon}cc)`,
95
- boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.35), 0 1px 2px rgba(16,18,24,0.12)',
96
- }}
97
- />
98
- <div>
99
- <div style={{ fontSize: 13.5, fontWeight: 600, color: INK, letterSpacing: '-0.005em' }}>{it.title}</div>
100
- <div style={{ fontSize: 11, color: INK3, marginTop: 2 }}>{it.sub}</div>
101
- </div>
102
- </div>
103
- ))}
104
- </div>
105
- <div style={{ flex: 1, borderLeft: `1px solid ${HAIR}`, paddingLeft: 22 }}>
106
- <div
107
- style={{
108
- height: 30, width: 168, borderRadius: 8, marginTop: 4, fontSize: 12, color: INK2, fontWeight: 500,
109
- background: '#fff', boxShadow: `inset 0 0 0 1px rgba(20,22,28,0.14), 0 1px 2px rgba(16,18,24,0.05)`,
110
- display: 'flex', alignItems: 'center', justifyContent: 'center',
111
- }}
112
- >
113
- + Add Shot Filter
114
- </div>
115
- <div style={{ fontSize: 10.5, color: INK3, marginTop: 24, letterSpacing: '0.08em', fontWeight: 600 }}>QUICK FILTERS</div>
116
- {['Assigned to Me', 'Created by Me'].map((t) => (
117
- <div key={t} style={{ fontSize: 13.5, color: INK2, marginTop: 11 }}>{t}</div>
118
- ))}
119
- <div style={{ fontSize: 10.5, color: INK3, marginTop: 24, letterSpacing: '0.08em', fontWeight: 600 }}>RENDER QUEUE</div>
120
- {[['Queued', 3], ['Rendered', 31], ['Archived', 7]].map(([t, n]) => (
121
- <div key={t} style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13.5, color: INK2, marginTop: 11, width: 168 }}>
122
- <span>{t}</span>
123
- <span style={{ color: INK3, fontVariantNumeric: 'tabular-nums', fontSize: 12 }}>{n}</span>
124
- </div>
125
- ))}
126
- </div>
127
- </div>
128
- );
129
-
130
- // ---------- 翻转前的旧页面(正面):另一张页面,翻面后才得到中枢页 ----------
131
- const PARAS = [
132
- 'A 45-second launch film for the new pricing page, cut from real page captures. video-shotcraft drafted the storyboard from twelve shot recipe cards; the beat grid is locked to the soundtrack.',
133
- 'Camera moves are 2.5D push-ins with a crash zoom on the hero. Sound design lands a whoosh on every cut, and the first full render is already queued for review in the workbench.',
134
- ];
135
- const FrontPanel: React.FC<{ glow: number }> = ({ glow }) => (
136
- <div style={{ ...panelShell(glow), padding: '30px 34px' }}>
137
- <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
138
- <div style={{ width: 26, height: 26, borderRadius: 7, background: 'linear-gradient(160deg, #5aaee6, #3d8fcc)', boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.35)' }} />
139
- <div style={{ fontSize: 26, fontWeight: 650, color: INK, letterSpacing: '-0.02em' }}>Launch Film v3</div>
140
- <div style={{ marginLeft: 'auto', fontSize: 11.5, color: INK3 }}>Edited 2h ago</div>
141
- </div>
142
- <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
143
- {['Storyboard', '12 shots', '0:45'].map((t) => (
144
- <div key={t} style={{ fontSize: 11.5, color: INK2, background: '#efeff1', borderRadius: 6, padding: '3px 10px', boxShadow: `inset 0 0 0 1px ${HAIR}` }}>
145
- {t}
146
- </div>
147
- ))}
148
- </div>
149
- <div style={{ height: 1, background: HAIR, marginTop: 18 }} />
150
- {/* 关键字段 */}
151
- <div style={{ display: 'flex', gap: 34, marginTop: 16 }}>
152
- {[['Duration', '0:45'], ['Stage', 'Rendering'], ['Ships', 'Sep 28'], ['Director', 'Dana Whitfield']].map(([k, v]) => (
153
- <div key={k}>
154
- <div style={{ fontSize: 10.5, color: INK3, letterSpacing: '0.06em', fontWeight: 600 }}>{k.toUpperCase()}</div>
155
- <div style={{ fontSize: 15, color: INK, fontWeight: 600, marginTop: 4, fontVariantNumeric: 'tabular-nums' }}>{v}</div>
156
- </div>
157
- ))}
158
- </div>
159
- <div style={{ fontSize: 15, fontWeight: 650, color: INK, marginTop: 22 }}>Summary</div>
160
- {PARAS.map((p, i) => (
161
- <div key={i} style={{ fontSize: 13, lineHeight: 1.62, color: INK2, marginTop: 8, maxWidth: 720 }}>{p}</div>
162
- ))}
163
- <div style={{ fontSize: 15, fontWeight: 650, color: INK, marginTop: 18 }}>Next steps</div>
164
- {['Tune the crash zoom on the hero shot', 'Render the final cut at 1080p'].map((s, i) => (
165
- <div key={s} style={{ display: 'flex', alignItems: 'center', gap: 9, marginTop: 9, fontSize: 13, color: INK2 }}>
166
- <div style={{ width: 13, height: 13, borderRadius: 4, boxShadow: `inset 0 0 0 1.2px ${i ? 'rgba(20,22,28,0.22)' : ACC}`, background: i ? '#fff' : 'rgba(91,85,200,0.1)' }} />
167
- {s}
168
- </div>
169
- ))}
170
- </div>
171
- );
172
-
173
- // ---------- 输入源图标瓷贴(video-shotcraft 自己的五种素材输入,无第三方标志) ----------
174
- // 线性图标:墨色描边 + 琥珀点睛(品牌唯一强调色);48 视框、显示 54px
175
- const Tile: React.FC<{ kind: string; on: number; tint: string }> = ({ kind, on, tint }) => {
176
- const AMBER = '#D3923C';
177
- const ln = { fill: 'none', stroke: INK, strokeWidth: 3, strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const };
178
- const am = { ...ln, stroke: AMBER };
179
- const glyph = (() => {
180
- switch (kind) {
181
- case 'capture':
182
- // 页面实拍:浏览器框 + 内容区里一枚取景角标
183
- return (
184
- <svg width={54} height={54} viewBox="0 0 48 48">
185
- <rect x={5} y={8} width={38} height={32} rx={5} {...ln} />
186
- <path d="M5 16 H43" {...ln} />
187
- <circle cx={10.5} cy={12} r={1.4} fill={INK} />
188
- <circle cx={15} cy={12} r={1.4} fill={INK} />
189
- <circle cx={19.5} cy={12} r={1.4} fill={INK} />
190
- <path d="M15 26 V22 H19 M29 22 H33 V26 M33 30 V34 H29 M19 34 H15 V30" {...am} strokeWidth={2.6} />
191
- </svg>
192
- );
193
- case 'code':
194
- // 代码仓库:</> 尖括号
195
- return (
196
- <svg width={54} height={54} viewBox="0 0 48 48">
197
- <path d="M16 14 L6 24 L16 34" {...ln} strokeWidth={3.4} />
198
- <path d="M32 14 L42 24 L32 34" {...ln} strokeWidth={3.4} />
199
- <path d="M27.5 10 L20.5 38" {...am} strokeWidth={3.4} />
200
- </svg>
201
- );
202
- case 'recipe':
203
- // 镜头配方卡:卡片 + 播放三角 + 两行配方
204
- return (
205
- <svg width={54} height={54} viewBox="0 0 48 48">
206
- <rect x={8} y={5} width={32} height={38} rx={6} {...ln} />
207
- <path d="M20 13 L30 19 L20 25 Z" fill={AMBER} stroke={AMBER} strokeWidth={2} strokeLinejoin="round" />
208
- <path d="M15 32 H33 M15 37 H26" {...ln} strokeWidth={2.6} />
209
- </svg>
210
- );
211
- case 'music':
212
- // 配乐 BGM:波形
213
- return (
214
- <svg width={54} height={54} viewBox="0 0 48 48">
215
- {[6, 14, 24, 32, 18, 26, 10].map((h, k) => (
216
- <path key={k} d={`M${6 + k * 6} ${24 - h / 2} V${24 + h / 2}`} {...(k === 2 || k === 3 ? am : ln)} />
217
- ))}
218
- </svg>
219
- );
220
- default: // sfx:音效库——扬声器 + 声波
221
- return (
222
- <svg width={54} height={54} viewBox="0 0 48 48">
223
- <path d="M7 19 H14 L23 11 V37 L14 29 H7 Z" {...ln} />
224
- <path d="M29 19 A7 7 0 0 1 29 29" {...am} />
225
- <path d="M33.5 14 A13.5 13.5 0 0 1 33.5 34" {...am} />
226
- </svg>
227
- );
228
- }
229
- })();
230
- return (
231
- <div
232
- style={{
233
- width: 112,
234
- height: 112,
235
- borderRadius: 28,
236
- background: 'linear-gradient(180deg, #ffffff 0%, #f1f1f4 100%)',
237
- display: 'flex',
238
- justifyContent: 'center',
239
- alignItems: 'center',
240
- boxShadow: [
241
- 'inset 0 1px 0 rgba(255,255,255,1)',
242
- 'inset 0 -2px 4px rgba(20,22,40,0.08)',
243
- '0 0 0 1px rgba(255,255,255,0.4)',
244
- '0 18px 40px -12px rgba(0,0,0,0.7)',
245
- // 连通后染上本管末端色的霓虹余光
246
- `0 0 ${18 + on * 40}px ${tint}${Math.round(Math.min(1, on) * 0x70).toString(16).padStart(2, '0')}`,
247
- ].join(', '),
248
- }}
249
- >
250
- {glyph}
251
- </div>
252
- );
253
- };
254
-
255
- // ---------- 光管(彩虹渐变霓虹管) ----------
256
- type Pipe = { kind: string; icon: [number, number]; path: string; len: number; tIcon: number; tPipe: number; tint: string };
257
- const PIPES: Pipe[] = [
258
- { kind: 'capture', icon: [452, 262], path: 'M 452 322 L 452 440 Q 452 480 492 480 L 552 480', len: 300, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
259
- { kind: 'code', icon: [252, 612], path: 'M 316 612 L 552 612', len: 240, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
260
- { kind: 'recipe', icon: [992, 178], path: 'M 992 240 L 992 332', len: 92, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
261
- { kind: 'music', icon: [1512, 272], path: 'M 1512 332 L 1512 440 Q 1512 480 1472 480 L 1372 480', len: 290, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
262
- { kind: 'sfx', icon: [1702, 618], path: 'M 1640 618 L 1372 618', len: 270, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
263
- ];
264
- const GROW = 9; // v8(批次 17):用户意见"翻转过来后,5个app同时出现,然后同时连接"——两拍制:五图标 tIcon 统一 52 同帧出现,五管 tPipe 统一 62 同帧连接
265
- const FLOW_SPEED = 4.6; // 输送脉冲速度 px/f
266
- const FLOW_PERIOD = 74; // 脉冲间距(px)
267
-
268
- // 路径上按弧长取点(只含直线段与一段二次曲线,生长头火花用)
269
- const pointAt = (path: string, dist: number): [number, number] => {
270
- const tok = path.match(/[MLQ]|-?[\d.]+/g)!;
271
- let i = 0, cx = 0, cy = 0, rest = dist;
272
- let last: [number, number] = [0, 0];
273
- while (i < tok.length) {
274
- const c = tok[i++];
275
- if (c === 'M') { cx = +tok[i++]; cy = +tok[i++]; last = [cx, cy]; continue; }
276
- if (c === 'L') {
277
- const x = +tok[i++], y = +tok[i++];
278
- const L = Math.hypot(x - cx, y - cy);
279
- if (rest <= L) { const k = rest / L; return [cx + (x - cx) * k, cy + (y - cy) * k]; }
280
- rest -= L; cx = x; cy = y; last = [cx, cy]; continue;
281
- }
282
- if (c === 'Q') {
283
- const qx = +tok[i++], qy = +tok[i++], x = +tok[i++], y = +tok[i++];
284
- const pts: [number, number][] = [];
285
- for (let s = 0; s <= 16; s++) {
286
- const u = s / 16;
287
- pts.push([(1 - u) * (1 - u) * cx + 2 * (1 - u) * u * qx + u * u * x, (1 - u) * (1 - u) * cy + 2 * (1 - u) * u * qy + u * u * y]);
288
- }
289
- for (let s = 1; s < pts.length; s++) {
290
- const L = Math.hypot(pts[s][0] - pts[s - 1][0], pts[s][1] - pts[s - 1][1]);
291
- if (rest <= L) { const k = rest / L; return [pts[s - 1][0] + (pts[s][0] - pts[s - 1][0]) * k, pts[s - 1][1] + (pts[s][1] - pts[s - 1][1]) * k]; }
292
- rest -= L;
293
- }
294
- cx = x; cy = y; last = [cx, cy]; continue;
295
- }
296
- }
297
- return last;
298
- };
299
-
300
- // ---------- 背景霓虹矩形轮廓 ----------
301
- const RECTS = Array.from({ length: 9 }, (_, i) => ({
302
- x: [150, 660, 1740, 250, 1150, 700, 1660, 90, 1330][i],
303
- y: [255, 355, 545, 850, 935, 985, 830, 555, 760][i],
304
- w: 90 + NOISE[i * 3] * 160,
305
- h: 60 + NOISE[i * 3 + 1] * 70,
306
- hue: [265, 285, 300, 255, 275, 210, 320, 240, 40][i],
307
- ph: NOISE[i * 3 + 2] * Math.PI * 2,
308
- }));
309
-
310
- // 相机:一条连续曲线(前摇段自然很慢,无关键帧顿点)
311
- const CAM = bezier(0.55, 0, 0.18, 1);
312
-
313
- export const IntegrationHubMap: React.FC = () => {
314
- const frame = useCurrentFrame();
315
- // 滤镜/渐变 ID 按实例生成,多实例同场不串引(useId 的 «:» 在 url() 里非法,需清洗)
316
- const uid = useId().replace(/[^a-zA-Z0-9]/g, '');
317
-
318
- // --- 相机/面板轨迹:近景正视旧页 → 整体翻转 180°(翻到背面=新页)+ 拉远落定 ---
319
- const cam = CAM(Math.min(1, Math.max(0, frame / 96)));
320
- const zoom = 2.05 + (1.0 - 2.05) * cam;
321
- // v6(批次 15):用户意见"翻转再快1倍"——翻面窗口 f14–84(70 帧)
322
- // 压半到 f14–49(35 帧),快翻+尾段减速曲线形状保持;
323
- // 90° 侧棱相应提前到 ~f21.2(easeOut=0.5 → t≈0.206)。
324
- const rotY = interpolate(frame, [14, 49], [0, 180], {
325
- extrapolateLeft: 'clamp',
326
- extrapolateRight: 'clamp',
327
- easing: Easing.out(Easing.cubic),
328
- });
329
- const panX = 130 + (0 - 130) * cam;
330
- const panY = 120 + (25 - 120) * cam;
331
-
332
- // v6:用户意见"中间不需要长时间的光晕,翻到中间闪一下就行"——
333
- // 长光晕平台删除,改为 90° 侧棱时刻(~f21)2 帧脉冲亮闪即回落
334
- const bloom = interpolate(frame, [19, 21, 23, 27], [0, 1, 0.25, 0], {
335
- extrapolateLeft: 'clamp',
336
- extrapolateRight: 'clamp',
337
- });
338
- const noise = NOISE[Math.min(frame, NOISE.length - 1)];
339
-
340
- // 全连通后呼吸
341
- const allOn = Math.max(...PIPES.map((p) => p.tPipe)) + GROW;
342
- const breathe = frame > allOn ? 0.5 + 0.5 * Math.sin((frame - allOn) * 0.16) : 0;
343
- const panelGlow = bloom * 1.1 + breathe * 0.16;
344
-
345
- // 星图元素(图标/光管/矩形)整体可见度
346
- const mapIn = interpolate(frame, [34, 60], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' });
347
- // 背景层弱视差:跟随相机 18% 的位移与 10% 的推拉
348
- const bgPar = `translate(${(panX * 0.18).toFixed(2)}px, ${(panY * 0.18).toFixed(2)}px) scale(${(1 + (zoom - 1) * 0.1).toFixed(4)})`;
349
-
350
- return (
351
- <AbsoluteFill style={{ background: '#09080e' }}>
352
- {/* 暗紫底:中心冷紫柔光 + 左下品红余光 */}
353
- <AbsoluteFill
354
- style={{
355
- background:
356
- 'radial-gradient(ellipse 60% 55% at 50% 50%, rgba(98,58,160,0.28), transparent 70%), radial-gradient(ellipse 45% 40% at 16% 80%, rgba(150,56,128,0.13), transparent 70%), radial-gradient(ellipse 40% 35% at 86% 18%, rgba(70,90,190,0.10), transparent 70%)',
357
- }}
358
- />
359
-
360
- {/* 背景霓虹矩形轮廓:细、淡、轻微失焦,作远景衬场 */}
361
- <AbsoluteFill style={{ transform: bgPar, transformOrigin: '50% 50%' }}>
362
- {RECTS.map((r, i) => {
363
- const on = interpolate(frame, [36 + i * 4, 56 + i * 4], [0, 1], {
364
- extrapolateLeft: 'clamp',
365
- extrapolateRight: 'clamp',
366
- easing: Easing.out(Easing.cubic),
367
- });
368
- const settle = interpolate(frame, [90, 120], [1, 0.62], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' });
369
- const a = on * settle;
370
- return (
371
- <div
372
- key={i}
373
- style={{
374
- position: 'absolute',
375
- left: r.x,
376
- top: r.y,
377
- width: r.w,
378
- height: r.h,
379
- borderRadius: 12,
380
- border: `1.5px solid hsla(${r.hue} 85% 72% / ${(0.5 * a).toFixed(3)})`,
381
- boxShadow: `0 0 14px hsla(${r.hue} 90% 62% / ${(0.32 * a).toFixed(3)}), inset 0 0 12px hsla(${r.hue} 90% 62% / ${(0.14 * a).toFixed(3)})`,
382
- filter: 'blur(0.8px)',
383
- }}
384
- />
385
- );
386
- })}
387
- </AbsoluteFill>
388
-
389
- {/* 光管层 */}
390
- <svg width={1920} height={1080} style={{ position: 'absolute', inset: 0, opacity: mapIn }}>
391
- <defs>
392
- {/* 每条管一个 userSpaceOnUse 渐变(沿管起终点),彩虹沿管线方向铺开。
393
- objectBoundingBox 在纯水平/垂直线上宽或高为 0 会禁用 paint,必须用户坐标。 */}
394
- {PIPES.map((p, i) => {
395
- const nums = p.path.match(/-?[\d.]+/g)!.map(Number);
396
- const [x1, y1] = [nums[0], nums[1]];
397
- const [x2, y2] = [nums[nums.length - 2], nums[nums.length - 1]];
398
- return (
399
- <linearGradient key={i} id={`rainbow-${uid}-${i}`} gradientUnits="userSpaceOnUse" x1={x1} y1={y1} x2={x2} y2={y2}>
400
- <stop offset="0%" stopColor="#ffe14d" />
401
- <stop offset="28%" stopColor="#ff8a5a" />
402
- <stop offset="52%" stopColor="#ff5ad0" />
403
- <stop offset="76%" stopColor="#b46bff" />
404
- <stop offset="100%" stopColor="#5ad0ff" />
405
- </linearGradient>
406
- );
407
- })}
408
- {/* userSpaceOnUse:纯水平/垂直直线管的 bbox 为零,百分比滤镜区域会
409
- 坍缩成 0 导致整条管不渲染(左 / 上中 / 右三条直管消失) */}
410
- <filter id={`pipeGlow-${uid}`} filterUnits="userSpaceOnUse" x="0" y="0" width="1920" height="1080">
411
- <feGaussianBlur stdDeviation="9" result="b" />
412
- <feMerge>
413
- <feMergeNode in="b" />
414
- <feMergeNode in="SourceGraphic" />
415
- </feMerge>
416
- </filter>
417
- <filter id={`soft-${uid}`} filterUnits="userSpaceOnUse" x="0" y="0" width="1920" height="1080">
418
- <feGaussianBlur stdDeviation="3.5" />
419
- </filter>
420
- </defs>
421
- {PIPES.map((p, i) => {
422
- const grow = interpolate(frame, [p.tPipe, p.tPipe + GROW], [0, 1], {
423
- extrapolateLeft: 'clamp',
424
- extrapolateRight: 'clamp',
425
- easing: Easing.out(Easing.quad),
426
- });
427
- if (grow <= 0) return null;
428
- const dashOn = p.len * grow;
429
- const pulse = frame > allOn ? 0.84 + 0.16 * Math.sin((frame - allOn) * 0.16 + i) : 1;
430
- // 输送感:亮脉冲沿管线方向(图标→中枢)持续循环流动
431
- const flowOffset = -((frame - p.tPipe) * FLOW_SPEED + i * 37);
432
- const flowIn = interpolate(frame, [p.tPipe + GROW, p.tPipe + GROW + 8], [0, 1], {
433
- extrapolateLeft: 'clamp',
434
- extrapolateRight: 'clamp',
435
- });
436
- const head = pointAt(p.path, dashOn);
437
- const growing = grow < 1;
438
- return (
439
- <g key={i}>
440
- <g filter={`url(#pipeGlow-${uid})`}>
441
- <path
442
- d={p.path}
443
- fill="none"
444
- stroke={`url(#rainbow-${uid}-${i})`}
445
- strokeWidth={12}
446
- strokeLinecap="round"
447
- strokeDasharray={`${dashOn} ${p.len + 60}`}
448
- opacity={0.9 * pulse}
449
- />
450
- </g>
451
- {/* 白热芯:细而亮,管体读作"发光的管"而不是色带 */}
452
- <path
453
- d={p.path}
454
- fill="none"
455
- stroke="rgba(255,250,255,0.92)"
456
- strokeWidth={3}
457
- strokeLinecap="round"
458
- strokeDasharray={`${dashOn} ${p.len + 60}`}
459
- opacity={0.8 * pulse}
460
- />
461
- {/* 生长头火花:只在 9f 生长期内出现 */}
462
- {growing && (
463
- <>
464
- <circle cx={head[0]} cy={head[1]} r={16} fill="rgba(255,240,255,0.5)" filter={`url(#soft-${uid})`} />
465
- <circle cx={head[0]} cy={head[1]} r={5.5} fill="#fff" />
466
- </>
467
- )}
468
- {grow >= 1 && flowIn > 0 && (
469
- <>
470
- {/* 彗星拖尾:较长、较暗,柔化 */}
471
- <path
472
- d={p.path}
473
- fill="none"
474
- stroke="rgba(255,255,255,0.7)"
475
- strokeWidth={8}
476
- strokeLinecap="round"
477
- strokeDasharray={`26 ${FLOW_PERIOD - 26}`}
478
- strokeDashoffset={flowOffset}
479
- opacity={0.38 * flowIn}
480
- filter={`url(#soft-${uid})`}
481
- />
482
- {/* 彗星亮头:位于拖尾前端(朝中枢方向) */}
483
- <path
484
- d={p.path}
485
- fill="none"
486
- stroke="#ffffff"
487
- strokeWidth={6}
488
- strokeLinecap="round"
489
- strokeDasharray={`7 ${FLOW_PERIOD - 7}`}
490
- strokeDashoffset={flowOffset - 19}
491
- opacity={0.95 * flowIn}
492
- />
493
- </>
494
- )}
495
- </g>
496
- );
497
- })}
498
- </svg>
499
-
500
- {/* 图标瓷贴:同帧弹现(一次过冲),连通后染色余光 */}
501
- {PIPES.map((p, i) => {
502
- const appear = interpolate(frame, [p.tIcon, p.tIcon + 13], [0, 1], {
503
- extrapolateLeft: 'clamp',
504
- extrapolateRight: 'clamp',
505
- });
506
- if (appear <= 0) return null;
507
- const pop = Easing.bezier(0.34, 1.5, 0.64, 1)(appear); // 过冲 ~8% 再回落
508
- const on = interpolate(frame, [p.tPipe + GROW - 2, p.tPipe + GROW + 8], [0, 1], {
509
- extrapolateLeft: 'clamp',
510
- extrapolateRight: 'clamp',
511
- easing: Easing.out(Easing.cubic),
512
- });
513
- return (
514
- <div
515
- key={i}
516
- style={{
517
- position: 'absolute',
518
- left: p.icon[0] - 56,
519
- top: p.icon[1] - 56,
520
- opacity: Math.min(1, appear * 2.2),
521
- transform: `translateY(${((1 - pop) * 22).toFixed(2)}px) scale(${(0.72 + 0.28 * pop).toFixed(4)})`,
522
- }}
523
- >
524
- <Tile kind={p.kind} tint={p.tint} on={on * (frame > allOn ? 0.82 + 0.18 * breathe : 1)} />
525
- </div>
526
- );
527
- })}
528
-
529
- {/* 中枢面板:双面卡整体翻转 180°(正面旧页 → 背面新中枢页) */}
530
- <AbsoluteFill style={{ justifyContent: 'center', alignItems: 'center', perspective: 1500 }}>
531
- <div
532
- style={{
533
- transform: `translate(${panX.toFixed(2)}px, ${panY.toFixed(2)}px) rotateY(${rotY.toFixed(3)}deg)`,
534
- position: 'relative',
535
- transformStyle: 'preserve-3d',
536
- width: PW * zoom,
537
- height: PH * zoom,
538
- flexShrink: 0,
539
- }}
540
- >
541
- {/* 正面:翻转前的旧页面 */}
542
- <div style={{ position: 'absolute', inset: 0, backfaceVisibility: 'hidden' }}>
543
- <div style={{ zoom }}>
544
- <FrontPanel glow={panelGlow} />
545
- </div>
546
- </div>
547
- {/* 背面:翻正后得到的新中枢页(预转 180° 使翻完时朝向镜头且不镜像) */}
548
- <div style={{ position: 'absolute', inset: 0, backfaceVisibility: 'hidden', transform: 'rotateY(180deg)' }}>
549
- <div style={{ zoom }}>
550
- <HubPanel glow={panelGlow} />
551
- </div>
552
- </div>
553
- {/* 面板过曝罩:爆发期盖白 */}
554
- <div
555
- style={{
556
- position: 'absolute',
557
- inset: -6 * zoom,
558
- borderRadius: 18 * zoom,
559
- background: '#ffffff',
560
- opacity: Math.min(0.96, bloom * 1.05),
561
- filter: `blur(${5 * zoom}px)`,
562
- pointerEvents: 'none',
563
- transform: rotY > 90 ? 'rotateY(180deg) translateZ(1px)' : 'translateZ(1px)',
564
- backfaceVisibility: 'hidden',
565
- }}
566
- />
567
- </div>
568
- </AbsoluteFill>
569
-
570
- {/* 管口接入:五管同帧抵达中枢边缘时各起一圈小涟漪(在面板之上) */}
571
- {PIPES.map((p, i) => {
572
- const nums = p.path.match(/-?[\d.]+/g)!.map(Number);
573
- const [ex, ey] = [nums[nums.length - 2], nums[nums.length - 1]];
574
- const k = interpolate(frame, [p.tPipe + GROW - 1, p.tPipe + GROW + 13], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' });
575
- if (k <= 0 || k >= 1) return null;
576
- const r = 6 + Easing.out(Easing.cubic)(k) * 26;
577
- return (
578
- <div
579
- key={`port-${i}`}
580
- style={{
581
- position: 'absolute', left: ex - r, top: ey - r, width: r * 2, height: r * 2, borderRadius: '50%',
582
- border: '2px solid rgba(255,255,255,0.9)', opacity: (1 - k) * 0.85,
583
- boxShadow: '0 0 12px rgba(255,200,255,0.6)',
584
- }}
585
- />
586
- );
587
- })}
588
-
589
- {/* 全屏白热眩光(S3/S4):白核+品红/粉翼+青蓝斑 */}
590
- {bloom > 0.02 && (
591
- <AbsoluteFill style={{ pointerEvents: 'none' }}>
592
- <div
593
- style={{
594
- position: 'absolute',
595
- left: 300,
596
- top: 60,
597
- width: 1100,
598
- height: 900,
599
- background:
600
- 'radial-gradient(closest-side, rgba(255,255,255,0.98), rgba(255,235,255,0.75) 42%, rgba(255,120,230,0.4) 68%, transparent 88%)',
601
- filter: 'blur(26px)',
602
- opacity: Math.min(1, bloom * (0.94 + 0.06 * noise)),
603
- }}
604
- />
605
- <div
606
- style={{
607
- position: 'absolute',
608
- left: 1150,
609
- top: 150,
610
- width: 700,
611
- height: 620,
612
- background: 'radial-gradient(closest-side, rgba(255,90,208,0.85), rgba(200,70,255,0.4) 60%, transparent 85%)',
613
- filter: 'blur(34px)',
614
- opacity: bloom * 0.9,
615
- }}
616
- />
617
- <div
618
- style={{
619
- position: 'absolute',
620
- left: 40,
621
- top: 480,
622
- width: 620,
623
- height: 520,
624
- background: 'radial-gradient(closest-side, rgba(140,210,255,0.8), rgba(90,120,255,0.35) 60%, transparent 85%)',
625
- filter: 'blur(30px)',
626
- opacity: bloom * 0.85,
627
- }}
628
- />
629
- {/* 横向紫白光痕(S2 左侧光痕),只随侧棱闪出现 */}
630
- <div
631
- style={{
632
- position: 'absolute',
633
- left: 30,
634
- top: 700,
635
- width: 420,
636
- height: 40,
637
- borderRadius: 20,
638
- background: 'linear-gradient(90deg, rgba(255,255,255,0.9), rgba(170,90,255,0.7), transparent)',
639
- filter: 'blur(16px)',
640
- opacity: interpolate(frame, [20, 34, 70, 92], [0, 0.9, 0.5, 0], {
641
- extrapolateLeft: 'clamp',
642
- extrapolateRight: 'clamp',
643
- }),
644
- }}
645
- />
646
- </AbsoluteFill>
647
- )}
648
- <Vignette strength={0.55} inner={0.42} color="#040308" />
649
- <Grain opacity={0.07} blend="soft-light" />
650
- </AbsoluteFill>
651
- );
652
- };
1
+ // integration-hub-map v5 —— 批次 14 单点节奏修正:
2
+ // 用户意见(逐字)"动作对了,但是需要翻的时候很快,最后快完成的时候变慢下来"
3
+ // → rotateY 0→180° 改为快翻+尾段减速:强 ease-out(cubic),前 ~40% 时间
4
+ // 完成 ~80% 角度,尾段明显减速缓着陆;仍一次连贯完成、无分段停顿
5
+ // (判例:"匀速"=无停顿≠字面 linear,本条已被用户亲自纠正为快翻尾缓)。
6
+ // 90° 侧棱时刻随之提前到 ~f28,白热爆发峰值同步前移对齐。其余全保留。
7
+ // —— 以下为 v3 说明(结构沿用):
8
+ // ① 开头不是"转一个角度",而是页面整个 rotateY 翻转 180° 翻到背面,
9
+ // 得到一张新的页面(双面卡:正面=近景旧页,背面=翻正后的新中枢页),
10
+ // 翻到侧棱(~90°)时白热爆发吞没画面(对应截图 3/4)。
11
+ // ② 五图标光管连上后有"输送感":亮脉冲沿管线方向(图标→中枢)持续
12
+ // 循环流动,直到片尾不停。
13
+ // 运动结构对照截图:S1 近景正视可读 → S2 翻转中+拉远+泛光起 →
14
+ // S3/S4 侧棱白热爆发+图标浮现 → S5/S6 新页转正、光管连入 → S7/S8 稳定输送。
15
+ // —— 质感层(改版):
16
+ // · 相机推拉/平移从 4 段关键帧(每段 inOut,关键帧处速度归零)改为一条连续曲线,前摇缓、无顿点
17
+ // · 面板推拉改走 CSS zoom(布局级缩放),2.05x 近景与落定 1x 文字都按原生分辨率栅格化(Q2);正面旧页换成出版级文档
18
+ // · 图标瓷贴弹现带一次过冲、连通后染上本管末端色的霓虹余光;品牌轮把五枚第三方 logo 换成 video-shotcraft 的五种输入
19
+ // (页面实拍 / 代码仓库 / 镜头配方卡 / 配乐 / 音效库)线性图标
20
+ // · 光管:彩虹管体收细 + 白热芯 + 生长头火花,输送脉冲改成"亮头+拖尾"彗星形;管口接入瞬间一圈小涟漪
21
+ // · 背景霓虹框去掉闪烁、减细减淡并随相机做弱视差,颗粒 + 暗角压住大面积暗场
22
+ import React, { useId } from 'react';
23
+ import { AbsoluteFill, useCurrentFrame, interpolate, Easing } from 'remotion';
24
+ import { Grain, Vignette, bezier } from '../../_fixtures/Polish';
25
+ import { ShotcraftWordmark } from '../../_fixtures/Brand';
26
+
27
+ export const INTEGRATION_HUB_MAP_DURATION = 150; // 前摇 0.5s + 快翻 1.2s + 两拍接入 0.7s + 输送呼吸 ~2.6s
28
+
29
+ const mulberry32 = (a: number) => () => {
30
+ let t = (a += 0x6d2b79f5);
31
+ t = Math.imul(t ^ (t >>> 15), t | 1);
32
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
33
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
34
+ };
35
+ const rand = mulberry32(20260718);
36
+ const NOISE: number[] = Array.from({ length: 200 }, () => rand());
37
+
38
+ const FONT = '-apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", Inter, Arial, sans-serif';
39
+ const INK = '#1d1e25', INK2 = '#5f616b', INK3 = '#a0a2ab', HAIR = 'rgba(20,22,28,0.08)';
40
+ const ACC = '#5b55c8';
41
+
42
+ // 面板推拉走 CSS zoom(布局级缩放)而非 transform scale:任意推拉量下文字都按显示尺寸原生栅格化(Q2)
43
+ const PW = 820, PH = 520;
44
+
45
+ // ---------- 中枢面板(video-shotcraft 工作区:版式对照截图 1/7,内容换成镜头/渲染的世界) ----------
46
+ const LIST: { icon: string; title: string; sub: string }[] = [
47
+ { icon: '#4a9fd8', title: 'Launch Film v3', sub: 'Storyboard · 12 shots · 0:45' },
48
+ { icon: '#4a9fd8', title: 'Shot 04 · Crash Zoom Punch', sub: 'Recipe card · Camera · 36f' },
49
+ { icon: '#34a853', title: 'Pricing Page Captures', sub: 'Page capture · 2x' },
50
+ { icon: '#a259ff', title: 'Hero Frame Design', sub: 'Design File · Last Edited' },
51
+ { icon: '#f2c744', title: 'Beat Grid · Soundtrack', sub: 'Audio · 120 BPM' },
52
+ { icon: '#9a9a98', title: 'Render Archive', sub: 'Archived · In Launch Film' },
53
+ { icon: '#c8c8c6', title: 'Render launch film - 1080p', sub: 'In Progress · In Render Queue · Yesterday' },
54
+ ];
55
+
56
+ // 面板外观:发丝线 + 顶部受光沿 + 投在暗场上的深影 + 一圈随 glow 增强的冷紫环境光(只给主角)
57
+ const panelShell = (glow: number): React.CSSProperties => ({
58
+ width: PW,
59
+ height: PH,
60
+ background: 'linear-gradient(180deg, #fdfdfc 0%, #f7f7f5 100%)',
61
+ borderRadius: 14,
62
+ boxSizing: 'border-box',
63
+ fontFamily: FONT,
64
+ overflow: 'hidden',
65
+ boxShadow: [
66
+ 'inset 0 1px 0 rgba(255,255,255,1)',
67
+ '0 0 0 1px rgba(255,255,255,0.55)',
68
+ '0 2px 6px rgba(0,0,0,0.35)',
69
+ '0 40px 90px -24px rgba(0,0,0,0.75)',
70
+ `0 0 ${50 + glow * 90}px rgba(236,226,255,${(0.10 + glow * 0.45).toFixed(3)})`,
71
+ `0 0 ${150 + glow * 120}px rgba(176,110,255,${(0.16 + glow * 0.28).toFixed(3)})`,
72
+ ].join(', '),
73
+ });
74
+
75
+ const HubPanel: React.FC<{ glow: number }> = ({ glow }) => (
76
+ <div style={{ ...panelShell(glow), padding: '26px 30px', display: 'flex', gap: 26 }}>
77
+ <div style={{ flex: 2 }}>
78
+ {/* 工作区标题 = 产品字标(亮底反色版标志) */}
79
+ <ShotcraftWordmark size={25} tone="light" color={INK} markScale={1.3} gap={10} style={{ height: 32 }} />
80
+ <div style={{ display: 'flex', gap: 16, marginTop: 12, borderBottom: `1px solid ${HAIR}`, paddingBottom: 8 }}>
81
+ {['All', 'Shots', 'Cards', 'Storyboards', 'Renders', 'Audio', 'Captures', 'Exports'].map((t, i) => (
82
+ <div key={t} style={{ fontSize: 12, color: i === 0 ? ACC : '#8e9099', fontWeight: i === 0 ? 650 : 450, position: 'relative' }}>
83
+ {t}
84
+ {i === 0 && <div style={{ position: 'absolute', left: 0, right: 0, bottom: -9, height: 2, borderRadius: 1, background: ACC }} />}
85
+ </div>
86
+ ))}
87
+ </div>
88
+ <div style={{ fontSize: 11, color: INK3, marginTop: 14, letterSpacing: '0.04em', fontWeight: 600 }}>RECENT</div>
89
+ {LIST.map((it, i) => (
90
+ <div key={i} style={{ display: 'flex', gap: 11, alignItems: 'center', marginTop: 12 }}>
91
+ <div
92
+ style={{
93
+ width: 22, height: 22, borderRadius: 6,
94
+ background: `linear-gradient(160deg, ${it.icon}, ${it.icon}cc)`,
95
+ boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.35), 0 1px 2px rgba(16,18,24,0.12)',
96
+ }}
97
+ />
98
+ <div>
99
+ <div style={{ fontSize: 13.5, fontWeight: 600, color: INK, letterSpacing: '-0.005em' }}>{it.title}</div>
100
+ <div style={{ fontSize: 11, color: INK3, marginTop: 2 }}>{it.sub}</div>
101
+ </div>
102
+ </div>
103
+ ))}
104
+ </div>
105
+ <div style={{ flex: 1, borderLeft: `1px solid ${HAIR}`, paddingLeft: 22 }}>
106
+ <div
107
+ style={{
108
+ height: 30, width: 168, borderRadius: 8, marginTop: 4, fontSize: 12, color: INK2, fontWeight: 500,
109
+ background: '#fff', boxShadow: `inset 0 0 0 1px rgba(20,22,28,0.14), 0 1px 2px rgba(16,18,24,0.05)`,
110
+ display: 'flex', alignItems: 'center', justifyContent: 'center',
111
+ }}
112
+ >
113
+ + Add Shot Filter
114
+ </div>
115
+ <div style={{ fontSize: 10.5, color: INK3, marginTop: 24, letterSpacing: '0.08em', fontWeight: 600 }}>QUICK FILTERS</div>
116
+ {['Assigned to Me', 'Created by Me'].map((t) => (
117
+ <div key={t} style={{ fontSize: 13.5, color: INK2, marginTop: 11 }}>{t}</div>
118
+ ))}
119
+ <div style={{ fontSize: 10.5, color: INK3, marginTop: 24, letterSpacing: '0.08em', fontWeight: 600 }}>RENDER QUEUE</div>
120
+ {[['Queued', 3], ['Rendered', 31], ['Archived', 7]].map(([t, n]) => (
121
+ <div key={t} style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13.5, color: INK2, marginTop: 11, width: 168 }}>
122
+ <span>{t}</span>
123
+ <span style={{ color: INK3, fontVariantNumeric: 'tabular-nums', fontSize: 12 }}>{n}</span>
124
+ </div>
125
+ ))}
126
+ </div>
127
+ </div>
128
+ );
129
+
130
+ // ---------- 翻转前的旧页面(正面):另一张页面,翻面后才得到中枢页 ----------
131
+ const PARAS = [
132
+ 'A 45-second launch film for the new pricing page, cut from real page captures. video-shotcraft drafted the storyboard from twelve shot recipe cards; the beat grid is locked to the soundtrack.',
133
+ 'Camera moves are 2.5D push-ins with a crash zoom on the hero. Sound design lands a whoosh on every cut, and the first full render is already queued for review in the workbench.',
134
+ ];
135
+ const FrontPanel: React.FC<{ glow: number }> = ({ glow }) => (
136
+ <div style={{ ...panelShell(glow), padding: '30px 34px' }}>
137
+ <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
138
+ <div style={{ width: 26, height: 26, borderRadius: 7, background: 'linear-gradient(160deg, #5aaee6, #3d8fcc)', boxShadow: 'inset 0 1px 0 rgba(255,255,255,0.35)' }} />
139
+ <div style={{ fontSize: 26, fontWeight: 650, color: INK, letterSpacing: '-0.02em' }}>Launch Film v3</div>
140
+ <div style={{ marginLeft: 'auto', fontSize: 11.5, color: INK3 }}>Edited 2h ago</div>
141
+ </div>
142
+ <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
143
+ {['Storyboard', '12 shots', '0:45'].map((t) => (
144
+ <div key={t} style={{ fontSize: 11.5, color: INK2, background: '#efeff1', borderRadius: 6, padding: '3px 10px', boxShadow: `inset 0 0 0 1px ${HAIR}` }}>
145
+ {t}
146
+ </div>
147
+ ))}
148
+ </div>
149
+ <div style={{ height: 1, background: HAIR, marginTop: 18 }} />
150
+ {/* 关键字段 */}
151
+ <div style={{ display: 'flex', gap: 34, marginTop: 16 }}>
152
+ {[['Duration', '0:45'], ['Stage', 'Rendering'], ['Ships', 'Sep 28'], ['Director', 'Dana Whitfield']].map(([k, v]) => (
153
+ <div key={k}>
154
+ <div style={{ fontSize: 10.5, color: INK3, letterSpacing: '0.06em', fontWeight: 600 }}>{k.toUpperCase()}</div>
155
+ <div style={{ fontSize: 15, color: INK, fontWeight: 600, marginTop: 4, fontVariantNumeric: 'tabular-nums' }}>{v}</div>
156
+ </div>
157
+ ))}
158
+ </div>
159
+ <div style={{ fontSize: 15, fontWeight: 650, color: INK, marginTop: 22 }}>Summary</div>
160
+ {PARAS.map((p, i) => (
161
+ <div key={i} style={{ fontSize: 13, lineHeight: 1.62, color: INK2, marginTop: 8, maxWidth: 720 }}>{p}</div>
162
+ ))}
163
+ <div style={{ fontSize: 15, fontWeight: 650, color: INK, marginTop: 18 }}>Next steps</div>
164
+ {['Tune the crash zoom on the hero shot', 'Render the final cut at 1080p'].map((s, i) => (
165
+ <div key={s} style={{ display: 'flex', alignItems: 'center', gap: 9, marginTop: 9, fontSize: 13, color: INK2 }}>
166
+ <div style={{ width: 13, height: 13, borderRadius: 4, boxShadow: `inset 0 0 0 1.2px ${i ? 'rgba(20,22,28,0.22)' : ACC}`, background: i ? '#fff' : 'rgba(91,85,200,0.1)' }} />
167
+ {s}
168
+ </div>
169
+ ))}
170
+ </div>
171
+ );
172
+
173
+ // ---------- 输入源图标瓷贴(video-shotcraft 自己的五种素材输入,无第三方标志) ----------
174
+ // 线性图标:墨色描边 + 琥珀点睛(品牌唯一强调色);48 视框、显示 54px
175
+ const Tile: React.FC<{ kind: string; on: number; tint: string }> = ({ kind, on, tint }) => {
176
+ const AMBER = '#D3923C';
177
+ const ln = { fill: 'none', stroke: INK, strokeWidth: 3, strokeLinecap: 'round' as const, strokeLinejoin: 'round' as const };
178
+ const am = { ...ln, stroke: AMBER };
179
+ const glyph = (() => {
180
+ switch (kind) {
181
+ case 'capture':
182
+ // 页面实拍:浏览器框 + 内容区里一枚取景角标
183
+ return (
184
+ <svg width={54} height={54} viewBox="0 0 48 48">
185
+ <rect x={5} y={8} width={38} height={32} rx={5} {...ln} />
186
+ <path d="M5 16 H43" {...ln} />
187
+ <circle cx={10.5} cy={12} r={1.4} fill={INK} />
188
+ <circle cx={15} cy={12} r={1.4} fill={INK} />
189
+ <circle cx={19.5} cy={12} r={1.4} fill={INK} />
190
+ <path d="M15 26 V22 H19 M29 22 H33 V26 M33 30 V34 H29 M19 34 H15 V30" {...am} strokeWidth={2.6} />
191
+ </svg>
192
+ );
193
+ case 'code':
194
+ // 代码仓库:</> 尖括号
195
+ return (
196
+ <svg width={54} height={54} viewBox="0 0 48 48">
197
+ <path d="M16 14 L6 24 L16 34" {...ln} strokeWidth={3.4} />
198
+ <path d="M32 14 L42 24 L32 34" {...ln} strokeWidth={3.4} />
199
+ <path d="M27.5 10 L20.5 38" {...am} strokeWidth={3.4} />
200
+ </svg>
201
+ );
202
+ case 'recipe':
203
+ // 镜头配方卡:卡片 + 播放三角 + 两行配方
204
+ return (
205
+ <svg width={54} height={54} viewBox="0 0 48 48">
206
+ <rect x={8} y={5} width={32} height={38} rx={6} {...ln} />
207
+ <path d="M20 13 L30 19 L20 25 Z" fill={AMBER} stroke={AMBER} strokeWidth={2} strokeLinejoin="round" />
208
+ <path d="M15 32 H33 M15 37 H26" {...ln} strokeWidth={2.6} />
209
+ </svg>
210
+ );
211
+ case 'music':
212
+ // 配乐 BGM:波形
213
+ return (
214
+ <svg width={54} height={54} viewBox="0 0 48 48">
215
+ {[6, 14, 24, 32, 18, 26, 10].map((h, k) => (
216
+ <path key={k} d={`M${6 + k * 6} ${24 - h / 2} V${24 + h / 2}`} {...(k === 2 || k === 3 ? am : ln)} />
217
+ ))}
218
+ </svg>
219
+ );
220
+ default: // sfx:音效库——扬声器 + 声波
221
+ return (
222
+ <svg width={54} height={54} viewBox="0 0 48 48">
223
+ <path d="M7 19 H14 L23 11 V37 L14 29 H7 Z" {...ln} />
224
+ <path d="M29 19 A7 7 0 0 1 29 29" {...am} />
225
+ <path d="M33.5 14 A13.5 13.5 0 0 1 33.5 34" {...am} />
226
+ </svg>
227
+ );
228
+ }
229
+ })();
230
+ return (
231
+ <div
232
+ style={{
233
+ width: 112,
234
+ height: 112,
235
+ borderRadius: 28,
236
+ background: 'linear-gradient(180deg, #ffffff 0%, #f1f1f4 100%)',
237
+ display: 'flex',
238
+ justifyContent: 'center',
239
+ alignItems: 'center',
240
+ boxShadow: [
241
+ 'inset 0 1px 0 rgba(255,255,255,1)',
242
+ 'inset 0 -2px 4px rgba(20,22,40,0.08)',
243
+ '0 0 0 1px rgba(255,255,255,0.4)',
244
+ '0 18px 40px -12px rgba(0,0,0,0.7)',
245
+ // 连通后染上本管末端色的霓虹余光
246
+ `0 0 ${18 + on * 40}px ${tint}${Math.round(Math.min(1, on) * 0x70).toString(16).padStart(2, '0')}`,
247
+ ].join(', '),
248
+ }}
249
+ >
250
+ {glyph}
251
+ </div>
252
+ );
253
+ };
254
+
255
+ // ---------- 光管(彩虹渐变霓虹管) ----------
256
+ type Pipe = { kind: string; icon: [number, number]; path: string; len: number; tIcon: number; tPipe: number; tint: string };
257
+ const PIPES: Pipe[] = [
258
+ { kind: 'capture', icon: [452, 262], path: 'M 452 322 L 452 440 Q 452 480 492 480 L 552 480', len: 300, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
259
+ { kind: 'code', icon: [252, 612], path: 'M 316 612 L 552 612', len: 240, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
260
+ { kind: 'recipe', icon: [992, 178], path: 'M 992 240 L 992 332', len: 92, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
261
+ { kind: 'music', icon: [1512, 272], path: 'M 1512 332 L 1512 440 Q 1512 480 1472 480 L 1372 480', len: 290, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
262
+ { kind: 'sfx', icon: [1702, 618], path: 'M 1640 618 L 1372 618', len: 270, tIcon: 52, tPipe: 62, tint: '#ffd44d' },
263
+ ];
264
+ const GROW = 9; // v8(批次 17):用户意见"翻转过来后,5个app同时出现,然后同时连接"——两拍制:五图标 tIcon 统一 52 同帧出现,五管 tPipe 统一 62 同帧连接
265
+ const FLOW_SPEED = 4.6; // 输送脉冲速度 px/f
266
+ const FLOW_PERIOD = 74; // 脉冲间距(px)
267
+
268
+ // 路径上按弧长取点(只含直线段与一段二次曲线,生长头火花用)
269
+ const pointAt = (path: string, dist: number): [number, number] => {
270
+ const tok = path.match(/[MLQ]|-?[\d.]+/g)!;
271
+ let i = 0, cx = 0, cy = 0, rest = dist;
272
+ let last: [number, number] = [0, 0];
273
+ while (i < tok.length) {
274
+ const c = tok[i++];
275
+ if (c === 'M') { cx = +tok[i++]; cy = +tok[i++]; last = [cx, cy]; continue; }
276
+ if (c === 'L') {
277
+ const x = +tok[i++], y = +tok[i++];
278
+ const L = Math.hypot(x - cx, y - cy);
279
+ if (rest <= L) { const k = rest / L; return [cx + (x - cx) * k, cy + (y - cy) * k]; }
280
+ rest -= L; cx = x; cy = y; last = [cx, cy]; continue;
281
+ }
282
+ if (c === 'Q') {
283
+ const qx = +tok[i++], qy = +tok[i++], x = +tok[i++], y = +tok[i++];
284
+ const pts: [number, number][] = [];
285
+ for (let s = 0; s <= 16; s++) {
286
+ const u = s / 16;
287
+ pts.push([(1 - u) * (1 - u) * cx + 2 * (1 - u) * u * qx + u * u * x, (1 - u) * (1 - u) * cy + 2 * (1 - u) * u * qy + u * u * y]);
288
+ }
289
+ for (let s = 1; s < pts.length; s++) {
290
+ const L = Math.hypot(pts[s][0] - pts[s - 1][0], pts[s][1] - pts[s - 1][1]);
291
+ if (rest <= L) { const k = rest / L; return [pts[s - 1][0] + (pts[s][0] - pts[s - 1][0]) * k, pts[s - 1][1] + (pts[s][1] - pts[s - 1][1]) * k]; }
292
+ rest -= L;
293
+ }
294
+ cx = x; cy = y; last = [cx, cy]; continue;
295
+ }
296
+ }
297
+ return last;
298
+ };
299
+
300
+ // ---------- 背景霓虹矩形轮廓 ----------
301
+ const RECTS = Array.from({ length: 9 }, (_, i) => ({
302
+ x: [150, 660, 1740, 250, 1150, 700, 1660, 90, 1330][i],
303
+ y: [255, 355, 545, 850, 935, 985, 830, 555, 760][i],
304
+ w: 90 + NOISE[i * 3] * 160,
305
+ h: 60 + NOISE[i * 3 + 1] * 70,
306
+ hue: [265, 285, 300, 255, 275, 210, 320, 240, 40][i],
307
+ ph: NOISE[i * 3 + 2] * Math.PI * 2,
308
+ }));
309
+
310
+ // 相机:一条连续曲线(前摇段自然很慢,无关键帧顿点)
311
+ const CAM = bezier(0.55, 0, 0.18, 1);
312
+
313
+ export const IntegrationHubMap: React.FC = () => {
314
+ const frame = useCurrentFrame();
315
+ // 滤镜/渐变 ID 按实例生成,多实例同场不串引(useId 的 «:» 在 url() 里非法,需清洗)
316
+ const uid = useId().replace(/[^a-zA-Z0-9]/g, '');
317
+
318
+ // --- 相机/面板轨迹:近景正视旧页 → 整体翻转 180°(翻到背面=新页)+ 拉远落定 ---
319
+ const cam = CAM(Math.min(1, Math.max(0, frame / 96)));
320
+ const zoom = 2.05 + (1.0 - 2.05) * cam;
321
+ // v6(批次 15):用户意见"翻转再快1倍"——翻面窗口 f14–84(70 帧)
322
+ // 压半到 f14–49(35 帧),快翻+尾段减速曲线形状保持;
323
+ // 90° 侧棱相应提前到 ~f21.2(easeOut=0.5 → t≈0.206)。
324
+ const rotY = interpolate(frame, [14, 49], [0, 180], {
325
+ extrapolateLeft: 'clamp',
326
+ extrapolateRight: 'clamp',
327
+ easing: Easing.out(Easing.cubic),
328
+ });
329
+ const panX = 130 + (0 - 130) * cam;
330
+ const panY = 120 + (25 - 120) * cam;
331
+
332
+ // v6:用户意见"中间不需要长时间的光晕,翻到中间闪一下就行"——
333
+ // 长光晕平台删除,改为 90° 侧棱时刻(~f21)2 帧脉冲亮闪即回落
334
+ const bloom = interpolate(frame, [19, 21, 23, 27], [0, 1, 0.25, 0], {
335
+ extrapolateLeft: 'clamp',
336
+ extrapolateRight: 'clamp',
337
+ });
338
+ const noise = NOISE[Math.min(frame, NOISE.length - 1)];
339
+
340
+ // 全连通后呼吸
341
+ const allOn = Math.max(...PIPES.map((p) => p.tPipe)) + GROW;
342
+ const breathe = frame > allOn ? 0.5 + 0.5 * Math.sin((frame - allOn) * 0.16) : 0;
343
+ const panelGlow = bloom * 1.1 + breathe * 0.16;
344
+
345
+ // 星图元素(图标/光管/矩形)整体可见度
346
+ const mapIn = interpolate(frame, [34, 60], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' });
347
+ // 背景层弱视差:跟随相机 18% 的位移与 10% 的推拉
348
+ const bgPar = `translate(${(panX * 0.18).toFixed(2)}px, ${(panY * 0.18).toFixed(2)}px) scale(${(1 + (zoom - 1) * 0.1).toFixed(4)})`;
349
+
350
+ return (
351
+ <AbsoluteFill style={{ background: '#09080e' }}>
352
+ {/* 暗紫底:中心冷紫柔光 + 左下品红余光 */}
353
+ <AbsoluteFill
354
+ style={{
355
+ background:
356
+ 'radial-gradient(ellipse 60% 55% at 50% 50%, rgba(98,58,160,0.28), transparent 70%), radial-gradient(ellipse 45% 40% at 16% 80%, rgba(150,56,128,0.13), transparent 70%), radial-gradient(ellipse 40% 35% at 86% 18%, rgba(70,90,190,0.10), transparent 70%)',
357
+ }}
358
+ />
359
+
360
+ {/* 背景霓虹矩形轮廓:细、淡、轻微失焦,作远景衬场 */}
361
+ <AbsoluteFill style={{ transform: bgPar, transformOrigin: '50% 50%' }}>
362
+ {RECTS.map((r, i) => {
363
+ const on = interpolate(frame, [36 + i * 4, 56 + i * 4], [0, 1], {
364
+ extrapolateLeft: 'clamp',
365
+ extrapolateRight: 'clamp',
366
+ easing: Easing.out(Easing.cubic),
367
+ });
368
+ const settle = interpolate(frame, [90, 120], [1, 0.62], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' });
369
+ const a = on * settle;
370
+ return (
371
+ <div
372
+ key={i}
373
+ style={{
374
+ position: 'absolute',
375
+ left: r.x,
376
+ top: r.y,
377
+ width: r.w,
378
+ height: r.h,
379
+ borderRadius: 12,
380
+ border: `1.5px solid hsla(${r.hue} 85% 72% / ${(0.5 * a).toFixed(3)})`,
381
+ boxShadow: `0 0 14px hsla(${r.hue} 90% 62% / ${(0.32 * a).toFixed(3)}), inset 0 0 12px hsla(${r.hue} 90% 62% / ${(0.14 * a).toFixed(3)})`,
382
+ filter: 'blur(0.8px)',
383
+ }}
384
+ />
385
+ );
386
+ })}
387
+ </AbsoluteFill>
388
+
389
+ {/* 光管层 */}
390
+ <svg width={1920} height={1080} style={{ position: 'absolute', inset: 0, opacity: mapIn }}>
391
+ <defs>
392
+ {/* 每条管一个 userSpaceOnUse 渐变(沿管起终点),彩虹沿管线方向铺开。
393
+ objectBoundingBox 在纯水平/垂直线上宽或高为 0 会禁用 paint,必须用户坐标。 */}
394
+ {PIPES.map((p, i) => {
395
+ const nums = p.path.match(/-?[\d.]+/g)!.map(Number);
396
+ const [x1, y1] = [nums[0], nums[1]];
397
+ const [x2, y2] = [nums[nums.length - 2], nums[nums.length - 1]];
398
+ return (
399
+ <linearGradient key={i} id={`rainbow-${uid}-${i}`} gradientUnits="userSpaceOnUse" x1={x1} y1={y1} x2={x2} y2={y2}>
400
+ <stop offset="0%" stopColor="#ffe14d" />
401
+ <stop offset="28%" stopColor="#ff8a5a" />
402
+ <stop offset="52%" stopColor="#ff5ad0" />
403
+ <stop offset="76%" stopColor="#b46bff" />
404
+ <stop offset="100%" stopColor="#5ad0ff" />
405
+ </linearGradient>
406
+ );
407
+ })}
408
+ {/* userSpaceOnUse:纯水平/垂直直线管的 bbox 为零,百分比滤镜区域会
409
+ 坍缩成 0 导致整条管不渲染(左 / 上中 / 右三条直管消失) */}
410
+ <filter id={`pipeGlow-${uid}`} filterUnits="userSpaceOnUse" x="0" y="0" width="1920" height="1080">
411
+ <feGaussianBlur stdDeviation="9" result="b" />
412
+ <feMerge>
413
+ <feMergeNode in="b" />
414
+ <feMergeNode in="SourceGraphic" />
415
+ </feMerge>
416
+ </filter>
417
+ <filter id={`soft-${uid}`} filterUnits="userSpaceOnUse" x="0" y="0" width="1920" height="1080">
418
+ <feGaussianBlur stdDeviation="3.5" />
419
+ </filter>
420
+ </defs>
421
+ {PIPES.map((p, i) => {
422
+ const grow = interpolate(frame, [p.tPipe, p.tPipe + GROW], [0, 1], {
423
+ extrapolateLeft: 'clamp',
424
+ extrapolateRight: 'clamp',
425
+ easing: Easing.out(Easing.quad),
426
+ });
427
+ if (grow <= 0) return null;
428
+ const dashOn = p.len * grow;
429
+ const pulse = frame > allOn ? 0.84 + 0.16 * Math.sin((frame - allOn) * 0.16 + i) : 1;
430
+ // 输送感:亮脉冲沿管线方向(图标→中枢)持续循环流动
431
+ const flowOffset = -((frame - p.tPipe) * FLOW_SPEED + i * 37);
432
+ const flowIn = interpolate(frame, [p.tPipe + GROW, p.tPipe + GROW + 8], [0, 1], {
433
+ extrapolateLeft: 'clamp',
434
+ extrapolateRight: 'clamp',
435
+ });
436
+ const head = pointAt(p.path, dashOn);
437
+ const growing = grow < 1;
438
+ return (
439
+ <g key={i}>
440
+ <g filter={`url(#pipeGlow-${uid})`}>
441
+ <path
442
+ d={p.path}
443
+ fill="none"
444
+ stroke={`url(#rainbow-${uid}-${i})`}
445
+ strokeWidth={12}
446
+ strokeLinecap="round"
447
+ strokeDasharray={`${dashOn} ${p.len + 60}`}
448
+ opacity={0.9 * pulse}
449
+ />
450
+ </g>
451
+ {/* 白热芯:细而亮,管体读作"发光的管"而不是色带 */}
452
+ <path
453
+ d={p.path}
454
+ fill="none"
455
+ stroke="rgba(255,250,255,0.92)"
456
+ strokeWidth={3}
457
+ strokeLinecap="round"
458
+ strokeDasharray={`${dashOn} ${p.len + 60}`}
459
+ opacity={0.8 * pulse}
460
+ />
461
+ {/* 生长头火花:只在 9f 生长期内出现 */}
462
+ {growing && (
463
+ <>
464
+ <circle cx={head[0]} cy={head[1]} r={16} fill="rgba(255,240,255,0.5)" filter={`url(#soft-${uid})`} />
465
+ <circle cx={head[0]} cy={head[1]} r={5.5} fill="#fff" />
466
+ </>
467
+ )}
468
+ {grow >= 1 && flowIn > 0 && (
469
+ <>
470
+ {/* 彗星拖尾:较长、较暗,柔化 */}
471
+ <path
472
+ d={p.path}
473
+ fill="none"
474
+ stroke="rgba(255,255,255,0.7)"
475
+ strokeWidth={8}
476
+ strokeLinecap="round"
477
+ strokeDasharray={`26 ${FLOW_PERIOD - 26}`}
478
+ strokeDashoffset={flowOffset}
479
+ opacity={0.38 * flowIn}
480
+ filter={`url(#soft-${uid})`}
481
+ />
482
+ {/* 彗星亮头:位于拖尾前端(朝中枢方向) */}
483
+ <path
484
+ d={p.path}
485
+ fill="none"
486
+ stroke="#ffffff"
487
+ strokeWidth={6}
488
+ strokeLinecap="round"
489
+ strokeDasharray={`7 ${FLOW_PERIOD - 7}`}
490
+ strokeDashoffset={flowOffset - 19}
491
+ opacity={0.95 * flowIn}
492
+ />
493
+ </>
494
+ )}
495
+ </g>
496
+ );
497
+ })}
498
+ </svg>
499
+
500
+ {/* 图标瓷贴:同帧弹现(一次过冲),连通后染色余光 */}
501
+ {PIPES.map((p, i) => {
502
+ const appear = interpolate(frame, [p.tIcon, p.tIcon + 13], [0, 1], {
503
+ extrapolateLeft: 'clamp',
504
+ extrapolateRight: 'clamp',
505
+ });
506
+ if (appear <= 0) return null;
507
+ const pop = Easing.bezier(0.34, 1.5, 0.64, 1)(appear); // 过冲 ~8% 再回落
508
+ const on = interpolate(frame, [p.tPipe + GROW - 2, p.tPipe + GROW + 8], [0, 1], {
509
+ extrapolateLeft: 'clamp',
510
+ extrapolateRight: 'clamp',
511
+ easing: Easing.out(Easing.cubic),
512
+ });
513
+ return (
514
+ <div
515
+ key={i}
516
+ style={{
517
+ position: 'absolute',
518
+ left: p.icon[0] - 56,
519
+ top: p.icon[1] - 56,
520
+ opacity: Math.min(1, appear * 2.2),
521
+ transform: `translateY(${((1 - pop) * 22).toFixed(2)}px) scale(${(0.72 + 0.28 * pop).toFixed(4)})`,
522
+ }}
523
+ >
524
+ <Tile kind={p.kind} tint={p.tint} on={on * (frame > allOn ? 0.82 + 0.18 * breathe : 1)} />
525
+ </div>
526
+ );
527
+ })}
528
+
529
+ {/* 中枢面板:双面卡整体翻转 180°(正面旧页 → 背面新中枢页) */}
530
+ <AbsoluteFill style={{ justifyContent: 'center', alignItems: 'center', perspective: 1500 }}>
531
+ <div
532
+ style={{
533
+ transform: `translate(${panX.toFixed(2)}px, ${panY.toFixed(2)}px) rotateY(${rotY.toFixed(3)}deg)`,
534
+ position: 'relative',
535
+ transformStyle: 'preserve-3d',
536
+ width: PW * zoom,
537
+ height: PH * zoom,
538
+ flexShrink: 0,
539
+ }}
540
+ >
541
+ {/* 正面:翻转前的旧页面 */}
542
+ <div style={{ position: 'absolute', inset: 0, backfaceVisibility: 'hidden' }}>
543
+ <div style={{ zoom }}>
544
+ <FrontPanel glow={panelGlow} />
545
+ </div>
546
+ </div>
547
+ {/* 背面:翻正后得到的新中枢页(预转 180° 使翻完时朝向镜头且不镜像) */}
548
+ <div style={{ position: 'absolute', inset: 0, backfaceVisibility: 'hidden', transform: 'rotateY(180deg)' }}>
549
+ <div style={{ zoom }}>
550
+ <HubPanel glow={panelGlow} />
551
+ </div>
552
+ </div>
553
+ {/* 面板过曝罩:爆发期盖白 */}
554
+ <div
555
+ style={{
556
+ position: 'absolute',
557
+ inset: -6 * zoom,
558
+ borderRadius: 18 * zoom,
559
+ background: '#ffffff',
560
+ opacity: Math.min(0.96, bloom * 1.05),
561
+ filter: `blur(${5 * zoom}px)`,
562
+ pointerEvents: 'none',
563
+ transform: rotY > 90 ? 'rotateY(180deg) translateZ(1px)' : 'translateZ(1px)',
564
+ backfaceVisibility: 'hidden',
565
+ }}
566
+ />
567
+ </div>
568
+ </AbsoluteFill>
569
+
570
+ {/* 管口接入:五管同帧抵达中枢边缘时各起一圈小涟漪(在面板之上) */}
571
+ {PIPES.map((p, i) => {
572
+ const nums = p.path.match(/-?[\d.]+/g)!.map(Number);
573
+ const [ex, ey] = [nums[nums.length - 2], nums[nums.length - 1]];
574
+ const k = interpolate(frame, [p.tPipe + GROW - 1, p.tPipe + GROW + 13], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp' });
575
+ if (k <= 0 || k >= 1) return null;
576
+ const r = 6 + Easing.out(Easing.cubic)(k) * 26;
577
+ return (
578
+ <div
579
+ key={`port-${i}`}
580
+ style={{
581
+ position: 'absolute', left: ex - r, top: ey - r, width: r * 2, height: r * 2, borderRadius: '50%',
582
+ border: '2px solid rgba(255,255,255,0.9)', opacity: (1 - k) * 0.85,
583
+ boxShadow: '0 0 12px rgba(255,200,255,0.6)',
584
+ }}
585
+ />
586
+ );
587
+ })}
588
+
589
+ {/* 全屏白热眩光(S3/S4):白核+品红/粉翼+青蓝斑 */}
590
+ {bloom > 0.02 && (
591
+ <AbsoluteFill style={{ pointerEvents: 'none' }}>
592
+ <div
593
+ style={{
594
+ position: 'absolute',
595
+ left: 300,
596
+ top: 60,
597
+ width: 1100,
598
+ height: 900,
599
+ background:
600
+ 'radial-gradient(closest-side, rgba(255,255,255,0.98), rgba(255,235,255,0.75) 42%, rgba(255,120,230,0.4) 68%, transparent 88%)',
601
+ filter: 'blur(26px)',
602
+ opacity: Math.min(1, bloom * (0.94 + 0.06 * noise)),
603
+ }}
604
+ />
605
+ <div
606
+ style={{
607
+ position: 'absolute',
608
+ left: 1150,
609
+ top: 150,
610
+ width: 700,
611
+ height: 620,
612
+ background: 'radial-gradient(closest-side, rgba(255,90,208,0.85), rgba(200,70,255,0.4) 60%, transparent 85%)',
613
+ filter: 'blur(34px)',
614
+ opacity: bloom * 0.9,
615
+ }}
616
+ />
617
+ <div
618
+ style={{
619
+ position: 'absolute',
620
+ left: 40,
621
+ top: 480,
622
+ width: 620,
623
+ height: 520,
624
+ background: 'radial-gradient(closest-side, rgba(140,210,255,0.8), rgba(90,120,255,0.35) 60%, transparent 85%)',
625
+ filter: 'blur(30px)',
626
+ opacity: bloom * 0.85,
627
+ }}
628
+ />
629
+ {/* 横向紫白光痕(S2 左侧光痕),只随侧棱闪出现 */}
630
+ <div
631
+ style={{
632
+ position: 'absolute',
633
+ left: 30,
634
+ top: 700,
635
+ width: 420,
636
+ height: 40,
637
+ borderRadius: 20,
638
+ background: 'linear-gradient(90deg, rgba(255,255,255,0.9), rgba(170,90,255,0.7), transparent)',
639
+ filter: 'blur(16px)',
640
+ opacity: interpolate(frame, [20, 34, 70, 92], [0, 0.9, 0.5, 0], {
641
+ extrapolateLeft: 'clamp',
642
+ extrapolateRight: 'clamp',
643
+ }),
644
+ }}
645
+ />
646
+ </AbsoluteFill>
647
+ )}
648
+ <Vignette strength={0.55} inner={0.42} color="#040308" />
649
+ <Grain opacity={0.07} blend="soft-light" />
650
+ </AbsoluteFill>
651
+ );
652
+ };