[Diagram Hongmeng] Use the drawing component Canvas to draw a heart rate curve

1. Operation effect

    The page title, heart rate graph, maximum heart rate and its icon, minimum heart rate and its icon, and the average number of heart rates per minute are displayed on the page. As shown below:

Two, realization of ideas

    In the life cycle event function onInit() of the page, a number of integers within a specified range are randomly generated as all heart rate data. Count the maximum, minimum and average values ​​of all heart rates based on randomly generated integers, and display them on the page through dynamic binding. Use component chart to draw heart rate graph. Specify the values ​​of the properties options and datasets in the component chart through dynamic binding to set the parameters of the graphics.

Three, detailed code

    Open the file index.hml.
    Modify the page title displayed in the component text to: heart rate curve, and nest a component div on the outer layer to set its style. Set the attribute class value of the component div to "title-container".
    Add a component div below the page title to display the heart rate graph, and set the value of the attribute class to "chart".
    Add a component list below the heart rate graph to display the maximum, minimum and icon of the heart rate, and set the attribute class value to "list".
    Nest a component list-item inside the component list to display each list item in the list, and set the value of the attribute class to "list-item". Specify the value of the attribute for to be "{{maxmin}}" through dynamic binding, so as to iterate the maxmin in data in index.js.
    Each list item consists of an image and a text, so add a component image and a component text to the component list-item.
    Set the attribute class value to "icon" in the component image, and set the attribute src value to "/common/{{$item.iconName}}.png" through dynamic binding. In this way, the maxmin in data in report2.js can be an array of dictionaries, and each dictionary in the array contains an element whose key is iconName.
    Set the value of the attribute class to "maxmin" in the component text, and set the displayed text to "{{$item.mValue}}" through dynamic binding. In this way, for index.
    Add a component div at the bottom of the list to display the average number of heart rate in one minute, and set the value of the attribute class to "average-container".
    Define three component texts nested in the component div. The values ​​of the attribute class are: "average", "average-number" and "average". The displayed texts are: average, {{average}}, time /Minute.
    Please see the following code for the above explanation:

<div class="container" onswipe="toNextPage">
    <div class="title-container">
        <text class="title">
            Heart rate curve
        </text>
    </div>
    <div class="chart">

    </div>
    <list class="list">
        <list-item class="list-item" for="{{maxmin}}">
            <image class="icon" src="/common/{{$item.iconName}}.png"/>
            <text class="maxmin">
                {{$item.mValue}}
            </text>
        </list-item>
    </list>
    <div class="average-container">
        <text class="average">
            average
        </text>
        <text class="average-number">
            {{average}}
        </text>
        <text class="average">
            Times/min
        </text>
    </div>
</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,以将文本显示为灰色。

    上述讲解请见如下代码:

.container {
       display: flex;
	flex-direction: column;
	justify-content: flex-start;
	align-items: center;
	left: 0px;
	top: 0px;
	width: 454px;
	height: 454px;
}
.title-container {
	justify-content: center;
	align-items: center;
	width: 300px;
	height: 130px;
}
.title {
	margin-top: 40px;
	font-size: 38px;
	text-align: center;
	width: 454px;
	height: 100px;
}
.chart {
	width: 400px;
	height: 180px;
}
.list {
	flex-direction: row;
	width: 240px;
	height: 45px;
}
.list-item {
	justify-content: center;
	align-items: center;
	width: 120px;
	height: 45px;
}
.icon {
	width: 32px;
	height: 32px;
}
.maxmin {
	font-size: 24px;
	letter-spacing: 0px;
}
.average-container {
	justify-content: space-between;
	align-items: center;
	width: 280px;
	height: 55px;
}
.average {
	font-size: 24px;
	color: gray;
}
.average-number {
	font-size: 38px;
	letter-spacing: 0px;
}

    把心率最大值图标max.png和心率最小值图标min.png添加到目录common中。
    打开文件index.js。
    在data中将占位符maxmin初始化为一个字典数组。该数组中包含两个字典,分别表示心率最大值和心率最小值的相关信息。每个字典中都有两个元素,对应的key都是iconName和mValue,分别表示心率最值的图标名称和心率最值。对于第一个字典,将心率最大值的图标名称iconName初始化为'max',并将心率最大值初始化为0。对于第二个字典,将心率最小值的图标名称iconName初始化为'min',并将心率最小值初始化为0。
    在data中将占位符average初始化为0。
    上述讲解请见如下代码:

