【图解鸿蒙】使用绘图组件Canvas绘制心率曲线图

开发
文章由鸿蒙社区产出,想要了解更多内容请前往:51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com/#zz

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz

一、运行效果

在页面中显示页面标题、心率曲线图、心率最大值及其图标、心率最小值及其图标、心率在每分钟内的平均次数。如下图所示:

二、实现思路

在页面的生命周期事件函数onInit()中,随机生成若干个指定范围内的整数,以作为所有的心率数据。根据随机生成的整数统计所有心率的最大值、最小值和平均值,并通过动态绑定的方式将其显示在页面中。使用组件chart绘制心率曲线图。通过动态绑定的方式指定组件chart中属性options和datasets的值,以对图形的参数进行设置。

三、代码详解

打开文件index.hml。

将组件text中显示的页面标题修改为:心率曲线,并在其外层嵌套一个组件div,以便对其样式进行设置。将该组件div的属性class的值设置为"title-container"。

在页面标题的下方添加一个组件div以显示心率曲线图,并将属性class的值设置为"chart"。

在心率曲线图的下方添加一个组件list,以显示心率的最大值、最小值及其图标,并将属性class的值设置为"list"。

在组件list的内部嵌套一个组件list-item以显示列表中的每个列表项,并将属性class的值设置为"list-item"。通过动态绑定的方式指定属性for的值为"{{maxmin}}",从而对index.js中data里面的maxmin进行迭代。

每个列表项都由一张图片和一个文本组成,因此在组件list-item中添加一个组件image和一个组件text。

在组件image中将属性class的值设置为"icon",并通过动态绑定的方式将属性src的值设置为"/common/{{$item.iconName}}.png"。这样,report2.js中data里面的maxmin可以是一个字典的数组,数组中的每个字典都包含一个key为iconName的元素。

在组件text中将属性class的值设置为"maxmin",并通过动态绑定的方式将显示的文本设置为"{{$item.mValue}}"。这样,对于index.js中data里面的数组maxmin,其中的每个字典都包含一个key为mValue的元素。

在列表的下方添加一个组件div以显示心率在一分钟内的平均次数,并将属性class的值设置为" average-container "。

在组件div中嵌套定义三个组件text,其属性class的值分别为:"average"、"average-number"和"average",其显示的文本分别为:平均、{{average}}、次/分。

上述讲解请见如下代码:

  1. <div class="container" onswipe="toNextPage"
  2.     <div class="title-container"
  3.         <text class="title"
  4.             心率曲线 
  5.         </text> 
  6.     </div> 
  7.     <div class="chart"
  8.  
  9.     </div> 
  10.     <list class="list"
  11.         <list-item class="list-item" for="{{maxmin}}"
  12.             <image class="icon" src="/common/{{$item.iconName}}.png"/> 
  13.             <text class="maxmin"
  14.                 {{$item.mValue}} 
  15.             </text> 
  16.         </list-item> 
  17.     </list> 
  18.     <div class="average-container"
  19.         <text class="average"
  20.             平均 
  21.         </text> 
  22.         <text class="average-number"
  23.             {{average}} 
  24.         </text> 
  25.         <text class="average"
  26.             次/分 
  27.         </text> 
  28.     </div> 
  29. </div> 

 打开文件index.css。

在类选择器container中删除样式display、left和top。将flex-direction的值设置为column,以在竖直方向上排列容器内的所有组件。将justify-content的值修改为flex-start,以让容器内的所有组件在主轴上向上对齐。

在类选择器title中删除样式text-align、width和height。将font-size的值修改为38px。将margin-top的值设置为40px,以让页面标题与页面的上边缘保持一定的间距。

添加一个名为title-container的类选择器,以设置页面标题的样式。将justify-content和align-items都设置为center,以让容器内的组件在水平方向和竖直方向都居中对齐。将宽度width和高度height的值分别设置为300px和130px。

添加一个名为chart的类选择器,以设置心率曲线图的样式。将宽度width和高度height的值分别设置为400px和180px。

添加一个名为list的类选择器,以设置列表的样式。将flex-direction的值设置为row,以在水平方向上排列所有列表项。将宽度width和高度height的值分别设置为240px和45px。

添加一个名为list-item的类选择器,以设置列表项的样式。将justify-content和align-items都设置为center,以让列表项内的组件在水平方向和竖直方向都居中对齐。将宽度width和高度height的值分别设置为120px和45px。

添加一个名为icon的类选择器,以设置心率的最大值图标和最小值图标的样式。将宽度width和高度height的值分别设置为32px和32px。

添加一个名为maxmin的类选择器,以设置心率的最大值文本和最小值文本的样式。将font-size的值设置为24px。将letter-spacing的值设置为0px,以让数字之间的间距更紧凑。

