enarratio

中文文档
0.7.2发布于 2026/11/03MITTypeScriptES Module零依赖构建来源已验证

可访问的,服务器渲染的图表和科学数字的网络

中文使用文档
文档目录10 节
  1. 需要说明
  2. 安装
  3. 五分钟开始
  4. 图表
  5. 主题
  6. 您自己的标记在一个主题
  7. 可访问性
  8. 发展
  9. 引用
  10. 许可证

Enarratio

可访问的,服务器渲染的图表和科学数字的网络。

现状:正在积极开发中。 Enarratio是一个。API可能会改变 在1.0之前,每个更改都记录在 更新日志。

Enarratio在服务器上绘制图表到HTML中。一张图表之前是完整的 任何JavaScript运行:阅读器立即看到它,屏幕阅读器得到一个写入 描述和等效的数据表、搜索引擎和语言模型 人们读同样的数字,这个页面不下载图表库。 一个可选的增强层可以添加悬停细节、键盘导航、 点击过滤事件和范围刷在顶部。

它涵盖了网站所需的图表(条形图、线条图、区域图、散点图、 热图,网络,带有预测带和时间轴),小原语a 仪表板需要(火花线,进度环,正常运行时间和热条,事件 时间线)和 实验室需要的数据,从抗体滴度图和基因组开始 痕迹。图表是建立在 可观察到的情节 和 d3-force (可选的对等依赖,已安装 (仅适用于使用它们的图表),并返回纯HTML字符串,因此 Enarratio适用于任何服务器框架。它在Node.js 24和26上进行了测试 并在Cloudflare Workers上运行(该画廊的第一个网站以一种方式呈现图表) 工人);Deno和Bun应该可以工作,因为它只使用标准模块 尚未测试。

画廊: 每个图表都有两个主题,光明和黑暗: enarratio.dustinedwards.info (由 npm run gallery).

天文学和EmDash: enarratio-astro 在Astro页面和Markdown中绘制Enarratio图表,以及 enarratio-emdash 将它们添加到 将EmDash编辑器作为图表块。它们是单独的包 DrDustinEdwards /阿斯特罗;看到 enarratio.dustinedwards.info /阿斯特罗。

需要说明

大多数web图表库都是在浏览器中绘制的。在浏览器中绘制的图表 在它的脚本下载和运行之前是不存在的,对任何东西都是不可见的 在不运行脚本的情况下读取HTML,并且通常对屏幕阅读器不透明。 存在静态图像的服务器端替代方案,但图像无法遵循 该网站的暗模式无法被辅助技术读取 文本,不能进行交互。

网络上的科学数据也有同样的问题,而且还有第二个问题 研究人员发表的数据(滴度图、基因组图、剂量反应曲线、 系统发育,监测图)不在通用的图表库中, 所以每个实验室都是手工绘制的,不一致,而且通常没有 文本的选择。

