HarmonyOS(鸿蒙)App项目实战(1)运动手表篇学习笔记

前言

张荣超老师的HarmonyOS(鸿蒙)APP项目实战系列视频是一部非常优秀的入门级视频。张老师用简单易懂的语言教我们如何创建一个项目,内容简单易懂。这些天来和同学们一起对其进行了学习,写下此博客来记录我们的学习过程。以下是原视频地址:https://edu.51cto.com/course/25054.html?hm。
如果有兴趣的同学可以去观看学习
一起学习的小伙伴:
clarelove
谭中浮叶
wei_xin52068433
qq_51250105

概括

本次课程将从零开始完成鸿蒙app呼吸训练项目在可穿戴设备上的编译,在课程中我们所用到的软件为DevEco Studio下载地址如下:https://www.harmonyos.com/cn/home/
在课程中我们要实现的内容为呼吸训练app的开发。
功能如下:
1.在初始界面中间显示鸿蒙的logo,两边有两个滚动选择器来选择训练的时间和强度,下边还有一个按钮来控制app的开始。
在这里插入图片描述

2.点击开始后,会进入倒计时页面,提示使用者准备和注意事项
在这里插入图片描述
3.在倒计时结束后会页面会跳转到训练页面,训练页面有一个logo的旋转,还会显示剩下坚持的时。显示吸气和呼气的进度的百分比。在屏幕的下方还有一个重新开始的按钮,当点击按钮,页面会回到主界面。当训练完成时,会显示已完成,进度百分比为100%。
在这里插入图片描述

创建项目

1.创建新的项目文件:点击左上角的file,点击new,选择Lite Wearable选项,选择默认的模板(如图),然后将文件命名为huxi(文件名路径最好不要出现中文,可能会导致无法创建项目)
在这里插入图片描述

创建主页面

创建index中的组件

首先我们要创建一个主页面。打开index文件夹,里面有三个文件,文件名分别为index.css,index.hml,index.js。我们要完成对主页面的修改就是通过修改这三个文件来完成的。
1.首先我们要打开index.hml文件
在这里插入图片描述

<div class="container1">

创建一个名为container1的区域组件,组件包含一个名为container2
的区域组件和一个按钮组件。

<div class="container2">

创建一个名为container2的区域组件

<picker-view class="pv1" range="{{picker1range}}" selected="1" onchange="changeAction1"/>

创建一个名为pv1 的滚动选择器,里面的数据picker1range通过动态绑定的方式获得,创建一个名为changeAction1的onchange事件,当滚动选择器中的数据发生改变的时候,会引发onchange事件

<text class="txt"></text>

创建一个文本组件,使其显示左边滚动选择器的数据的单位,分

<image src="/common/hm.png" class="img" />

创建一个名为img的图片组件,src为图片的地址

<picker-view class="pv2" range="{{picker2range}}" selected="1" onchange="changeAction2"/>

创建一个名为pv2 的滚动选择器,里面的数据picker2range通过动态绑定的方式获得,创建一个名为changeAction2的onchange事件,当滚动选择器中的数据发生改变的时候,会引发onchange事件

<input type="button" value="点击开始" class="btn" onclick="clickAction"/>

创建一个名为btn的按钮组件,按钮上显示的文字为点击开始,点击按钮会引发clickAction事件。

这样一来我们就在index.hml创建好我们所要用到的组件

设定index中组件的样式

在这里插入图片描述

设定container1组件的样式

flex-direction: column

使在.container1内的元素横向排列

justify-content: center

设置,container居中对齐

align-items: center

使.container1的元素居中对齐

width: 454px;
height: 454px;

规定.container1的范围。Container1在手表上最多显示的范围就是width:454px,
Height:454px这个矩形的内接圆。
在这里插入图片描述

规定container2组件的样式

flex-direction: row;

使在.container2的元素竖向排列

justify-content: center;

使.container2的元素居中对齐

margin-top: 50px;

设定.container2组件的外上边距为50px

width: 454px;
height: 250px;

设定.container2组件的高度和宽度‘
在这里插入图片描述

规定滚动选择器pv1的样式

width: 30px;
height: 250px;

设定滚动选择器pv1的高度和宽度
在这里插入图片描述

规定txt组件的样式

text-align: center;

使txt组件的文本居中对齐

width: 50px;
height: 36px;

设定txt组件的高度和宽度
在这里插入图片描述

规定滚动选择器px2的样式

width: 80px;
height: 250px;