添加一个名为average-container的类选择器,以设置心率平均值的相关文本的样式。将justify-content的值设置为space-between,以让容器内的组件在水平方向上两端对齐。将align-items的值设置为center,以让容器内的组件在竖直方向上居中对齐。将宽度width和高度height的值分别设置为280px和55px。

添加一个名为average-number的类选择器,以设置心率平均值的样式。将font-size的值设置为38px。将letter-spacing的值设置为0px,以让数字之间的间距更紧凑。

添加一个名为average的类选择器,以设置心率平均值的两边文本的样式。将font-size的值设置为24px。将color的值设置为gray,以将文本显示为灰色。

上述讲解请见如下代码:

  1. .container { 
  2.        display: flex; 
  3.     flex-direction: column
  4.     justify-content: flex-start; 
  5.     align-items: center; 
  6.     left: 0px; 
  7.     top: 0px; 
  8.     width: 454px; 
  9.     height: 454px; 
  10. .title-container { 
  11.     justify-content: center; 
  12.     align-items: center; 
  13.     width: 300px; 
  14.     height: 130px; 
  15. .title { 
  16.     margin-top: 40px; 
  17.     font-size: 38px; 
  18.     text-align: center; 
  19.     width: 454px; 
  20.     height: 100px; 
  21. .chart { 
  22.     width: 400px; 
  23.     height: 180px; 
  24. .list { 
  25.     flex-direction: row; 
  26.     width: 240px; 
  27.     height: 45px; 
  28. .list-item { 
  29.     justify-content: center; 
  30.     align-items: center; 
  31.     width: 120px; 
  32.     height: 45px; 
  33. .icon { 
  34.     width: 32px; 
  35.     height: 32px; 
  36. .maxmin { 
  37.     font-size: 24px; 
  38.     letter-spacing: 0px; 
  39. .average-container { 
  40.     justify-content: space-between
  41.     align-items: center; 
  42.     width: 280px; 
  43.     height: 55px; 
  44. .average { 
  45.     font-size: 24px; 
  46.     color: gray; 
  47. .average-number { 
  48.     font-size: 38px; 
  49.     letter-spacing: 0px; 

 把心率最大值图标max.png和心率最小值图标min.png添加到目录common中。

打开文件index.js。

在data中将占位符maxmin初始化为一个字典数组。该数组中包含两个字典,分别表示心率最大值和心率最小值的相关信息。每个字典中都有两个元素,对应的key都是iconName和mValue,分别表示心率最值的图标名称和心率最值。对于第一个字典,将心率最大值的图标名称iconName初始化为'max',并将心率最大值初始化为0。对于第二个字典,将心率最小值的图标名称iconName初始化为'min',并将心率最小值初始化为0。

在data中将占位符average初始化为0。

上述讲解请见如下代码:

  1. import router from '@system.router' 
  2.  
  3. export default { 
  4.     data: { 
  5.         maxmin: [{ 
  6.                      iconName: 'max'
  7.                      mValue: 0 
  8.                  }, 
  9.                  { 
  10.                      iconName: 'min'
  11.                      mValue: 0 
  12.                  }], 
  13.         average: 0 
  14.     } 

 在index.js中自定义一个名为getRandomInt的函数,该函数用于随机生成一个介于min和max之间(包含min和max)的整数。

在页面的生命周期事件函数onInit()里,首先创建一个空数组并赋值给局部作用域变量heartRates,然后通过for循环执行100次迭代。在每一次迭代中,调用自定义函数getRandomInt()随机生成一个介于73和159之间的整数,并调用函数push()将随机生成的整数添加到数组heartRates中。

定义一个名为countMaxMinAverage的函数,其形参为heartRates,该函数用于计算heartRates中所有元素的最大值、最小值和平均值。

在函数onInit()的最后,调用自定义函数countMaxMinAverage (),并将heartRates作为实参传递给形参heartRates。

上述讲解请见如下代码:

  1. import router from '@system.router' 
  2.  
  3. export default { 
  4.     data: { 
  5.             ...... 
  6.     }, 
  7.     onInit() { 
  8.         let heartRates = []; 
  9.         for (let i = 0; i < 100; i++) { 
  10.             heartRates.push(this.getRandomInt(73, 159)); 
  11.         } 
  12.         this.countMaxMinAverage(heartRates); 
  13.     }, 
  14.     getRandomInt(minmax) { 
  15.         return Math.floor(Math.random() * (max - min + 1) ) + min
  16.     }, 
  17.     countMaxMinAverage(heartRates) { 
  18.  
  19.     } 

 在自定义函数countMaxMinAverage ()的函数体中,分别调用Math.max.apply()和Math.min.apply()计算数组heartRates中的最大值和最小值,然后分别赋值给data中的maxmin[0].mValue和maxmin[1].mValue。通过for循环对数组heartRates中的所有心率数据进行遍历,在遍历的过程中将心率数据累加到局部作用域变量sum,以计算数组heartRates中所有心率数据的总和。求出总和之后,将其除以所有心率数据的个数就得到了所有心率数据的平均值。调用函数Math.round()返回与心率平均值最接近的整数,并将其赋值给data中的average。

上述讲解请见如下代码:

  1. import router from '@system.router' 
  2.  
  3. export default { 
  4.         ...... 
  5.     countMaxMinAverage(heartRates) { 
  6.         this.maxmin[0].mValue = Math.max.apply(null, heartRates); 
  7.         this.maxmin[1].mValue = Math.min.apply(null, heartRates); 
  8.  
  9.         let sum = 0; 
  10.         for (let index = 0; index < heartRates.length; index++) { 
  11.             sum += heartRates[index]; 
  12.         } 
  13.         this.average = Math.round(sum / heartRates.length); 
  14.     }, 
  15.         ...... 

 保存所有代码后打开模拟器,在页面中显示出了页面标题、心率最大值及其图标、心率最小值及其图标、心率在每分钟内的平均次数,运行效果如图所示:


打开文件index.hml。

将组件list上方的组件div修改为chart,以绘制一张心率曲线图。在组件chart中,通过动态绑定的方式将属性options和datasets的值分别设置为"{{options}}"和"{{datasets}}"。

上述讲解请见如下代码:

  1. <div class="container" onswipe="toNextPage"
  2.     <div class="title-container"
  3.         <text class="title"
  4.             心率曲线 
  5.         </text> 
  6.     </div> 
  7.     <chart class="chart" options="{{options}}" datasets="{{datasets}}"/> 
  8.     <list class="list"
  9.         ......     
  10.     </list> 
  11.     ...... 
  12. </div 

 打开文件index.js。

在data中将占位符options的值初始化为一个字典,字典中包含两个元素,分别用于设置x轴和y轴的参数。第一个元素的key是xAxis,对应的value是一个空字典{},说明不需要对x轴的参数进行设置。第二个元素的key是yAxis,对应的value是一个由两个元素组成的字典,分别用于设置y轴的最小值和最大值,其中,key分别是min和max,value分别是0和160。

在data中将占位符datasets的值初始化为一个字典的数组,该数组中只包含一个字典,该字典中包含两个元素。第一个元素的key是gradient,对应的value是true,用于表示折线向下填充颜色到x轴。第二个元素的key是data,对应的value是一个空数组[],用于指定心率图中的数据。

在页面的生命周期事件函数onInit()中,在随机生成100个整数之后将所有整数组成的数组赋值给data中的datasets[0].data。

上述讲解请见如下代码:

  1. import router from '@system.router' 
  2.  
  3. export default { 
  4.     data: { 
  5.         ......       
  6.                 average: 0, 
  7.         options: { 
  8.             xAxis: {}, 
  9.             yAxis: { 
  10.                 min: 0, 
  11.                 max: 160 
  12.             } 
  13.         }, 
  14.         datasets: [{ 
  15.                        gradient: true
  16.                        data: [] 
  17.                    }] 
  18.     }, 
  19.     onInit() { 
  20.         let heartRates = []; 
  21.         for (let i = 0; i < 100; i++) { 
  22.             heartRates.push(this.getRandomInt(73, 159)); 
  23.         } 
  24.         this.datasets[0].data = heartRates; 
  25.         this.countMaxMinAverage(heartRates); 
  26.     }, 
  27.     ...... 

 保存所有代码后打开模拟器,运行效果如下图所示:


项目源代码,请见附件。

欢迎订阅我的专栏【图解鸿蒙】:

https://harmonyos.51cto.com/column/27

©著作权归作者和HarmonyOS技术社区共同所有,如需转载,请注明出处,否则将追究法律责任

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-01-06 10:05:09

鸿蒙HarmonyOSCanvas

2013-05-20 16:12:23

2013-06-09 11:18:44

C++程序员

2012-02-22 15:41:50

HTML 5

2022-06-10 15:51:22

机器学习数据模型学习

2011-04-20 09:37:59

amChartsWPF

2012-02-24 15:28:36

ibmdw

2022-02-28 15:52:07

canvasHarmonyOS鸿蒙

2020-12-28 10:15:18

鸿蒙HarmonyOSListContain

2022-02-23 15:17:04

鸿蒙OpenHarmonJacascript

2022-02-14 14:14:02

鸿蒙数据可视化JS

2014-04-29 14:27:59

OpenGL ES 2Android绘制纹理

2011-08-12 11:08:45

iPhone绘图QuartZ绘制

2011-08-12 11:01:09

iPhone绘图QuartZ绘制

2012-05-31 09:19:22

HTML5

2011-08-12 08:56:31

JavaScript

2011-08-12 10:46:18

iPhone绘图绘制QuartZ

2011-06-13 17:17:22

Qt 绘图 QWT

2022-07-05 16:21:44

绘制表盘鸿蒙

2011-08-11 09:16:50

JavaScript
点赞
收藏

51CTO技术栈公众号