Enarratio适用于研究、教学和小型组织的开发人员 想要图表的网站:

  • 在服务器上呈现 作为语义HTML中的内联SVG,没有客户机 所需的代码;
  • 可通过建筑进入:书面描述(生成自。 (当没有给出时的数据),一个等效的数据表,键盘访问和 屏幕阅读器的每一个互动公告,不依赖于颜色 独自一人;
  • 遵循网站的主题 在光明和黑暗模式下,从一个渲染,与 调色板检查对比度和色觉缺陷;
  • 包括科学图表类型 与一般的设计一起设计, 分享它们的主题、可访问性和交互性。

安装

npm install enarratio

这就是核心:主题、样式表、颜色检查和小字体 原语(火花线、进度环、正常运行时间条等),没有 运行时依赖关系。图表是单独的入口点,每个入口点都有 它需要的包作为可选的对等依赖项,因此站点只安装 它吸引了:

进口持有也安装
enarratio核心、原语和 tableChart没有什么
enarratio/plotlineChart, areaChart, barChart, scatterPlot, heatmap 下面的图表@observablehq/plot linkedom
enarratio/sciencegenomeTrack, titerPlot, doseResponse, survivalPlot, forestPlot, phylogeneticTree, networkChart,以及他们的统计数据@observablehq/plot d3-force linkedom
enarratio/mapdotMap 和 choroplethMap,从您自己的GeoJSON中绘制没有什么
enarratio/litebarChart, lineChart, areaChart 没有Observable Plot,用于浏览器;也 enarratio/lite/bar, /line, /area没有什么
enarratio/enhance浏览器交互没有什么
enarratio/redraw重新绘制服务器的图表到它的帧宽度; enarratio/redraw/narrow 持有 narrowChart,仅交换到服务器的狭窄绘图没有什么
enarratio/themesdefaultTheme没有什么
enarratio/base.css无主题样式表没有什么

(linkedom 是从浏览器包中删除的,它使用浏览器自己的 文档)。要在浏览器中绘制条形图、折线图和面积图,请从 enarratio/lite:提供相同的选项(包括错误栏和注释) 相同的SVG,没有可观察图,链接或DOM,每个图表15到16 kB 捆绑,缩小和压缩。Enarratio仅支持ESM,需要Node.js 22或 (或任何带有标准ES模块的运行时)。包括TypeScript类型。

五分钟开始

1. 在服务器上呈现图表。 每个图表都有它的数据,字段 情节, alt说明图表所显示内容的句子。

import { stylesheet } from "enarratio";
import { barChart } from "enarratio/plot";
import { defaultTheme } from "enarratio/themes";

const entries = [
  { year: 2022, type: "Publications" },
  { year: 2022, type: "Talks" },
  { year: 2023, type: "Publications" },
  { year: 2024, type: "Publications" },
  { year: 2024, type: "Grants" },
];

const chart = barChart({
  id: "entries",
  data: entries,
  x: "year",
  series: "type", // stacks by type; omit y to count rows
  title: "Entries per year",
  alt: "Entries per year by type, 2022 to 2024: one or two a year, mostly publications.",
});

2. 将其放入具有主题样式表的页面中。 样式表为 无论图表的数量多少,每页都包含一次。

const html = `<!doctype html>
<html lang="en">
<head>
<meta name="color-scheme" content="light dark">
<style>${stylesheet(defaultTheme)}</style>
</head>
<body>${chart}</body>
</html>`;

该页面完成了:图表、图例和数据表 脚本关闭,然后 color-scheme 元标签使它们跟随读者的 浅色或深色偏好。

3. 可选地,在浏览器中增强它。

import { enhance } from "enarratio/enhance";

enhance(); // every Enarratio chart on the page
document.addEventListener("enarratio:select", (event) => {
  const { chartId, field, value } = event.detail; // e.g. "entries", "type", "Talks"
  console.log(chartId, field, value); // value is null when the filter is cleared
});

现在条形图显示悬停和聚焦的细节,箭头键在它们之间移动 一个系列和系列之间),输入或点击过滤器按栏的系列 (和火灾 enarratio:select),图例条目变成切换按钮,拖动, 用方向键移动或从-到窗体选择时间轴上的范围 (enarratio:brush),数据表排序并可以替换图表。 逃避清除。所有的东西都被宣布给屏幕阅读器,动作停止 下 prefers-reduced-motion。 { expand: true, url: true } 添加扩展的 查看并保留地址中的过滤器; strings 翻译图层。

