HarmonyOS - 基于ArkUI(ETS) 实现心电图组件

系统 OpenHarmony
绘制这个心电图没有用到重绘机制,动画效果是每次绘制的时候覆盖在原有的波形线上的,但是这样会比重绘整个画布性能更好一些。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

前言

随着大家生活水平的提升,越来越多的人注重自身身心健康,养生成了目前比较热门的活动。心电图是检测心脏活动状态的直观表现,可以通过心电图来观察人提的健康状况。
响应鸿蒙万物互联的口号,肯定少不了智能设备和心电检测设备的互联。所以本文实现了简单的心电图功能UI展示。

效果图

#打卡不停更# HarmonyOS - 基于ArkUI(ETS) 实现心电图组件-开源基础软件社区

组件API

ygEcg

属性名

类型

默认值

描述

ecgData

​EcgDataType​

-

配置心电图的信息

接口 EcgDataType

参数名

参数类型

必填

默认值

参数描述

data

Array<number>


-

心电数据源

timeStep

number


40

每一小格代表时间(毫秒),x轴方向

mvStep

number


0.1

每小格表示电压(毫伏/mv),y轴方向

waveLineColor

string


-

波线颜色

gridColor

Array<string>


-

网格颜色,第一个为小网格,第二个为大网格

maxTime

number


-

图标显示最大时间区域(毫秒)

width

number


-

画布宽度

height

number


-

画布高度

backgroundColor

string


-

画布背景色

组件调用

// import 引入接口和组件
import ygEcg,{EcgDataType} from './../common/compontents/ygEcg'
@Entry
@Component
struct Index {
@State ecgData:EcgDataType = {
data: [
0, 0, 0, 0.1, 0, 0, 0, -0.2, 1.5, -0.4, 0, 0, 0, 0.1, 0.2, 0.1, 0, 0, 0,
0, 0, 0, 0.1, 0, 0, 0, -0.2, 1.0, -0.4, 0, 0, 0, 0.1, 0.2, 0.1, 0, 0, 0,
0, 0, 0, 0.1, 0, 0, 0, -0.2, 1.0, -0.4, 0, 0.1, 0, 0.1, 0.2, 0.1, 0, 0, 0,
0, 0, 0, 0.1, 0, 0, 0, -0.2, 2.0, -0.3, 0, 0, 0, 0.1, 0.2, 0.1, 0, 0, 0,
0, 0, 0, 0.1, 0, 0, 0, -0.2, 1.0, -0.4, 0, 0, -0.1, 0.1, 0.2, 0.4, 0, 0, 0,
0, 0, 0, 0.1, 0, 0, 0, -0.2, 1.0, -0.4, 0, 0, 0, 0.1, 0.2, 0.2, 0, 0, 0,
0, 0, 0, 0.1, 0, 0, 0, -0.2, 1.0, -0.4, 0, 0.1, 0, 0.1, 0.2, 0.1, 0, 0, 0,
0, 0, 0, 0.1, 0, 0, 0, -0.2, 1.0, -0.4, 0, 0, 0, 0.1, 0.2, 0.1, 0, 0, 0,
0, 0, 0, 0.1, 0, 0, 0, -0.2, 1.0, -0.4, 0, 0, 0, 0.1, 0.2, 0.1, 0, 0, 0,
],
timeStep: 40, // 每一小格表示40毫秒,x轴方向
mvStep: 0.1, // 每小格表示0.1mv,y轴方向
waveLineColor: '#181818', // 波线颜色
gridColor: ['#ffa5a5','#dd0000'], // 网格颜色,第一个为小网格,第二个为大网格
maxTime: 6000,
width: 700,
height: 300,
backgroundColor: '#fff'
}
build() {
Row(){
ygEcg({ecgData: $ecgData})
}
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.width('100%')
.height('100%')
// .backgroundColor('#151515')
}
}

实现前的准备

在写这个demo之前,以为心电图应该就是现在简单的上下波动的折线图。

实现原理

通过使用canvas组件,绘制一个类似医学上的心电图纸网格,然后通过心电源数据,绘制对应的折线形成心电波形。

实现过程

1、创建canvas画布

@Component
struct ygEcg {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private ctx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
@Link ecgData: EcgDataType;
build() {
Canvas(this.ctx)
.onReady(()=>{
})
.width(this.ecgData.width)
.height(this.ecgData.height)
.backgroundColor(this.ecgData.backgroundColor)
}
}

2、绘制小网格

因为通上面的心电波形图解得知,默认一个小网格的走纸速度是0.04秒,也就是40毫秒,通过传入的数据timeStep字段控制
那么要绘制多少个小格呢?通过画布宽度,和maxTime字段(最大的显示时间,上面代码案例是6000毫秒)可以计算得知,将要绘制。
6000/40=150小格。

// 组件生命周期
aboutToAppear() {
// 计算每1小格需要绘制的宽度
this.littleGridSize = Math.floor(this.ecgData.width / (this.ecgData.maxTime / this.ecgData.timeStep))
// 计算每1大格需要绘制的宽度(每5小格是1大格)
this.LargeGridSize = this.littleGridSize * 5
}
// 绘制小格
drawLittleGrid = ():void => {
let c = this.ctx;
let {width:w, height: h} = this.ecgData;
c.strokeStyle = this.ecgData.gridColor[0];
c.lineWidth = 0.5;
c.beginPath();
for(let x = 0; x <= w; x += this.littleGridSize){
c.moveTo(x, 0)
c.lineTo(x, h)
c.stroke()
}
for(let y = 0; y <= h; y += this.littleGridSize){
c.moveTo(0, y)
c.lineTo(w, y)
c.stroke()
}
c.closePath();
}