设定滚动选择器pv2的高度和宽度
在这里插入图片描述

规定图片组件的样式

width: 208px;
height: 208px;

设定图片组件的高度和宽度

margin-left: 15px;
margin-right: 15px;

设定图片组件的左边距和右边距
在这里插入图片描述

规定按钮组件的样式

width: 200px;
height: 50px;

设定图片组件的高度和宽度

font-size: 38px;

设定按钮组件字体的大小

background-color: #000000;

设定按钮组件的背景颜色 #000000为黑色

border-color: #000000;

设定按钮组件边框的颜色 #000000为黑色

为主页面添加应有的功能

我们创建完组件,设定好组件的样式后,就可以为我们的主页面添加“一点点”功能了

 import router from '@system.router'

var picker1value = null;
var picker2value = null;

导入要用到的router,声明变量picker1value和picker2value,并初始化变量

 export default {
    data: {
        picker1range: ["1", "2", "3"],
        picker2range: ["较慢", "舒缓", "较快"]
    },

把数据赋予动态绑定的两个滚动选择器中的数据

clickAction() {
router.replace({
uri: ‘pages/daojishi/daojishi’,
params: {“data1”: picker1value, “data2”: picker2value}
});
},

点击按钮所引发的事件,点击按钮会通过router.replace跳转到倒计时页面,并把picker1value和picker2value的值通过字典的形式传递到训练页面

     changeAction1(pv) {
        console.log("左边的选中项:" + pv.newValue);
        picker1value = pv.newValue;
    },
    changeAction2(pv) {
        console.log("右边的选中项:" + pv.newValue);
        picker2value = pv.newValue;
    }
}

当滚动选择器pv1和滚动选择器pv2的值发生改变时所引发的事件。
当滚动器的值发生改变时通过pv.newValue获得改变后的值,并将其给picker1value或者picker2value

这样我们就完成了主页面的所有功能。主页面如下图所示
在这里插入图片描述

创建倒计时页面

在完成主页面的设计后,我们接下来要做一个倒计时页面。首先鼠标右键点击page文件,点击new,创建新文件,选择JS Page
在这里插入图片描述
名字输入为daojishi即可创建一个倒计时页面
在这里插入图片描述

创建daojishi中的组件

在这里插入图片描述

<div class="container">

创建一个区域组件container

<image class="img" src="{{imgsrc}}"/>

创建一个图片组件,图片地址通过动态绑定的方式获得

<text class="txt">
    请保持静止
</text>

创建一个文本组件,内容是显示“请保持静止”

<text class="txt">
    {{seconds}} 秒后跟随训练指引
</text>

创建一个文本组件,内容为多少秒后跟随训练指引,秒数通过动态绑定的方式获得

<text class="txt">
    进行吸气和呼气
</text>

创建一个文本组件,内容是显示“进行吸气和呼气”

设定daojishi组件的样式

在这里插入图片描述

规定 “.container”的组件的样式

flex-direction: column

使在.container内的元素横向排列

justify-content: center

设置,container居中对齐

align-items: center

使.container的元素居中对齐

width: 454px;
height: 454px;

规定.container的范围。Container在手表上最多显示的范围就是width:454px,
Height:454px这个矩形的内接圆。
在这里插入图片描述

规定图片组件的样式

width: 100px;
height: 100px;

设定图片组件的高度和宽度

margin-bottom: 30px;

设定图片组件的下边距
在这里插入图片描述

规定txt1组件的样式

font-size: 38px;

设定txt组件的字体大小为38px,在手表的开发中字体大小一般都是30px或者38px。如没有设定,则系统默认为30px。

text-align: center;

设定txt1组件的文本对齐方式为居中对齐

width: 454px;
height: 50px;

设定txt1的组件的位置

margin-top: 10px;

规定txt1组件的外下边距

为倒计时页面添加应有的功能

import router from '@system.router'

var counter = 3;

var timer = null;

var pv1 = null;
var pv2 = null;