import router from '@system.router'

export default {
	data: {
		maxmin: [{
			         iconName: 'max',
			         mValue: 0
		         },
		         {
			         iconName: 'min',
			         mValue: 0
		         }],
		average: 0
	}
}

    在index.js中自定义一个名为getRandomInt的函数,该函数用于随机生成一个介于min和max之间(包含min和max)的整数。
    在页面的生命周期事件函数onInit()里,首先创建一个空数组并赋值给局部作用域变量heartRates,然后通过for循环执行100次迭代。在每一次迭代中,调用自定义函数getRandomInt()随机生成一个介于73和159之间的整数,并调用函数push()将随机生成的整数添加到数组heartRates中。
    定义一个名为countMaxMinAverage的函数,其形参为heartRates,该函数用于计算heartRates中所有元素的最大值、最小值和平均值。
    在函数onInit()的最后,调用自定义函数countMaxMinAverage (),并将heartRates作为实参传递给形参heartRates。
    上述讲解请见如下代码:

import router from '@system.router'

export default {
	data: {
            ......
	},
	onInit() {
		let heartRates = [];
		for (let i = 0; i < 100; i++) {
			heartRates.push(this.getRandomInt(73, 159));
		}
		this.countMaxMinAverage(heartRates);
	},
	getRandomInt(min, max) {
		return Math.floor(Math.random() * (max - min + 1) ) + min;
	},
	countMaxMinAverage(heartRates) {

	}
}

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

import router from '@system.router'

export default {
        ......
	countMaxMinAverage(heartRates) {
		this.maxmin[0].mValue = Math.max.apply(null, heartRates);
		this.maxmin[1].mValue = Math.min.apply(null, heartRates);

		let sum = 0;
		for (let index = 0; index < heartRates.length; index++) {
			sum += heartRates[index];
		}
		this.average = Math.round(sum / heartRates.length);
	},
        ......
}

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

    打开文件index.hml。
    将组件list上方的组件div修改为chart,以绘制一张心率曲线图。在组件chart中,通过动态绑定的方式将属性options和datasets的值分别设置为"{{options}}"和"{{datasets}}"。
    上述讲解请见如下代码:

<div class="container" onswipe="toNextPage">
    <div class="title-container">
        <text class="title">
            心率曲线
        </text>
    </div>
    <chart class="chart" options="{{options}}" datasets="{{datasets}}"/>
    <list class="list">
        ......    
    </list>
    ......
</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。
    上述讲解请见如下代码:

import router from '@system.router'

export default {
	data: {
		......		
                average: 0,
		options: {
			xAxis: {},
			yAxis: {
				min: 0,
				max: 160
			}
		},
		datasets: [{
			           gradient: true,
			           data: []
		           }]
	},
	onInit() {
		let heartRates = [];
		for (let i = 0; i < 100; i++) {
			heartRates.push(this.getRandomInt(73, 159));
		}
		this.datasets[0].data = heartRates;
		this.countMaxMinAverage(heartRates);
	},
	......
}

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

项目源代码,请见附件。

 

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

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


文章相关附件可以点击下面的原文链接前往学习
原文链接:https://harmonyos.51cto.com/posts/2265#bkwz


想了解更多关于鸿蒙的内容,请访问:

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

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


Guess you like

Origin blog.51cto.com/14901125/2575813