医工互联

 找回密码
 注册[Register]

手机动态码快速登录

手机号快速登录

微信登录

微信扫一扫,快速登录

QQ登录

只需一步,快速开始

查看: 151|回复: 0
收起左侧

使用ES6和Canvas实现模拟ECG心电图效果

[复制链接]

  在线 

发表于 2022-11-5 16:42:45 来自手机 | 显示全部楼层 |阅读模式 <
最近项目中遇到实现ECG心电图效果,此示例只是模拟效果,还不能对接真实数据。
    展现的效果图
  
174505rqnhtts4q2254nnp.png
  本示例使用 ES6 的 class 语法糖,结合 canvas 画布标签实现。
  1. class ECGCanvas {}
复制代码


  • 首先创建类名 ECGCanvas
构造函数
  1. constructor(options={}){
  2.   this.element = options.element || 'canvas'; // canvas元素id
  3.   this.canvas = document.getElementById(this.element);  // canvas对象
  4.   this.context = this.canvas.getContext("2d");  // canvas上下文
  5.   this.context.width = options.width || 250; // canvas宽
  6.   this.context.height = options.height || 100; // canvas高
  7.   this.context.lineWidth = options.lineWidth || 1;  // canvas 绘制线粗细
  8.   this.context.strokeStyle = options.strokeStyle || '#396'; // canvas 绘制线颜色
  9.   this.speed = options.speed || 20; // 绘制速度
  10.   this.point = { x : 0, y : this.context.height / 2 }; // 绘制当前坐标位置
  11.   this.counter = 0; // 计数,为累加用
  12.   this.distance = 10; //  波动间隔
  13.   this.interval = null; // 定时器
  14. }
复制代码
接着实现 ECGCanvas 类的构造函数,对应属性已给出注释,下面几个说明一下


  • point 是要画线的坐标位置,{ x : 0 } 表示横向从画布的最左端开始, { y : this.context.height / 2 } 是纵向从画布的最中间开始。
  • counter 绘制线时做累加用
  • distance 波动间隔,数值越大,波动越不明显
  • interval 做定时器用,绘制动画用 setInterval 实现。
绘制方法draw()
  1. draw(){
  2.   let x = (this.counter += 0.1) * this.distance;
  3.   let y = this.context.height / 2 - Math.tan((Math.cos(this.counter) * Math.random() * 2));
  4.   this.context.beginPath();
  5.   this.context.moveTo(this.point.x, this.point.y)
  6.   this.context.lineTo(x, y);
  7.   this.context.closePath();
  8.   this.context.stroke();
  9.   this.point = { x, y };
  10.   if( this.point.x >= this.context.width ){
  11.     this.reset();
  12.   }
  13. }
复制代码
实现 ECGCanvas 类的绘制线的 draw() 方法


  • x 算法是 counter 累加0.1的结果再与 distance 求乘积。
  • y 的算法是模拟绘制图线上下波动的关键。随机数 Math.random 生成0到1之间的小数,再与 Math.cos 余弦函数的乘积使其波动的概率减小。与 context.height / 2 取差值是为了绘制点的纵向坐标始终在纵向的中心上下波动。正切函数 Math.tan 在某一个间断区间内是递增函数,它的值小概率会接近正负∞,也就是绘制曲线时波动会小概率出现陡增陡降的情况。
reset() 方法
  1. reset(){
  2.   clearInterval(this.interval);
  3.   this.counter = 0;
  4.   this.point = { x : 0, y : this.context.height / 2 };
  5. }
复制代码


  • 停止计时器
  • 重置 counter 和 point
clear() 方法
  1. clear(){
  2.   this.context.clearRect(0, 0, this.context.width, this.context.height);
  3. }
复制代码


  • context.clearRect 清空画布
最后写一个 start() 方法
  1. start(){
  2.   this.reset();
  3.   this.clear();
  4.   clearInterval(this.interval);
  5.   this.interval = setInterval(this.draw.bind(this),this.speed);
  6. }
复制代码


  • 注意 setInterval 中的 this.draw.bind(this)。 ( this 本身的坑,不然现在都推崇 hooks )
现在可以开始测试了
  1. <canvas id="canvas" width="250" height="100"></canvas>
  2. <button onclick="onDraw()">绘制</button>
复制代码


  • 准备一个 canvas 标签,和一个触发绘制功能的按钮。
  1. let ecg = new ECGCanvas();
  2. function onDraw(){
  3.   ecg.start();
  4. }
复制代码


  • 实例化对象,并调用 start 方法绘制心电图。

来源:https://blog.csdn.net/sonicwater/article/details/120433685
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

提醒:禁止复制他人回复等『恶意灌水』行为,违者重罚!
您需要登录后才可以回帖 登录 | 注册[Register] 手机动态码快速登录 微信登录

本版积分规则

发布主题 快速回复 收藏帖子 返回列表 客服中心 搜索
简体中文 繁體中文 English 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french

QQ|RSS订阅|小黑屋|处罚记录|手机版|联系我们|Archiver|医工互联 |粤ICP备2021178090号 |网站地图

GMT+8, 2024-12-22 14:51 , Processed in 0.255221 second(s), 66 queries .

Powered by Discuz!

Copyright © 2001-2023, Discuz! Team.

快速回复 返回顶部 返回列表