@bruno00o/graph

中文文档
0.19.0发布于 2026/11/08MITTypeScriptES Module构建来源已验证近 30 天下载 3877

框架可知性,用WebGL2提供打入的图形可视化.

中文使用文档
文档目录6 节
  1. 安装
  2. 快开始
  3. 实例
  4. 参与
  5. 添加实例
  6. 许可证

@ bruno00o/ 图表

框架可知性,用WebGL2提供打入的图形可视化.

  • 包括5万个节点和10万个边缘的平滑
  • 声明标记: 将您的字段映射到颜色、 大小、 标签、 箭头和破折叠度通过平面图共享或保存到一个标记, 从数据中推断类型
  • 已键入事件和状态:单击、徘徊、拖放和焦点目标带有自己的项目类型,以标记名称收缩,无所可投
  • 直播来源:通过 TanStack DB 收藏, 或任何与 subscribeChanges重新绘制
  • 在 GPU 上解决命名状态( 选择、 徘徊、 焦点和您自己)
  • 图像和图标被剪接到节点形状、角徽章、轮廓、标签背景、平行边缘和自环
  • 边上有两端, 分别是颜色、 宽度、 破折叠和标签
  • 嵌入组被绘制为容器,在双击上折叠成一个单一的节点,交叉的边缘被合并并被其计数所样式
  • 标有自有大小、颜色、重量、字体、放入、换行和截取等标签,标有节点和边缘,边缘标签随其边缘并保持正上;标签只放在适合的位置而不重叠
  • 拖放、平板、缩放、按住触摸屏、多选择和拉索出框外,加上键盘导航功能宣布用于屏幕阅读器
  • 缩放、平板或离开页面滚动、缩放限制和限制视图的轮子不能离开,并拖动边滚动
  • 在 Web Worker 中强制 GPU 的布局, 并带有 CPU 倒置: 节点在保持平稳时固定, 并拖取节点针
  • 适应缩放的背景网格、环绕结点组、状态或列表的船体,以及HTML 被固定在节点、边缘或点上而无需每个框的渲染
  • 带有 CSS 变量、 光和暗
  • 导出到 PNG , 超过 GPU 限制, 或导出到一个独立的 SVG 文档
  • 按经度和纬度布置的节点,在自己的WebGL上下文中被绘制在地图Libre地图内,并带有地图,图和归属的PNG导出
  • 查看您的应用程序可以控制, 作为选择, 没有滞后框架
  • 一个框架不可知核心,带有薄回放适配器,外加 TanStack DB 和 TanStack 查询集成

早期开发:API仍然可能在1.0之前改变.

安装

pnpm add @bruno00o/graph
入境点目录同伴依赖关系
@bruno00o/graphdefineGraph, (中文(简体) ), nodes, (中文(简体) ), edges, (中文(简体) ), hull, (中文(简体) ), mountGraph
@bruno00o/graph/react<Graph>, (中文(简体) ), <Anchor>, (中文(简体) ), useGraph, (中文(简体) ), useGraphState, (中文(简体) ), useGraphEventreact 19号, react-dom 第 19 条
@bruno00o/graph/dbpersistPositions 财务报告和审定财务报表 subset 用于 TanStack DB 收藏@tanstack/db
@bruno00o/graph/querycreateExploration 用于装入 TanStack 查询的邻居@tanstack/query-core
@bruno00o/graph/cyphercypherGraph,节点和边缘来自一个 Cypher 查询的结果
@bruno00o/graph/exportexportPng 财务报告和审定财务报表 exportSvg
@bruno00o/graph/mapmountMapGraph 财务报告和审定财务报表 exportMapPng 用于地图Libre地图maplibre-gl 6个
@bruno00o/graph/map/react<MapGraph>,用于 MapLibre 地图的回放组件maplibre-gl 6, (简体中文), react 19号, react-dom 第 19 条
@bruno00o/graph/layoutslayers, (中文(简体) ), grid, (中文(简体) ), rings 财务报告和审定财务报表 radial 版式
@bruno00o/graph/layouts/forceforce 布局,在Web Worker的GPU上计算
@bruno00o/graph/devtoolsTanStack Devtools 的图形面板和渲染时间@tanstack/devtools
@bruno00o/graph/devtools/reactgraphDevtoolsPlugin 财务报告和审定财务报表 <GraphDevtoolsPanel> 用于反应@tanstack/devtools-utils, (中文(简体) ), react 第 19 条
@bruno00o/graph/theme.css默认光和暗主题

快开始

import { defineGraph, edges, mountGraph, nodes } from '@bruno00o/graph'
import '@bruno00o/graph/theme.css'

type Item = { id: string; label: string; group: string; weight: number }
type Link = { id: string; from: string; to: string }

const definition = defineGraph({
  marks: [
    edges<Link>(links, { source: 'from', target: 'to', arrow: 'target' }),
    nodes<Item>(items, { color: 'group', size: 'weight', label: 'label' }),
  ],
  states: { muted: { opacity: 0.2, label: false } },
})