要在服务器上绘制适合手机的宽页面的图表,请在旁边写上它的规格 redrawAttribute 并调用 redrawCharts() (或 redrawChart (一个主人)从 enarratio/redraw 相反,每个图表都以其帧的宽度作为该宽度重新绘制 变化,然后增强。

没有捆绑者,发球 node_modules/enarratio/dist/enhance/index.js 作为一个 文件, sound.js 和 image.js 从它旁边的同一个文件夹(index.js 只有当读者按下“按声音播放”时,才会导入第一个,而第二个则按下 第一次下载),然后用 <script type="module">import { enhance } from "/enhance.js"; enhance();</script>, 或从CDN,如 https://cdn.jsdelivr.net/npm/[email protected]/dist/enhance/index.js。

要重新绘制图表,请将新的服务器标记传递给 update() 在图表上 enhance() 的回报。该标记应该来自Enarratio:它是经过清理的 但它不是插入任意HTML的一种方式。

这个 例子 目录中每个图表的可运行文件 画廊。每个导出图表的HTML,和 npm run gallery 使他们 所有成 site/dist。

图表

函数进口吸引了
barChartenarratio/plot条,堆叠或分组,垂直或水平,在一个类别或时间轴上;在未给定值时计数行;误差线
divergingBarChartenarratio/plot符号值大约为零,每个条都标有它的符号
waterfallChartenarratio/plot一座从一个总数到另一个总数的桥梁,通过增加和减少
lineChartenarratio/plot随时间变化的线或任何数字,带有间隙、参考线、事件标记、直接标签、log y,以及在选定的x后虚线的预测带
areaChartenarratio/plot随着时间堆叠区域,或者堆叠到100%
smallMultiplesenarratio/plot每组一个柱状图或折线图,在共享的尺度上
scatterPlotenarratio/plot线性或对数轴上的点,每个序列的符号,95%波段的可选回归,带有大小图示的气泡,误差条
histogram, densityPlotenarratio/plot分布:分类计数和核密度曲线
boxPlot, stripPlotenarratio/plot箱形图,每一个值都是蜂群
dotPlot, rangePlot, dumbbellPlotenarratio/plot每项一行:点(带间隔)、从低到高的范围和两个连接在一起的值
slopeChartenarratio/plot每件物品两次的价值,在两端贴上标签
pieChartenarratio/plot一种馅饼或甜甜圈,据报道超过六片就有问题
heatmapenarratio/plot主题顺序坡道上的网格,带有打印值和标记的箱子
tableChartenarratio一个可分类的表格与行内酒吧,热电池和火花线
networkChartenarratio/science一个部署在服务器上的强制定向网络,是确定的
titerPlotenarratio/science稀释轴上的滴度具有几何平均值、95% CI和检测限
genomeTrackenarratio/science在核苷酸轴上缩放的特征,以链为单位的箭头,在通道中重叠
doseResponseenarratio/science一个四参数logistic曲线,拟合或给定,有EC50标记
survivalPlotenarratio/scienceKaplan-Meier曲线带有审查标记、置信带和处于风险中的数字
forestPlotenarratio/science有间隔的研究估计,和混合估计(固定或随机效应)
phylogeneticTreeenarratio/science纽威克的一棵树,矩形,顶端按组着色,结点处有支撑
dotMapenarratio/map在你的街道或海岸线上按价值大小划分的点,地标作为正方形,一个突出显示
choroplethMapenarratio/map在连续斜坡的五个标记步骤的区域,值打印在他们适合的地方,没有数据概述
sparklineenarratio一个字大小的趋势线
progressRingenarratio向总目标迈进
uptimeStripenarratio上升、下降、下降或未测量,每周期一个刻度
heatStripenarratio顺序斜坡上的单行条带,每个值一个单元格
timelineenarratio站点或代理的通道,时间窗口上的跨度和点事件,颜色和形状的状态

预测是由你计算出来的,只由Enarratio绘制 lineChart 这个 界如田和界,它遮蔽了带,虚线之后 边界,绘制空心预测点,并在数据中标记预测行 表格。时间轴在 barChart 不需要预先格式化的标签:

import { barChart, lineChart } from "enarratio/plot";

lineChart({
  data: days, // { day, visits, lower, upper }, the last rows computed by your model
  x: "day",
  y: "visits",
  band: { lower: "lower", upper: "upper", label: "95% interval" },
  forecastFrom: "2026-02-23",
  alt: "Daily visits, with a one-week forecast and its 95% interval from 24 February.",
});

barChart({
  data: runs, // { at: "2026-06-09T08:00Z", site }, one row per run
  x: "at",
  xType: "time", // one bar per day, quiet days included
  series: "site",
  alt: "Analysis runs per day at three sites.",
});

每个原语也可以表示它的数字: sparklineTable, uptimeStripTable, progressRingTable, timelineTable 和 heatStripTable 返回一个表和一个总结句,这些表和摘要句是根据与 绘图,在需要的页面旁边。

文档中记录了每个函数 API参考 在它里面 打印稿声明。图表类型仍将出现,以及它们的顺序 进来吧,都在 科学海图。

主题

主题是数据:字体、网格线、明暗配色方案 有八个系列颜色,一个五步顺序坡道和状态颜色。 stylesheet(theme) 将其转换为CSS自定义属性;图表仅指 这些属性,所以一个服务器呈现服务于每个主题和两个方案。

import { checkTheme, defineTheme, stylesheet } from "enarratio";
import { defaultTheme, highContrastTheme } from "enarratio/themes";

const theme = defineTheme({
  ...defaultTheme,
  name: "lab",
  fonts: { body: "Inter, system-ui, sans-serif" },
  light: { ...defaultTheme.light, background: "#fbfaf7" },
});
const report = checkTheme(theme);
// report.issues: text below 4.5:1, marks below 3:1 (WCAG 2.2),
// series names below 4.5:1 on the background, ramp steps under 3:1 by fill
// and edge, and series colors closer than 10 CIEDE2000 units under simulated
// protanopia, deuteranopia or tritanopia. stylesheet() throws on any of them.
const css = stylesheet(theme, { highContrast: highContrastTheme });

背景上写的系列名称(直接标签、生存曲线标签) 以达到4.5:1的每个系列颜色的阴影绘制,并且坡道步骤 太苍白,看不到背景(热图的最低值)得到的优势 3:1。 stylesheet() 既可以从主题中衍生,也可以采用主题本身 seriesLabels 和 sequentialEdges。

您自己的标记在一个主题

任何主题颜色都可以是网站自己的自定义属性之一,具有其值 作为后备: var(--brand-ink, #1c1727). 样式表按照给定的方式编写它, 因此,图表跟随标记,无论网站改变它(一个家庭,一个密度,一个 它自己的黑暗模式),并且没有任何东西被十六进制复制。 checkTheme() 措施 回退,所以保持它等于令牌的值。

const theme = defineTheme({
  ...defaultTheme,
  name: "site",
  light: {
    ...defaultTheme.light,
    background: "var(--surface, #fdfdfe)",
    text: "var(--text, #1c1727)",
    mutedText: "var(--muted, #686471)",
  },
});

当级数或斜坡是符号时,给出 seriesLabels 和 sequentialEdges 也是一种象征;否则它们的阴影是由 后退并保持固定。

颜色和类型已经存在于自己的设计标记中的站点可以跳过 Theme 对象:链接 enarratio/base.css (或称 baseStylesheet()),定义 颜色和字体属性自己,并调整任何大小,重量,半径或动画 举个例子,时间也是一样的 --enarratio-font-size-mark 或 --enarratio-duration-grow. 每个属性都有今天的值作为回退,所以 设置none不会改变任何东西。完整的列表在 API参考。

任何图表都可以用 colors: { Talks: "#8a4a1b" } 或者一个 浅色和深色的一对。图表在data属性中携带它,而不是 style 属性,因此严格的Content-Security-Policy不需要 'unsafe-inline':添加 colorStyles(html) 到页面的CSS。包中附带了两个主题 enarratio/themes: defaultTheme, highContrastTheme,这个例子 上面的用法适用于需要更多对比的读者。这个 画廊的第二页使用了一个中立的,大量评论的示例主题, 例子/主题/ example.ts,是为了复制而写的 和编辑。

可访问性

  • 每个图表都是一个带有标题的图形,一个可见的一句话发现(图表) alt),屏幕阅读器概述(类型,轴和范围,系列和点), 从数据(趋势、极值、异常值、间隔)、注释、源行、“下载CSV”链接和数据计算得出的摘要 表,所有这些都在HTML中,脚本关闭。原始人也是人物,除非 inline。
  • alt 将图表的SVG (role="img"),属于SVG 对图形进行修改,使标题和表格保持可读性。一张没有 一个是根据它的数据来命名自己,并报告一个问题; strict: true 转 每一期(没有Alt或标题,没有标记的轴,太多的系列或点, (CSV太大而无法内联)导致生成失败的错误。
  • 数字、日期和每个生成的字符串紧随其后 locale 和 strings。
  • 每个图表都带有一个等效的数据表,无论是公开的还是直观的 隐藏的。
  • 每个标记都有悬停细节,通过SVG无需脚本即可工作 <title>。
  • 系列的区别不仅仅在于色调:填充条和纹理 区域,图例和直接标签(分开,以免重叠), 散点图中的符号,探测极限以下的空心点,高度 在正常运行时间条中,虚线表示缺失值。
  • 绘图中的文本遵循浏览器的字体大小,并且永远不会在 默认缩放为12px,缩小到320px。
  • 图表遵循强制颜色(Windows高对比度), prefers-contrast: more, prefers-reduced-motion 和印刷,和携带没有 style 属性。
  • 图表的绘制是一种名为图像(role="img"),是否增强;这个 增强层的点在它旁边,在它们自己的 role="application" 层(创纪录的0027).
  • 增强的图表增加了“下载SVG”,“下载PNG”,“下载触觉SVG” (黑底白底,11 * 11.5英寸的纸张,用于盲文压花或膨胀 纸)和带an的图形 id,“复制嵌入”(链接到图表) 旁边的“下载CSV”和“播放声音”,播放每一个系列的上升 还有降调。
  • 地图不接受Enarratio的边界:您传递GeoJSON,每个地图都有一个 总结,一个数据表和一个键盘从北向南走,从来没有 仅通过颜色显示值。
  • 增强的图表是键盘操作,一个选项卡停止,通过本机 按钮上的标记和描述的关键提示;他们宣布每个点 通过活动区域放置、过滤、范围、排序和更新,以及尊重 prefers-reduced-motion。
  • 测试套件在画廊上运行了两个主题,光和 黑暗,有剧本或没有剧本。

发展

npm ci
npm run typecheck && npm run lint && npm test     # unit and rendering tests
npm run build && npm run gallery                  # site/dist
npm run test:browser                              # accessibility, interaction, visual

开发需要Node.js 24或更高版本,它直接运行TypeScript脚本; .nvmrc 针26。

画廊在 https://enarratio.dustinedwards.info 仅作为资产 Cloudflare Worker (wrangler.jsonc),并有严格的内容安全策略 以及投资组合的共享安全标头,来自站点运行时站点注册表中的图库条目 (worker/index.ts, _headers 从 site-runtime-headers). npm run deploy:gallery 构建和 部署;“部署图库”工作流在每次推送时都做同样的事情 main 一旦存储库拥有 CLOUDFLARE_API_TOKEN 和 CLOUDFLARE_ACCOUNT_ID 的秘密。看到 文档/设计/ 0008 -画廊hosting.md. 看到 CONTRIBUTING.md 对于工作流和 文档/设计 埃纳拉比为什么会是现在这个样子

引用

如果您在研究中使用Enarratio,请使用元数据引用 CITATION.cff。

许可证

麻省理工学院。达斯汀·爱德华兹版权所有。

版本与发布记录

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

版本发布日期距今
0.7.2latest2026/11/03今天
0.7.12026/11/03今天
0.7.02026/11/022 天前
0.6.12026/11/012 天前
0.6.02026/11/012 天前
0.5.0next2026/10/313 天前

关于 enarratio 的常见问题

enarratio 是什么?

可访问的,服务器渲染的图表和科学数字的网络

如何安装 enarratio?

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

enarratio 支持 TypeScript 吗?

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

enarratio 支持 ESM 还是 CommonJS?

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

enarratio 需要什么版本的 Node.js?

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

enarratio 可以商用吗?

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

enarratio 还在维护吗?

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