引入router,声明要用到的变量,并初始化它们。

 export default {
    data: {
        imgsrc: "",
        seconds: ""
    },

初始化在doajishi.hml中动态绑定的变量

 run() {
    counter = counter - 1;
    if (counter != 0) {
        this.imgsrc = "/common/" + counter.toString() + ".png";
        this.seconds = counter.toString();
    } else {
        this.imgsrc = "";
        this.seconds = "";
        
        clearInterval(timer);
        timer = null;
        
        router.replace({
            uri: 'pages/xunlian/xunlian',
            params: {"key1": pv1, "key2": pv2}
        });
    }
},

计时器timer运行时运行的函数,当函数运行时,计数的变量counter递减,如果counter的值不为0,那么换下张图片,把counter赋予动态绑定的变量sconds。如果counter等于0,把图片地址置为空,秒数也置为空,清除计时器timer,并重置变量timer,页面跳转到训练页面,并把pv1和pv2 的值也传递过去。

     onInit() {
        pv1 = this.data1;
        pv2 = this.data2;

        this.imgsrc = "/common/" + counter.toString() + ".png";
        this.seconds = counter.toString();
    },
    onShow() {
        timer = setInterval(this.run, 1000);
    }
}

onInit()为在页面数据准备时被引发的事件,把从主页面传递过来的值分别赋予pv1和pv2。
把counter字符化赋予imgsrc,以实现更换图片的作用,把counter字符化赋予this,seconds
onShow()事件为页面显示时所引发的事件,当页面显示时,触发定时器timer1,每过1毫秒运行一次run()函数。

创建训练页面

在完成倒计时页面后,我们接下来要创建训练页面,创建方法同上。
在这里插入图片描述
在这里插入图片描述

创建训练页面中的组件

在这里插入图片描述

<div class="container">

创建一个叫.container的区域组件

image class="img" 

创建一个图片组件

src="/common/hm.png"

存放图片的地址

style="animation-duration: {{duration}}

通过动态绑定的方式设定图片的动画效果,animation-duration的作用为定义动画完成一个周期需要的时间,具体的时间由index.js中this.duration得到

animation-iteration-count: {{count}}

通过动态绑定的方式设定图片动画播放的次数,具体的次数由index.js中的this.count得到

<text class="txt1">
    {{huxi}}({{percent}}%)
</text>

创建一个叫txt1文本组件,里面的文字通过动态绑定的方式由index.js中得到
作用:显示呼气/吸气和呼气/吸气的进度百分比

<text class="txt2" show="{{isshow}}">
    再坚持 {{seconds}}</text>

创建一个叫txt2的文本组件,通过show="{{isshow}}来控制txt2的显示与否,txt2的内容为再坚持的秒数,具体的时间由index,js中的this.seconds得到

<input type="button" value="点击重新开始" class="btn" onclick="clickAction"/>

设置一个按钮,按钮的名字被赋为点击重新开始,class="btn"设置一个叫btn的组件,并创建一个叫onclick的点击事件(当按钮被点击的时候会发生该事件)

设定训练页面的组件样式

在这里插入图片描述

作用:规定 “.container”的组件的样式

flex-direction: column

使在.container内的元素横向排列

justify-content: center

设置,container居中对齐

align-items: center

使.container的元素居中对齐

width: 454px;
height: 454px;

规定.container的范围。Container在手表上最多显示的范围就是width:454px,
Height:454px这个矩形的内接圆。
在这里插入图片描述

规定.img图片组件的样式

width: 208px;
height: 208px;

图片组件的高度和宽度

margin-bottom: 10px;

规定图片组件的外下边距

animation-name: aniname;

为图片的@keyframes动画指定名称
在这里插入图片描述

设定动画效果,把图片由顺时针旋转一圈
在这里插入图片描述

规定txt1组件的样式

font-size: 38px;

设定txt1组件的字体大小为38px,在手表的开发中字体大小一般都是30px或者38px。如没有设定,则系统默认为30px。

text-align: center;

设定txt1组件的文本对齐方式为居中对齐

width: 454px;
height: 40px;

设定txt1的组件的位置

margin-bottom: 10px;

规定txt1组件的外下边距
在这里插入图片描述

设定txt2组件的样式

font-size: 30px;

设定txt2中字体的大小

text-align: center;

设定txt2组件的文本对齐方式为居中对齐

width: 400px;
height: 40px;

设定txt2组件的位置
在这里插入图片描述

设定按钮组件的样式

width: 300px;
height: 50px;

设定按钮组件的位置

font-size: 38px;

设定按钮组件字体的大小

background-color: #000000;

设定按钮组件的背景颜色 #000000为黑色

border-color: #000000;

设定按钮组件边框的颜色 #000000为黑色

margin-top: 40px;

设定按钮组件的上部边距

为训练页面添加功能

import router from '@system.router'

var picker1value = null;
var picker2value = null;

var picker1seconds = null;
var picker2seconds = null;

