npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

monto-3d-director-desk

v0.0.13

Published

A browser-based 3D director desk React component built with Vite, Three.js, and React Three Fiber.

Readme

3D导演台

一个基于 React、Vite、Three.js 和 React Three Fiber 的 3D 分镜导演台。它适用于轻量级预演、镜头规划和场景摆位,支持在浏览器里搭建角色、机位、场景和全景背景,并快速记录镜头与截图结果。

功能概览

  • 导演视角 / 机位视角切换
  • 内置8种不同的人物,20种不同的人物姿势
  • 角色、群演、基础几何体和机位快速添加
  • 本地 FBX / OBJ 模型导入,可自定义模型库
  • 群众阵列,想多少人就可以多少人
  • 全景图导入与背景调节
  • 机位拍摄、截图记录和基础镜头管理
  • 视口比例框、九宫格、平移 / 旋转 / 缩放控制
  • 本地场景状态持久化

界面截图

项目截图 项目截图 项目截图 项目截图 项目截图 项目截图 项目截图

技术栈

  • React 19
  • Vite 6
  • TypeScript
  • Three.js
  • @react-three/fiber
  • @react-three/drei
  • Zustand
  • Vitest

项目结构

src
├─ index.ts            # npm 组件入口
├─ DirectorDesk.tsx    # 可嵌入的 React 组件
├─ app/layout          # 顶层壳布局,组织画布与左右侧栏
├─ editor/canvas       # Three.js / R3F 视口、画幅框、工具条、截图视图
├─ editor/panels       # 左侧对象树与右侧属性面板
├─ editor/store        # Zustand 状态管理、撤销与剪贴板逻辑
├─ editor/io           # 截图导出、工程导入导出、宿主通信
├─ editor/loaders      # 本地模型与全景图导入
├─ editor/runtime      # 角色渲染、骨骼和姿势应用
├─ editor/schema       # 数据结构、机位和视口相关定义
└─ styles              # 全局样式

docs                   # 组件调用示例(消费 dist 打包产物)
dist                   # Vite lib 构建产物(发布用)

作为组件使用

Peer dependencies:仅需 react / react-dom ^19three@react-three/fiber@9@react-three/drei@10 等由本包装配为 dependencies,随安装自动带上。

npm install monto-3d-director-desk
import { DirectorDesk, createDefaultDirectorProject } from "monto-3d-director-desk";
import "monto-3d-director-desk/style.css";

export function MyPage() {
  return (
    <div style={{ height: "100vh" }}>
      <DirectorDesk
        theme="dark"
        instanceId="my-project"
        initial={createDefaultDirectorProject()}
        material={{
          kind: "panorama",
          url: "https://example.com/panorama.jpg",
        }}
        showCloseButton={false}
        onReady={() => console.log("ready")}
        onChange={(project) => console.log("project changed", project)}
        onCapturesSent={(captures) => console.log(captures)}
      />
    </div>
  );
}
  • initial:外部工程快照(DirectorProject),每个 instanceId 首次就绪时灌入一次(支持异步后到)。
  • lang:界面语言,"zh" | "en",默认 "zh"
  • onChange:工程内容变化时触发(默认防抖 300ms),便于宿主持久化。
  • uploadModel:可选。传入宿主侧 export async function 上传函数;导入 FBX/OBJ 时 await 其返回的 URL,写入 project.assets[].url。未传时仍回退为 base64 Data URL。
  • uploadCaptures:可选。批量上传截图;传入 (files: File[]) => Promise<string[]>,截图后立即上传,工程内与「发送到画布」均使用返回的远程 URL,不再写入 base64。
  • ref:暴露截图 imperative API(见下)。
<DirectorDesk lang="en" title="Director Desk" />
// host: uploadModel.ts
export async function uploadModel(file: File): Promise<string> {
  const form = new FormData();
  form.append("file", file);
  const response = await fetch("/api/models/upload", { method: "POST", body: form });
  const data = await response.json();
  return data.url; // e.g. https://cdn.example.com/models/xxx.fbx
}
// host: uploadCaptures.ts
export async function uploadCaptures(files: File[]): Promise<string[]> {
  const form = new FormData();
  files.forEach((file) => form.append("files", file));
  const response = await fetch("/api/captures/upload", { method: "POST", body: form });
  const data = await response.json();
  return data.urls as string[];
}
import { uploadCaptures } from "./uploadCaptures";
import { uploadModel } from "./uploadModel";