const graph = mountGraph(container, { definition, ariaLabel: 'Sample graph' })

graph.on('click', ({ target }) => {
  if (target?.kind === 'node') console.log(target.datum.label)
})
graph.states.set('muted', { nodes: ['n4', 'n7'] })

用反应 :

import { defineGraph, edges, nodes } from '@bruno00o/graph'
import { Graph, useGraphState } from '@bruno00o/graph/react'
import { useMemo } from 'react'

function Hovered() {
  const hovered = useGraphState((state) => state.hovered)
  return <output>{hovered?.kind === 'node' ? String(hovered.key) : ''}</output>
}

export function SampleGraph({ items, links }: { items: Item[]; links: Link[] }) {
  const definition = useMemo(
    () =>
      defineGraph({
        marks: [
          edges(links, { source: 'from', target: 'to' }),
          nodes(items, { color: 'group', label: 'label' }),
        ],
      }),
    [items, links],
  )
  return (
    <Graph definition={definition} ariaLabel="Sample graph" style={{ height: 480 }}>
      <Hovered />
    </Graph>
  )
}

无节点 x 财务报告和审定财务报表 y 按定义的布局排列。 它运行在第一个节点上,然后在邻居附近放置新的节点而不移动其他节点.

import { force } from '@bruno00o/graph/layouts/force'

const definition = defineGraph({ marks, layout: force({ edgeLength: 60 }) })
const graph = mountGraph(container, { definition, ariaLabel: 'Sample graph' })

button.addEventListener('click', async () => {
  const completed = await graph.layout.run(undefined, { keys: graph.selection.get().nodes })
  if (completed) graph.view.fit({ ...graph.selection.get(), duration: 400 })
})

GPU上运行的大图 (WebGL2 in the worker)和CPU上运行的小图; force({ engine: 'gpu' }) 或者说 'cpu' 强迫选择. graph.layout.run() 确定每个节点,或者只 keys,并决心 false 当停止。 进步在商店里生活state.layout.running 财务报告和审定财务报表 state.layout.progress),以及 layoutstart 财务报告和审定财务报表 layoutend 标记每次运行.

grid, (中文(简体) ), rings 财务报告和审定财务报表 radial 立即计算结果 节点滑翔过来 transitions.layout (默认为400毫秒)和 fit 他们降落的地方.

import { grid, radial } from '@bruno00o/graph/layouts'

await graph.layout.run(grid<Item>({ order: (a, b) => a.group.localeCompare(b.group) }), {
  fit: true,
})
await graph.layout.run(radial({ root: 'hub' }), { duration: 600 })

一个 TanStack DB 收藏是一个活源:通过它到一个标记,它的更改在没有新定义的情况下到达.

nodes(itemsCollection, { color: 'group', label: 'label' })

要过滤一个大收藏, subset 用一个 where 表达式:一个新的过滤器只移动输入或离开的行,而点取的收藏只载出图表要求的.

import { subset } from '@bruno00o/graph/db'
import { gte } from '@tanstack/db'

const heavy = subset(itemsCollection, (item) => gte(item.weight, 40))
nodes(heavy, { color: 'group' })

实例

这个 examples 文件夹有可操作的示例:香草和回放图、图像、徽章和轮廓、平行边缘和回放、折叠和展开的嵌入组、有船体和锚定的HTML的背景网格、高达50万个节点、分层、网格、环和射线布局、与TanStack DB的分页间协作、过滤50万个TanStack DB行的边缘并按要求加载、与TanStack Query相邻的探索、以及绘制在地图上的地方。 跟着他们跑 pnpm install && pnpm dev。 。 。 .