var timer1 = null;
var timer2 = null;
var timer3 = null;

var counter = 0;

引入router,声明要用到的变量并初始化变量

export default {
    data: {
        seconds: 0,
        isshow: true,
        huxi: "吸气",
        percent: "0",
        duration: "",
        count: ""
    },

把xunlian.hml所用到的动态绑定的变量置为0,

  clickAction() {
        clearInterval(timer1);
        timer1 = null;

        clearInterval(timer2);
        timer2 = null;

        clearInterval(timer3);
        timer3 = null;

        router.replace({
            uri: 'pages/index/index'
        });
    },

清除计时器time1,time2,time3,并把timer1,timer2,timer3置为初始量。

router.replace({
    uri: 'pages/index/index'
});

跳转到pages目录下的index页面,也就是主页面.

 run1() {
        this.seconds--;
        if(this.seconds == 0) {
            clearInterval(timer1);
            timer1 = null;
            this.isshow = false;
        }
    },

计时器timer1运行时的运行的函数,使this.seconds的值递减,当this.seconds的值减为0时,清除计时器timer1,并把变量timer1的值重置,把this.isshow的值赋予false,即使组件.txt2中的内容改为不可见.

 run2() {
        counter++;
        if (counter == picker1seconds / picker2seconds) {
            clearInterval(timer2);
            timer2 = null;
            this.huxi = "已完成";
        } else {
            if (this.huxi == "吸气") {
                this.huxi = "呼气";
            } else if (this.huxi == "呼气") {
                this.huxi = "吸气";
            }
        }
    },

计时器timer2运行时运行的函数,使变量counter递增,如果counter的值等于吸气和呼气的总次数的话,清除定时器timer2,并重置timer2的值,并把在txt2组件显示的文字改为已完成。如果不是,就把txt2组件的文字从呼气改为吸气,或者从吸气改为呼气。

 run3() {
        this.percent = (parseInt(this.percent) + 1).toString();
        if (parseInt(this.percent) < 10) {
            this.percent = "0" + this.percent;
        }
        if (parseInt(this.percent) == 100) {
            this.percent = "0";
        }
        if (timer2 == null) {
            clearInterval(timer3);
            timer3 = null;
            this.percent = "100";
        }
    },

计时器timer3运行时运行的函数,把this.percent的值取整再加一并转换为字符串并重新赋予this.percent(this.percent即在txt2组件中显示百分比的动态绑定变量)。如果this.percnet的值小于10,就在显示的数字前加0。如果this.percent的值等于100,就使其重新置为零。如果计时器timer2=null,就清除计时器timer3,并重置timer3的值,把this.percent的值改为100。

onInit() {
        picker1value = this.key1;
        picker2value = this.key2;

        if (picker1value == "1") {
            picker1seconds = 60;
        } else if (picker1value == "2") {
            picker1seconds = 120;
        } else if (picker1value == "3") {
            picker1seconds = 180;
        }

把从主页面传递过来的两个值this.key1(选择训练的时间),this.key2(选择训练的强度)赋值给picker1value,picker2value。如果pikcer1value的值为不同的分钟,就把对应分钟的秒数赋予给picker1seconds


        if (picker2value == "较慢") {
            picker2seconds = 6;
        } else if (picker2value == "舒缓") {
            picker2seconds = 4;
        } else if (picker2value == "较快") {
            picker2seconds = 2;
        }

        this.seconds = picker1seconds;

        this.duration = picker2seconds + "s";
        this.count = (picker1seconds / picker2seconds).toString();
    },

如果picker2value的值为不同的强度,就把对应强度的数字赋予picker2seconds。
把picker1seconds赋予在txt2组件动态绑定的seconds(即显示训练剩下的秒数)
把picker2seconds赋予为图片组件动画完成一个周期的时间
把(picker1seconds/picker2seconds)的值赋予图片组件的动画播放的次数

    onShow() {

        timer1 = setInterval(this.run1, 1000);
        timer2 = setInterval(this.run2, picker2seconds * 1000);
        timer3 = setInterval(this.run3, picker2seconds / 100 * 1000);
    },
}

onShow函数中包含三个计时器,计时器原理:每过一千毫秒,this.run()函数会运行一次。

这样就完成了训练页面的所有功能。

结语

在观看了张老师的视频后,我们写了这学习笔记来记录我们的鸿蒙之旅。希望以后我们的路程能走的更远。下面有视频教程中所用到的图片,如果有需要的人可以拿去用。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值