很多前端项目都能"画一条曲线",但要把真实的 ECG 采样画成一张可读、可缩放、比例正确的心电图纸,细节远比一条 canvas.lineTo() 多。
我把这个过程整理成了 h5ECG:一个框架无关的 ECG Canvas 渲染库,提供原生、React 和 Vue 三种入口。它把网格、波形、缩放、拖拽、12 导联排版和测量尺都封装好;你只需要准备自己的采样数据。
本文讨论的是数据可视化与前端实现,不用于医疗诊断。实际临床使用还需要合规的数据处理、设备标定与专业审核。

先说最容易踩坑的:你的"数值"到底是什么?
不同采集设备输出的数据并不相同。有的直接给 mV,有的给 ADC 整数,有的还带着偏移量。h5ECG 默认按本仓库示例的标定理解输入:
- 基线 adcBaseline: 2048
- 换算系数 adcUnitsPerMv: 1000,即 1000 个 ADC units = 1mV
因此,一串类似 2025, 2025, 2038 的数据不是直接拿来当像素高度,而是先换算为 mV,再按增益绘制。若你的设备参数不同,务必覆盖这两个选项;比例错了,波形看似正常,时间和电压含义却已经不对了。
安装:npm、GitHub 都可以
优先使用 npm:
npm install h5ecg
如果你希望直接依赖源码仓库,也可以固定到已发布版本:
bash
npm install github:dongweiq/h5ecg#v0.1.1
固定 tag 而不是分支名,是为了让团队构建更稳定、结果更可复现。
最小可用示例:在页面上画出一条自己的波形
页面里准备一个有高度的容器:
bash
<div id="viewer" style="height: 520px"></div>
再把你自己的单导联数据传入:
ini
import { EcgCanvas } from 'h5ecg';
const samples = '2025\n2025\n2038\n2040';
const viewer = new EcgCanvas(document.getElementById('viewer')!, {
mode: '12x1',
speed: 25,
gain: 10,
pixelsPerMillimeter: 8,
adcBaseline: 2048,
adcUnitsPerMv: 1000,
});
viewer.setData(samples);
这里有三个真正决定"心电图纸感"的参数:
- speed: 25:25 mm 对应 1 秒,所以 1 mm 小格为 40 ms。
- gain: 10:10 mm 对应 1 mV。
- pixelsPerMillimeter:只决定屏幕显示密度,不改变上述医学比例。
想看更细的局部时,可以直接调用:
ini
viewer.zoomBy(1.2);
viewer.setOptions({ speed: 50, gain: 20 });
viewer.resetViewport();
用户也能用鼠标拖动、滚轮或双指缩放。网格与波形会分层绘制,且只处理可见样本;高密度数据缩小时会保留每个像素桶的峰谷,而不是把尖峰"抹平"。
你的数据是 12 导联?直接传数组或对象
h5ECG 支持 12x1、6x2-sync、6x2-continuous、3x4-sync 和 3x4-continuous 等布局。可以传入 12 条导联的数组,也可以传一个带导联名的对象:
php
viewer.setOptions({ mode: '3x4-continuous' });
viewer.setData({
I: leadI,
II: leadII,
III: leadIII,
aVR: leadAVR,
aVL: leadAVL,
aVF: leadAVF,
V1: leadV1,
V2: leadV2,
V3: leadV3,
V4: leadV4,
V5: leadV5,
V6: leadV6,
});
这比在业务代码里手动切 12 个 Canvas、算每个导联的起止坐标要省心得多。
React 和 Vue:包装组件直接上
React:
javascript
import { EcgCanvas } from 'h5ecg/react';
export function ReportView({ samples }: { samples: number[] }) {
return (
<EcgCanvas
data={samples}
mode="6x2-sync"
speed={25}
gain={10}
style={{ height: 520 }}
/>
);
}
Vue:
ini
<script setup lang="ts">
import { EcgCanvas } from 'h5ecg/vue';
const samples = '2025\n2025\n2038';
</script>
<template>
<EcgCanvas
:data="samples"
:options="{ mode: '3x4-continuous', speed: 25, gain: 10 }"
style="height: 520px"
/>
</template>
加上测量尺,让"看图"变成可交互查看
除了展示,组件还支持可拖拽的测量尺,可返回时长、电压和心率估算:
javascript
const viewer = new EcgCanvas(container, {
onRulerChange(measurement) {
console.log(measurement.durationMs);
console.log(measurement.voltageMv);
console.log(measurement.heartRateBpm);
},
});
viewer.setRulerVisible(true);
这些结果建立在 speed、gain、设备标定和缩放比例正确的前提上。也正因为如此,先把数据单位搞清楚,比先调颜色和线宽更重要。
试试看,也欢迎一起完善
在线示例在这里:h5ECG Demo。
项目源码、Issue 和贡献入口在这里:github.com/dongweiq/h5...。
如果这个库帮你少写了一堆 Canvas 坐标计算,欢迎点一个 Star ;如果你也在做医疗可视化、波形渲染或前端组件库,欢迎 Follow 一下。我会持续把实际项目里遇到的性能、交互与数据适配问题沉淀到这个仓库里。