原生JS与Canvas实现动态心电图效果
本文介绍如何使用原生JavaScript结合HTML5 Canvas元素,无需任何第三方框架,实现一个动态的心电图模拟效果。通过控制画笔路径、随机波峰波谷及循环机制,展示如何创建逼真的医疗数据可视化动画,适合前端初学者学习Canvas绘图与定时器应用。
项目背景与简介
自2015年2月转型进入IT行业以来,至今已近两载。从最初的Java开发转向前端领域,这一路全靠自我探索与学习。虽不敢称前端大神,但自认已迈出入门步伐。
从最初的懵懂无知,到如今尝试撰写GitHub项目与博客,技术积累尚浅。本文仅分享基于兴趣开发的小型项目,旨在抛砖引玉,恳请资深开发者指正。目前Demo功能已完备,后续将针对样式与代码结构进行优化。
项目运行效果展示如下:

项目简介:本示例利用原生JavaScript配合Canvas技术制作模拟心电图的HTML页面。虽然项目随Vue.js单页应用打包发布至GitHub,但核心逻辑并不依赖任何额外框架或样式库。读者可直接使用原生技术完成该Demo,接下来我们将逐步拆解实现过程。
Canvas初始化与变量定义
第一步:在页面中创建Canvas画布。为了让心电图的“线条”在页面上动态呈现,Canvas是不可或缺的工具。鉴于本项目结构较为简单,至此页面的DOM元素构建已完成,后续主要工作量将集中在JavaScript逻辑部分。
<div class="heartBeat">
<canvas id="can">Canvas画板</canvas>
</div>
第二步:定义并初始化若干变量,这些变量将在运行过程中用于关键计算。
var can = document.getElementById('can'),//画布对象
pan,//获取2D图像API接口
index = 0,//用来接收setinerval的值
flag = true,//用来控制心电图折线的运行方向
wid = document.body.clientWidth,//获取浏览器宽度
hei = document.body.clientHeight,//获取浏览器高度
x = 0,//心电图的“点”在画布上的x轴坐标,从0开始
y = hei/2;//心电图的“点”在画布上的y轴坐标,从页面y轴居中位置开始
第三步:初始化画布配置,设定各项属性参数。
function start(){
can.height = hei;//设置画布高度
can.width = wid;//设置画布宽度
pan = can.getContext("2d");//获取2D图像API接口
pan.strokeStyle = "#08b95a";//设置画笔颜色
pan.lineJoin = "round";//设置画笔轨迹基于圆点拼接
pan.lineWidth = 9;//设置画笔粗细
pan.beginPath();//开始一条画笔的路径
pan.moveTo(x,y);//定位我们的“落笔点”
index = setInterval(move,1);//让我们的画笔动起来
};
值得注意的是,此阶段尚未涉及实际的“绘制”动作,仅完成了画布尺寸的初始化,使其填满屏幕,并预设了画笔颜色、线条粗细及初始落点等操作。随后,利用setInterval方法使画笔按照计算出的路径持续运动。若对setInterval不熟悉,建议查阅相关用法文档,此处不再赘述。为了实现心电图的无限循环与自动执行,我们将核心逻辑封装为start()函数。当心电图线条运动至屏幕最右端时,重新调用start()函数即可实现循环播放。
核心动画逻辑实现
第四步:让心电图“动”起来。前几步操作并无高难度,真正的核心代码在于控制心电图的运动轨迹,使其按照预期路径行进。接下来,我们将使心电图真正“活”起来。
function move(){
x++;//x轴是始终运动的,所以x一直自增
if(x < 100){
//前100px,我们不希望做垂直运动,让点只沿垂直方向运动即可,所以不做任何操作
}else{
if(x >= wid - 100){
//最后的100px,同样希望心电图只做水平运动,不会上下波动,所以不做任何操作
}else{
//为了让心电图看起来更加逼真,我们希望心电图在运动时每次的波峰和波谷都是随机的,这样更类似于人类的心跳,所以我们给它一个随机值z
var z = Math.random()*280;
if(y <= z){
//画布的坐标是从左上角开始计算的,也就是最左上角的点的坐标是(0,0),y是当前画笔所在坐标的y轴,假如y小于z,就代表y已经到达波峰位置,准备开始向波谷运动
flag = true
}
if((hei - y) <= z){
//假如当前画笔在y轴的坐标y距离浏览器底部hei的差值已经小于随机值z,代表当前的画笔已经运行到波谷位置,准备转向波峰位置运动
flag = false
}
if(flag){
//假如flag为true,代表画笔仍然向波谷位置前进,需要花点功夫理解的是,因为画布左上角的点的坐标是(0,0),所以y的值越大,画笔在y轴的位置越靠近浏览器底部,所以向波谷运动时,y的值是不断增加的,同时为了让波峰波谷更陡峭,我这里设置y += 5,
y+=5
}else{
//假如flag为false,表示向波峰运动,y的值是不断减小的
y-=5
}
}
}
if(x == wid){
//当画笔运动到浏览器右侧边缘,停止绘图
pan.closePath();
//清除循环
clearInterval(index);
//将index置零,准备下一次循环
index = 0;
//重新定位画笔到屏幕左侧上下居中的位置
x = 0;
y = hei/2;
flag = true;
//重新进行下一次心电图的绘制
start();
}
//lineTo和stroke函数负责描绘运动轨迹
pan.lineTo(x,y);
pan.stroke();
}
关键注意事项
第五步:注意事项。至此,心电图已具备运行条件,但需注意将body的高度设置为100%,否则画布可能无法完全撑满整个页面,影响显示效果。
html,body{
width: 100%;
height: 100%;
margin: 0;
}
项目完整代码展示如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模拟心电图</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<style>
html,body{
width: 100%;
height: 100%;
margin: 0;
}
</style>
</head>
<body>
<div id="canvas">
<canvas id="can">Canvas画板</canvas>
</div>
<script src="js/vue.min.js"></script>
<script>
var can = document.getElementById('can'),
pan,
index = 0,
flag = true,
wid = document.body.clientWidth,
hei = document.body.clientHeight,
x = 0,
y = hei/2;
start();
function start(){
can.height = hei;
can.width = wid;
pan = can.getContext("2d");//获取2D图像API接口
pan.strokeStyle = "#08b95a";//设置画笔颜色
pan.lineJoin = "round";//设置画笔轨迹基于圆点拼接
pan.lineWidth = 9;//设置画笔粗细
pan.beginPath();
pan.moveTo(x,y);
index = setInterval(move,1);
};
function move(){
x++;
if(x < 100){
}else{
if(x >= wid - 100){
}else{
var z = Math.random()*280;
if(y <= z){
flag = true
}
if((hei - y) <= z){
flag = false
}
if(flag){
y+=5
}else{
y-=5
}
}
}
if(x == wid){
pan.closePath();
clearInterval(index);
index = 0;
x = 0;
y = hei/2;
flag = true;
start();
}
pan.lineTo(x,y);
pan.stroke();
}
/* */
</script>
</body>
</html>
以上关于使用原生JavaScript结合Canvas实现模拟心电图的实例分享完毕,希望能为读者提供参考,也欢迎多多支持。
JavaScript将图片转换为Base64编码的两种途径
2026-11-05 16:43:05
怎么在 Vue 或 React 项目中正确集成 animate.js
2026-11-05 10:23:38
JS注册事件:addEventListener基础语法与参数详解
2026-11-05 08:44:56
JSP和JS的区别:运行环境与服务端/客户端职责解析
2026-11-04 23:34:36
pdf.js 官方下载地址:GitHub Release 获取预编译包
2026-11-04 23:07:27