参与

  • 欢迎提出问题和拉动请求.
  • pnpm verify 运行 lint, 类型, 测试, 构建和包检查 .
  • 添加 ?caps=low 以实例 URL 运行到最小的 WebGL2 设备:最小限制和没有可选扩展. ?caps=software 报告软件渲染器,以及 &texture=4096 仅降低最大纹理大小。 在测试中, limitWebgl 从 src/testing/webgl-caps.ts 并列出设备拒绝的纹理.
  • pnpm test:browsers 构建示例和文档,然后用 Playwright 打开 Chromium, Firefox 和 WebKit 中的每一个示例页面. 每个页面必须记录不出错,绘制其画布,在悬浮上选择一个节点,在点击时选择并缩放在车轮上. 它按浏览器打印页面表,并保存每个页面的截图 browser-results运行 pnpm exec playwright install 一次下载浏览器.
    • --browser firefox 或者说 --browser chromium,webkit 只运行一些浏览器 .
    • --example nodes, (中文(简体) ), --example 'docs/*' 或者说 --example examples/labels 只运行一些页面。 这个 low/* 页面打开五个示例 ?caps=low。 。 。 .
    • --no-build 重新使用最后的建筑, --software 在没有GPU的机器上绘制其软件渲染器的铬, --headed 显示窗口.
    • 在 Linux 上, Firefox 创建了仅包含显示的 WebGL 上下文: 运行 xvfb-run pnpm test:browsers 在一台没有一台的机器上,像CI一样.
    • 每个例子页将其图表显示为 window.graph支票上写着.

添加实例

Docs 画廊读取所有文件夹 docs/src/examples,所以一个实例只触及到自己的文件夹:

docs/src/examples/<slug>/
  meta.ts               title, description, hint, category, order, tags, api, guides
  main.ts               exports mount(container), which returns the graph
  main.tsx              or exports a React Example that passes its ref to <Graph>
  messages.ts           every text the example shows
  notes.mdx             optional prose under the demo: how it works, what to try
  thumbnail.webp        generated, light theme
  thumbnail-dark.webp   generated, dark theme
  • pnpm docs:new-example <slug> <category> 创建带有小图形的文件夹开始, --react 以反应为例。 文件夹名称是弹簧和地址, /examples/<slug>:永远不要重命名一个已出版的.
  • meta.ts 导出对象 satisfies ExampleMeta,并且只导入类型:
    • title, (中文(简体) ), description (一两句,相与相与相接 hint (什么尝试,在演示之上);
    • category,类型之一 docs/src/examples/categories.ts数字 : basics, (中文(简体) ), style, (中文(简体) ), layouts, (中文(简体) ), structure, (中文(简体) ), interaction, (中文(简体) ), analysis, (中文(简体) ), edges, (中文(简体) ), time-and-maps, (中文(简体) ), data, (中文(简体) ), tools· ;
    • order (a) 在类别内,分10个步骤,使一个新的例子适合其他两个例子;
    • tags数字 : Vanilla 或者说 React 条目文件后加 TanStack DB, (中文(简体) ), TanStack Query 财务报告和审定财务报表 TanStack Devtools 当实例导入时;
    • api,页 /docs/api 实例使用,例如 define-graph,以及 guides,页 /docs 例如 states 或者说 view#view-limits: 与两者的页面链接;
    • harness: { select: false } 当点击一个节点时,不选择它.
  • 代码查看器显示文件夹的每个文件, 然后显示它们从 ../shared。页上列出的模块来自输入.
  • pnpm docs:thumbnails <slug> 构建道克,打开Chromium中的页面,等待第一个渲染和布局的结束,并用400个光和暗的WebP图像将舞台保存为两个640个,每个图像约25个KB. 没有一发子弹,它就能捕捉到每一个例子; --no-build 复用后一积. 提交两个图像 .
  • pnpm test 在错误的元数据、 未知的类别、 重复的 switter 、 缺失的 docs 页面的链接、 与导入不匹配的标签、 丢失的缩略图、 文件夹外的导入, ../shared 以及公共入口,或脚手架上留下的文字。 礛 pnpm test:browsers --example 'docs/<slug>' 检查三个浏览器中的页面.
  • pnpm docs:dev 向5192号港口的文件提供服务; pnpm --dir docs exec vite dev --port <port> 再选一个.

公约:

  • 一个例子,一个想法,大约50到150行.
  • 中性以固定的种子生成数据,这样每个运行和每个缩略图都是相同的:没有商业域,没有包含一个的活世界数据集. ../shared/data 有种子的发电机.
  • 屏幕上的每个文字都来自示例 messages.ts。示例拉动请求不编辑 ../shared 或文件夹外的任何文件.
  • 没有投篮 datum:打出标记推断出.
  • 只有公共入境点: @bruno00o/graph, (中文(简体) ), @bruno00o/graph/react, (中文(简体) ), @bruno00o/graph/layouts 以及其他的子路径.

许可证

麻省理工学院

版本与发布记录

@bruno00o/graph 共发布 26 个版本,首次发布于 2026/11/06;过去 12 个月发布了 26 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.19.0latest2026/11/08今天
0.18.02026/11/08今天
0.17.12026/11/08今天
0.17.02026/11/08今天
0.16.02026/11/08今天
0.15.02026/11/08今天

关于 @bruno00o/graph 的常见问题

@bruno00o/graph 是什么?

框架可知性,用WebGL2提供打入的图形可视化.

如何安装 @bruno00o/graph?

在项目目录运行 npm install @bruno00o/graph,或使用 pnpm add / yarn add / bun add。

@bruno00o/graph 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@bruno00o/graph 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@bruno00o/graph 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@bruno00o/graph 可以商用吗?

@bruno00o/graph 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@bruno00o/graph 的下载量有多少?

根据 npm 官方下载统计,@bruno00o/graph 在 2026/10/09 – 2026/11/07 这 30 天内被下载 3,877 次,日均约 129 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@bruno00o/graph 还在维护吗?

最新版本 0.19.0 发布于 2026/11/08(今天);至今共发布 26 个版本,其中过去 12 个月发布了 26 个;首次发布于 2026/11/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。