<DirectorDesk
  uploadModel={uploadModel}
  uploadCaptures={uploadCaptures}
  onChange={(project) => console.log(project.assets)}
  onCapturesSent={(captures) => console.log(captures.map((item) => item.dataUrl))}
/>

截图 API

所有截图输出的 dataUrl 均为 PNG base64 Data URL,格式:

data:image/png;base64,<payload>

类型别名:DirectorDeskImageDataUrl / ScreenshotDataUrl(可直接用于 <img src> 或持久化字符串)。

底部工具栏「当前视角截图」调用链:

ViewportToolbar.handleCapture("current")requestViewportCapture()DirectorCanvas.CanvasCaptureBridge 内注册的 WebGL 截图 handler(最终走 captureViewportCanvas())。

外部可通过 ref 调用同等能力:

import { useRef } from "react";
import { DirectorDesk, type DirectorDeskHandle } from "monto-3d-director-desk";

const deskRef = useRef<DirectorDeskHandle>(null);

<DirectorDesk ref={deskRef} onReady={() => console.log("ready")} />;

// 纯视口截图(等同 CapturePanel)
await deskRef.current?.captureCurrentView();

// 四 / 十二方位
await deskRef.current?.captureFourDirections();
await deskRef.current?.captureTwelveDirections();

// 当前机位截图(等同 CameraPanel)
await deskRef.current?.captureCameraShot("cam_1", { saveToProject: true });

// 等同底部工具栏相机按钮:必要时新建机位、切机位视角、写入工程
await deskRef.current?.captureFromToolbar("current");

// 发送到宿主(触发 onCapturesSent / postMessage)
deskRef.current?.sendCaptures([{ dataUrl: "...", fileName: "shot.png" }]);

也可直接 import 低层函数(需组件已挂载且 Canvas 已注册 handler):

captureCurrentView / captureFourDirections / captureTwelveDirections / captureCameraShot / captureFromViewportToolbar / requestViewportCapture

传入 material.kind === "panorama"url 非空时,会自动加载该全景图,并禁用工具栏「导入全景图」。

本地开发与构建

本仓库的 srcVite lib 组件库,不提供根目录独立 dev 应用;需先打包,再由宿主或 docs/ 引用 dist

pnpm install
pnpm build

产物在 dist/monto-3d-director-desk.jsstyle.css、类型声明)。样式已限定在 .director-desk-root 下,不会污染宿主页面的全局元素。

本地 playground(会先执行 pnpm build):

pnpm dev:docs

默认地址通常为 http://127.0.0.1:5273/。修改库源码后需重新 pnpm build(或重启 pnpm dev:docs)才能在 docs 中看到更新。

常用操作

  • 顶部可切换 导演视角机位视角
  • 左侧用于搜索、选择、分组查看场景对象,并支持可见性 / 锁定 / 删除
  • 中央视口用于摆放场景、切换变换模式、添加角色和机位、导入资源与截图
  • 右侧属性面板会根据当前选中对象自动切换为场景 / 角色 / 模型 / 摄像机编辑面板

快捷键

以下快捷键仅在导演视角下生效(机位视角下不会触发):

  • Ctrl/Cmd + C:复制当前选中对象
  • Ctrl/Cmd + V:粘贴复制对象
  • Ctrl/Cmd + Z:撤销最近一次操作
  • Ctrl/Cmd + Shift + Z:重做最近一次撤销
  • Delete / Backspace:删除当前选中对象

数据与嵌入

  • 当前场景会写入浏览器 localStorage(不含本地导入的外挂模型文件)
  • 本地导入模型保存在当前工程 project.assets 中;传入 uploadModel 时存远程 URL,否则回退 base64 Data URL。由宿主通过 onChange / initial 持久化。
  • 支持导出工程 JSON,也支持通过文件重新导入
  • 支持“保存最近工程 / 恢复最近工程”
  • 组件已包含宿主页面通信桥,适合嵌入到更大的创作工作台中

构建与测试

构建库产物:

pnpm build

构建 docs playground:

pnpm build:docs

测试:

pnpm test

GitHub Pages

推送到 main 后,.github/workflows/deploy-docs.yml 会自动构建 docs 并部署到 GitHub Pages。

首次启用时,在仓库 Settings → Pages 将 Source 设为 GitHub Actions。部署地址一般为:

https://<owner>.github.io/monto-3d-director-desk/

开源说明

  • 本仓库以可发布的 React 组件库为主,适合嵌入更大的创作工作台。
  • 当前版本保留内置角色能力,并支持通过界面导入本地模型与全景图。
  • 若你基于本项目继续发布,请自行确认新增模型、贴图和场景素材的分发许可。

License

MIT