ChartBuddy 嵌入了 API (@chartbuddy.io/embed(中文(简体) )
创建图表库 透视 在任何网页上. 默认为只查看 (无头)
平面 : 悬挂左上方的 ChartBuddy 球 下载 (巴布亚新几内亚), 导出
配置 (JSON), 和 (JSON), 和 (JSON), (JSON), (JSON), (JSON), (JSON) (JSON), (JSON) (JSON) (JSON) (JSON) (JSON) (JSON) (JSON) (JSON) 编辑 (完整互动编辑器). 过 editable: true
立即打开编辑器。 电子表格是 没有 包含。 没有账户或
需要图表 ID: 通过 chartData。 。 。 .
公共 API : Insight (通过) new Insight(), (中文(简体) ), getInsights, (中文(简体) ), snapshotInsights, (中文(简体) ),
version全球登记册: window.__CHARTBUDDY_INSIGHTS__。 。 。 .
联合来文的每个条目(包装根,
.single.mjs,多加载器)以注释打开 命名导出和最小示例的头条 。 探员: 开始于llms.txt,然后获取链接的文档.md视需要编制。 还: https://unpkg.com/@chartbuddy.io/embed/llms.txt • 妇女 https://chartbuddy.io/embed/docs/llms.txt。 。 。 . Unpkg 上的套接字根将解析为可读的再导出 单文件构建.
Claude/ 严格的CSP( 建议)
import { Insight } from 'https://unpkg.com/@chartbuddy.io/embed';
// equivalent:
// import { Insight } from 'https://unpkg.com/@chartbuddy.io/embed/chartbuddy-embed.single.mjs';
<div id="chart" style="width:960px;height:560px"></div>
<script type="module">
import { Insight } from 'https://unpkg.com/@chartbuddy.io/embed';
// Default: view-only + ChartBuddy hover ball
new Insight('#chart', {
instanceId: 'revenue', // stable id for multi-mount
chartData: {
chartType: 'clusteredBar',
isDataTransposed: true,
seriesData: [
['', 'Q1', 'Q2', 'Q3', 'Q4'],
['Revenue', 100, 112, 125, 140],
['Costs', 60, 66, 70, 78],
],
title: { visible: true, text: 'Revenue vs Costs' },
subtitle: { visible: false, text: '' },
},
});
// Full editor: new Insight('#chart', { editable: true, chartData: … })
</script>
执行 没有 通过 assetBase 在这条路上。 宾德勒: import { Insight } from '@chartbuddy.io/embed'。 。 。 .
安装/ 多文件( 正常网站)
npm install @chartbuddy.io/embed
缓存友好多文件加载器( 当 CSP 允许时, 双胞胎确定) :
https://unpkg.com/@chartbuddy.io/embed/chartbuddy-embed.mjs
或者说 import { Insight } from '@chartbuddy.io/embed/multi'。 。 。 .
用反应
使用捆绑的绑定器- 它们处理 ExpressMode 的双挂载, 补齐活的 关于数据变化的图表,而不是重新挂载,而是在卸载上销毁.
import { InsightChart } from '@chartbuddy.io/embed/react';
export function ChartEmbed({ chartData }) {
return <InsightChart chartData={chartData} style={{ width: '100%', height: 560 }} />;
}
react 是可选的同伴依赖(反应18或19)。 因为必须进入
实例:
import { useInsight } from '@chartbuddy.io/embed/react';
const { ref, insight, ready, error } = useInsight({ chartData, editable: true });
// <div ref={ref} style={{ height: 400 }} />
chartData 以身份来比较——如果建立内线,就记住它.
没有捆绑器, Plain HTML 页面需要导入映射 两者 react
和后路 .mjs 文件名 :
<script type="importmap">{"imports":{
"react": "https://esm.sh/react@19",
"react-dom/client": "https://esm.sh/react-dom@19/client",
"@chartbuddy.io/embed/react": "https://unpkg.com/@chartbuddy.io/embed/react.mjs"
}}</script>
使用 React.createElement 没有建设步骤意味着没有JSX。 对于一个独立
工艺品,平地 new Insight() 或自定义元素比两者都简单.
带Vue 3
<script setup>
import { InsightChart } from '@chartbuddy.io/embed/vue';
</script>
<template>
<InsightChart :chart-data="chartData" style="height: 400px" @change="onChange" />
</template>
vue 是一个可选的同伴依赖. useInsight() 也导出用于
必须进入。 指定新对象为 chartData 以补丁图表——
未检测到已存在的突变.
带有 Angular (和 Svelte / Solid / plain HTML) 的图像
角线使用 <chartbuddy-insight> 自定义元素而不是编译的元素
角质库,所以ChartBuddy的升级 与你的角质主修没有联系. 没有
相对依赖.
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@chartbuddy.io/embed/element';
// template:
// <chartbuddy-insight [chartData]="cd" instance-id="revenue"
// style="display:block; height:400px"
// (change)="onChange($event)"></chartbuddy-insight>
chartData 必须设置为 属性 它是一个物体。 活动是
CustomEvents 改为 event.detail。完整指南 :
https://chartbuddy.io/embed/docs/guides/angular (中文(简体) )
用法( 标记/ 全局)
<script src="https://unpkg.com/@chartbuddy.io/embed/chartbuddy-embed.global.js"></script>
<script>new ChartBuddyEmbed.Insight('#chart');</script>
单文件 IIFE: chartbuddy-embed.single.global.js。 。 。 .
API 密码
new Insight(target: string | HTMLElement, options?: {
chartData?: object; // ChartBuddy chart-data (cd) — see below
assetBase?: string; // multi-file only; ignored by single-file
editable?: boolean; // default false → view mode; true → full editor
allowEdit?: boolean; // default true; false = Download/Drag only (no Edit)
editSession?: 'toggle' | 'locked'; // locked = always edit, no mode chrome
host?: { // optional chrome hooks
getToolbarPlacement?: () => object; // widget (default) | float | dock
getToolbarContainer?: () => string | Element | null;
positionToolbar?: (toolbar, target) => void; // float only
getPopupContainer?: () => string | Element | null; // menus; default body
startDragging?: (event) => void;
};
engineFlags?: { // engine features still being built; all off by default
arrowGeometry?: boolean; // arrows clear bars and total labels (see below)
};
}): {
container: HTMLElement;
assetBase: string;
instanceId: string;
chartContainerId: string;
mode: 'view' | 'edit';
editSession: 'toggle' | 'locked';
allowEdit: boolean;
ready: Promise<void>;
chart: any | null;
focus(): void;
setChartData(cd: object): void; // partial OK — chartType optional
setData(seriesData: any[][]): void;
update(patch?: object): void; // no arg = redraw only
getChartData(): object | null;
on(event: 'ready' | 'mode' | 'change', handler: Function): () => void;
off(event: 'ready' | 'mode' | 'change', handler: Function): void;
isDirty(): boolean;
getRevision(): number;
toPngBlob(options?: { scale?: number; background?: string | null }): Promise<Blob>;
toPngBase64(options?: { scale?: number; background?: string | null }): Promise<string>;
// PNG helpers default background to #ffffff; downloadPng defaults transparent
downloadPng(options?: { scale?: number; background?: string | null }): Promise<void>;
dragExport(): Promise<void>;
exportConfig(): void;
enterEditMode(): Promise<void>; // view → edit (no-op if allowEdit: false)
exitEditMode(): Promise<void>; // edit → view (also ball → Done)
destroy(): void;
};
getInsights(): Record<string, Insight>;
snapshotInsights(options?: {
png?: boolean;
scale?: number;
background?: string | null;
}): Promise<{ schemaVersion: 1; version: string; charts: Record<string, any> }>;
version: string;
发动机旗 (engineFlags(中文(简体) )
仍在建设的图表引擎的特性可以打开每页 之前,他们为每个人。 旗帜适用于页面上的每个图表 下图,然后在功能默认时退出.
arrowGeometry: 将差分箭头( 以及后来的 CAGR 和等分箭头) 定位 通过一个共享的计算,所以它们清除了横跨的条和总标签 图表给他们留了空间 而不是剪断它们。 现有图表中的箭头 开机时可能会动.
new Insight('#chart', { chartData, engineFlags: { arrowGeometry: true } });
查看模式( 默认)
- 无头图图(没有格式化工具栏/选择铬).
- 盘旋时:ChartBuddy球(左上方)- 下载 巴布亚新几内亚, 拖放到幻灯片, (中文(简体) ), 编辑。 。 。 .
enterEditMode()/ 发球 编辑 用当前重挂载完整的编辑器chartData。 。 。 .
只显示( E)allowEdit: false(中文(简体) )
- 相同视图球和导出,但 编辑 省略.
enterEditMode()是个禁忌.
编辑模式( E)editable: true(中文(简体) )
- 交互式 ChartBuddy 编辑器, 格式化为 UI .
- 默认工具栏位置是 部件 (变形铁路中的模块). 覆盖
host.getToolbarPlacement。 。 。 . - 通过球离开 完成 或者说
exitEditMode()(返回以当前配置查看).
已锁定编辑( E)editSession: 'locked'(中文(简体) )
- 总是在编辑器上: 没有完成 / 变形 .
enterEditMode()编号 :exitEditMode()绝对不是.- 当主机页面拥有周围的铬时使用(demos, 对话框).
图表数据 (cd计划
options.chartData 是一个图表库 图表数据 对象。 部分对象为
默认合并 (已注销) title 编号 : subtitle 编号 : legend 编号 : axes 编号 :
canvas 编号 : footnote 被深深地淹没.
需求
| 外地 | 类型 | 页:1 |
|---|---|---|
chartType | string | 见下面允许的值 |
seriesData | array[] | 2D 网格( 参见布局) |
建议
| 外地 | 类型 | 页:1 |
|---|---|---|
isDataTransposed | boolean | 偏爱 true 下面的网格布局 |
title | 文本块 | { visible, text } —— 说 text 可能为平面或 HTML |
subtitle | 文本块 | 相同的形状; 设置 visible: false 隐藏默认字幕 |
footnote | 文本块 | 相同形状 |
legend | 对象 | { visible, colors?: string[], … } ——系列颜色活在 legend.colors |
backgroundColor | string | 默认 "transparent" |
orientation | "vertical" | "horizontal" | 默认 "vertical" |
允许 chartType 数值
切巴迪: 性别-切巴蒂: 贝京
barMekko • 妇女 clusteredBar • 妇女 combo • 妇女 line • 妇女 mekko • 妇女 pie • 妇女 scatter
stackedArea • 妇女 stackedArea100 • 妇女 stackedBar • 妇女 stackedBar100
waterfall
还接受: bubble → scatter, (中文(简体) ), donut → pie。 。 。 .
切巴迪:性别-切巴蒂:结束
别名是快捷键 种子默认值 他们不只是重命名:
| 你通过 | 决定 | 种子 |
|---|---|---|
'donut' | pie | pie.innerRadiusRatio: 0.5 (一个真正的洞) |
'pie' | pie | pie.innerRadiusRatio: 0 (一个完整的派) |
'bubble' | scatter | 大点直径 |
吃甜甜圈,通过吧 chartType: 'donut' 设置 innerRadiusRatio 你自己来
只需覆盖孔大小. getChartData() 返回时 pie 与
innerRadiusRatio: 0.5,这回路是正确的.
验证
图表数据在API边界验证——两者 new Insight({ chartData })
财务报告和审定财务报表 setChartData() 编号 : setData() 编号 : update()无效输入 掷出 与
每一个问题的路径,所以你得到一个可操作的错误而不是空白
图表 :
insight.setChartData({ chartType: 'pie', pie: { innerRadiusRatio: 5 } });
// Error: [chartbuddy/embed] setChartData: invalid chart data — 1 problem:
// • pie.innerRadiusRatio: 5 is above the maximum of 1
检查什么 : chartType (有你的意思提示),字段类型,enums,
数字范围 seriesData 网格(包括每行/栏的最小值)
),以及选项包是否与图表类型相匹配—— bar 选项
(单位:千美元) pie 图表被拒绝。 标记 seriesData (行长不等) 警告时
但不要丢。 复制 instanceId 同页上的值 掷出。 。 。 .
未知的密钥是 永远 错误,所以为新版本编写的配置
负载. chart-schema.json 是同一规则的机器可读形式,可用
用于验证或限制生成或结构化图表数据.
未挂起的检查
同样的支票出口. validateChartData() 从不扔和报告
所有它找到的,这就是当一个模型 作者的配置:
import { validateChartData } from '@chartbuddy.io/embed';
const { valid, errors, warnings } = validateChartData(candidate);
// errors[0] → {
// path: 'chartType',
// code: 'unknown-chart-type',
// severity: 'error',
// message: '"clusterdBar" is not a known chart type. Did you mean "clusteredBar"?',
// expected: 'a ChartType or alias',
// received: '"clusterdBar"',
// allowed: ['barMekko', 'clusteredBar', 'stackedArea', …],
// suggestion: 'clusteredBar',
// }
code 财务报告和审定财务报表 path 稳定合同—— code,修复值为
path,从不分析 message代码 : not-an-object, (中文(简体) ), unknown-chart-type, (中文(简体) ),
empty-patch, (中文(简体) ), wrong-type, (中文(简体) ), out-of-range, (中文(简体) ), not-in-enum, (中文(简体) ), series-data-shape, (中文(简体) ),
ragged-series-data (警告), foreign-option-bag。 。 。 .
投出物携带相同的物体:
import { ChartDataValidationError } from '@chartbuddy.io/embed';
try {
insight.setChartData(candidate);
} catch (err) {
if (err instanceof ChartDataValidationError) console.log(err.errors);
}
部分更新
await insight.ready;
insight.setData([['', 'Q1'], ['Revenue', 120]]); // data only
insight.update({ title: { text: 'FY26' } }); // any partial patch
insight.update(); // redraw only
setChartData 还接受部分 chartType 无需.
活动
insight.on('ready', () => { … });
insight.on('mode', (mode) => { … }); // 'view' | 'edit'
insight.on('change', (cd) => { … }); // after meaningful edits
insight.isDirty(); // true since boot / last Done
insight.getRevision(); // monotonic edit counter
seriesData 布局( 建议)
与 isDataTransposed: true,使用时 图表 连续行数 :
[
['', 'Q1', 'Q2', 'Q3'], // row 0: categories ( [0][0] usually "" )
['Revenue', 100, 112, 125], // each later row = one series
['Costs', 60, 66, 70],
]
馅饼 (类别/值对):
[
['Category', 'Value'],
['North', 45],
['South', 30],
['East', 25],
]
散点 (译出不支持):
[
['', 'Metric X', 'Metric Y', 'Size', 'Group'],
['Point 1', 10, 15, 8, 'A'],
['Point 2', 20, 12, 5, 'B'],
]
最小示例
{
chartType: 'clusteredBar',
isDataTransposed: true,
seriesData: [
['', 'Q1', 'Q2', 'Q3'],
['Revenue', 100, 112, 125],
],
title: { visible: true, text: 'Revenue' },
subtitle: { visible: false, text: '' },
}
完整配置
最有钱最安全 cd 是一个活编辑器通过
insight.getChartData() (或 insight.exportConfig()之后 ready传回JSON作为 chartData。 。 。 .
可选先进领域(关于全部出口): canvas, (中文(简体) ), axes, (中文(简体) ),
chartPositionPercentages, (中文(简体) ), annotations, (中文(简体) ), multilines,类型特定块
(单位:千美元)bar, (中文(简体) ), line, (中文(简体) ), area, (中文(简体) ), pie, (中文(简体) ), waterfall, (中文(简体) ), mekko, (中文(简体) ), combo, (中文(简体) ), seriesLabels。 。 。 .
如何运作
单文件 : d3 + DOMPurify + 引擎+ CSS 在一个模块中——用于克洛德.
多个文件 : 小型装载机牵引兄弟姐妹(webapp-entry.js卖家,CSS,
劳工。 使用您控制的网站 .
安全性:图表数据来自何处
chartData 现按规定执行。 引擎把它当作文件
作者, 不是不可信输入, 所以 如果页面上的图表数据是
受自己终端用户的影响, 对待它的方式,你对待任何
用户提供的内容.
值得了解的具体案例:在图表数据中使用了字体姓氏 以请求网页字体。 ChartBuddy 验证它们并拒绝可以 摆脱样式表,但页面上的内容-安全政策是控件 这不取决于我们是否正确。 如果您提供图表数据 用户可以施加影响,至少设定:
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src 'self' data: https://fonts.gstatic.com;
object-src 'none';
style-src 财务报告和审定财务报表 font-src 将样式表或字体从中取出,
因此恶意字体名称不能变成对主机的请求
选择. 'unsafe-inline' 用于 style-src 因为引擎设定
渲染时的内入样式; 它不会削弱上面的源许可列表 .
如果您的页面图表数据只来自您的后端或图表 你自己的团队授权, 这是深入的防御,而不是要求.
页:1
- 多挂载支持 . 构造
new Insight()在一个文档中多次. - 无电子表格 本包中.
- 默认视图模式没有格式化工具栏;使用编辑或
editable: true。 。 。 . - 单行文件使用主行脚标签放置(没有工人/瓦斯取回).
- 需要浏览器( N)
document) (中文(简体) ).
许可证
专有评价许可证——"ChartBuddy". 见捆绑 LICENSE 文档.