3、绘制大网格

每1大格等于5小格。

//  绘制大格
drawLargeGrid = ():void => {
let c = this.ctx;
let {width:w, height: h} = this.ecgData;
let lg = this.LargeGridSize;
c.strokeStyle = this.ecgData.gridColor[1];
c.lineWidth = 0.5;
c.beginPath();
for(let x = 0; x <= w; x += lg){
c.moveTo(x, 0);
c.lineTo(x, h);
c.stroke();
}
for(let y = 0; y <= h; y += lg){
c.moveTo(0, y);
c.lineTo(w, y);
c.stroke();
}
c.closePath();
}

最后绘制的结果如图:

#打卡不停更# HarmonyOS - 基于ArkUI(ETS) 实现心电图组件-开源基础软件社区

4、绘制心电波形

获取画布高度的一半位置,作为心电波形的基线,在基线的基础上,通过心电数据源,将每个数据在基线上通过对数据的偏于来绘制点线,最后形成一个折线状态的心电波形线。

// 数据视图更新
update = (data?: Array<number>):void => {
let c = this.ctx;
// c.clearRect(0, 0, this.ecgData.width, this.ecgData.height)
c.beginPath();
c.strokeStyle = this.ecgData.waveLineColor;
c.lineWidth = 1.2;
c.lineJoin = 'round'
c.lineCap = 'round'
let point = data || this.ecgData.data;
if(point.length === 0) return;

//开始遍历输出数据
c.moveTo(0, Math.floor(this.ecgData.height / 2))
for (let i = 0; i < point.length; i++) {
let x = i * this.littleGridSize;
let y = Math.floor(this.ecgData.height / 2) + point[i] * this.LargeGridSize * -1
c.lineTo(x, y);
c.stroke();
}
c.closePath();

}

刷新预览器看看效果:

#打卡不停更# HarmonyOS - 基于ArkUI(ETS) 实现心电图组件-开源基础软件社区

5、最后一步实现心跳的动画效果

这里的动画刷新时间是根据配置的心电图步长来做定时器的时间,默认是40毫秒,也就是每一小格走纸的时间。这样就可以保持跟实际时间对应,不会出现心跳快慢的问题。
当然,这里还是有写误差的,因为代码执行的过程也是消耗时间的,会比实际时间多一丢丢。

//  获取心律数据
getEcgData = ():void => {
let points = this.ecgData.data;
//最后传递出去的数据
let pointsLast = [];
//当前取到了第几个数据了
let currInedx = 0;
let timer = null;
clearInterval(timer)
timer = setInterval( ()=> {
if(currInedx < points.length){
currInedx ++;
pointsLast = points.slice(0,currInedx)
this.update(pointsLast)
} else {
clearInterval(timer)
}
},this.ecgData.timeStep)
}

最后再来看一下心电图的动画效果:

#打卡不停更# HarmonyOS - 基于ArkUI(ETS) 实现心电图组件-开源基础软件社区

代码地址

​https://gitee.com/yango520/yg-ecg2​

总结

绘制这个心电图没有用到重绘机制,动画效果是每次绘制的时候覆盖在原有的波形线上的,但是这样会比重绘整个画布性能更好一些。
通过实现这个demo之后,对心电图上的信息有了全新的了解,我觉得大家都可以去学会看心电图来分析心脏状况,自己理解了总比别人告知更有说服力。

避坑小技巧

  1. 当代码大变更的时候(一般复制出来单独做一个文件的时候),需要在build选项卡里清理项目,不然也不报错,也不刷新,但是样式就是错乱。
  2. 预览器开久了之后,当一段时间不动了,再次刷新开启都一直卡着开启中进不去,需要关闭IDE重新打开才可以用。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

责任编辑:jianghua 来源: 51CTO开源基础软件社区
相关推荐

2022-11-02 16:06:54

ArkUIETS

2022-07-04 16:34:46

流光按钮Stack

2022-10-17 14:36:09

ArkUI虚拟摇杆组件

2022-09-05 15:22:27

ArkUIets

2022-09-16 15:34:32

CanvasArkUI

2022-07-26 14:40:42

ArkUIJS

2022-05-26 14:50:15

ArkUITS扩展

2022-02-23 15:07:22

HarmonyOS常用控制ArkUI-eTS

2022-01-25 17:05:44

ArkUI_eTS操作系统鸿蒙

2022-09-15 15:04:16

ArkUI鸿蒙

2021-11-26 10:08:57

鸿蒙HarmonyOS应用

2022-08-05 19:27:22

通用API鸿蒙

2022-09-14 15:17:26

ArkUI鸿蒙

2022-10-09 15:13:18

TextPickerArkUI eTS

2022-10-10 14:51:51

ArkUI eTSPieChart组件

2022-02-23 15:36:46

ArkUI-eTS事件监听鸿蒙

2022-09-21 14:51:21

ArkUI信件弹出

2022-07-13 16:24:12

ArkUI(JS)打地鼠游戏

2022-08-22 17:28:34

ArkUI鸿蒙

2022-07-05 16:13:37

ArkUI-eTS智能晾晒系统
点赞
收藏

51CTO技术栈公众号