上述代码中,将clicktest组件的onclick属性设置为Click,这里的Click其实是在js文件中定义的一个函数,当此组件所包含的区域被单击时就会触发Click函数。这里依旧以5.3.3节中的3种不同颜色的手机为例,代码如下:
在hml文件代码中定义了一个div组件,并将其onclick属性连接到了js文件中定义的Click函数,在Click函数中会根据tmp的值来决定每次单击后显示的视图及显示的视图名字,Click函数在js文件中的实现代码如下:
//.js文件代码
export default {
data: {
Image: "/common/1.png", //最开始显示black视图
Name: "black",
tmp: 1,
},
Click() {
if ( this.tmp == 0) {
this.Image = "/common/1.png"; //第3次单击跳到第一视图
this.Name = "black";
}
else if ( this.tmp == 1 ) {
this.Image = "/common/2.png"; //第1次单击跳到第二视图
this.Name = "orange";
}
else if ( this.tmp == 2 ) {
this.Image = "/common/3.png"; //第2次单击跳到第三视图
this.Name = "white";
}
this.tmp = ( this.tmp + 1) % 3 ;
}
}
在css文件中对布局样式进行简单设计,代码如下:
.container {
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.click-test {
width: 100%;
}
.image {
height: 80%;
justify-content: center;
}
.image-name {
color: #BCBCBC;
width: 300px;
text-align: center;
}
运行上述代码,当应用程序打开时,开始界面如图5.18所示。
当第1次单击界面容器之后,图片会进行跳转,从图5.18所示效果跳转至图5.19所示效果,如图5.19所示。
同理,当第2次单击之后效果如图5.20所示。第3次单击之后又会回到开始界面,即图5.18所示的效果,之后不断循环。
图5.18组件示例
效果图
图5.19第1次手势交互后
组件示例效果图
图5.20第2次手势交互后
组件示例效果图
5.4.2按键事件
按键事件是智慧屏上特有的手势事件,会在用户操作遥控器按键时触发。当用户单击一个遥控器按钮时,通常会触发两次key事件: 先触发action为0即触发按下事件,再触发action为1即手指抬起事件。action等于2的场景较少出现,一般为用户按下按键后不抬起即长按,此时repeatCount将返回次数。每个物理按键对应各自的按键keycode以实现不同的功能,代码如下:
/* index.js */
export default {
data: {
up: 'up',
down: 'down',
},
focusUp: function() {
this.up = 'up focused';
},
blurUp: function() {
this.up = 'up';
},
keyUp: function() {
this.up = 'up keyed';
},
focusDown: function() {
this.down = 'down focused';
},
blurDown: function() {
this.down = 'down';
},
keyDown: function() {
this.down = 'down keyed';
},
}
按键事件通过获焦事件向下分发,因此上述示例中使用了focus事件和blur事件来明确当前焦点位置。当按上下键时,相应的focused状态将会响应。当失去焦点按键时,恢复到正常的up或down按键文本。按确认键后该键变为keyed状态。
5.4.3页面路由
很多情况下,在开发App时不只使用一个页面,例如在购物App中有时需要从商品详情页面跳转到购物车页面,这时就需要在商品详情页面设置一个能跳转到购物车页面的入口,在浏览完购物车页面之后又需要回到之前的商品详情页面,此时就需要页面路由功能。
在页面路由中需要定义两个或两个以上页面,然后在各自页面的js文件中定义相应的路由函数来使用目标页面的uri跳转到目标页面。定义两个页面,两个页面的hml文件代码分别如下:
在第一个页面中定义了一个button并将其与first.js中的launch函数相关联,第二个页面中的两个button分别与second.js中的launch函数与launch2函数相关联,两个js文件中的代码如下:
//first.js
import router from '@system.router';
//指定的页面。在调用router 方法之前,需要导入 router 模块
export default {
launch: function () {
router.push({
uri: 'pages/second/second', //目标页面的路径
})
},
}
//second.js
import router from '@system.router'
export default {
launch: function () {
router.back(); //回到路由前的页面
},
launch2: function () {
router.push({
uri: 'pages/first/first', //目标页面的路径
})
}
}
在第一个页面的first.js文件中,使用router.push来跳转到第二个页面,uri代表目标页面的路径,然而回到之前的页面有两条途径,也就是在第二个页面中所使用的两种方法,router.back和router.push。其中,router.back可以实现直接跳回原页面,所以不需要任何uri,而router.push利用原页面的uri再次跳转到原页面。
下面是两个页面的css文件,代码如下:
/* first.css */
.container {
flex-direction: column;
justify-content: center;
align-items: center;
}
.text-div{
justify-content: center;
}
.button-div{
justify-content: center;
}
/* second.css */
.container {
flex-direction: column;
justify-content: center;
align-items: center;
}
.text-div{
justify-content: center;
}
.button-div{
justify-content: center;
}
为了实现页面跳转,需要将每个页面的3个文件(hml、css、js)都放入各自独立的文件夹,如图5.21所示。
图5.21页面路由示例工程结构图
之后还需要在App模块的config.json文件中注册已编写好的页面,代码如下:
"js": [
{
"pages": [
"pages/first/first",
"pages/second/second"
],
...
}
]
pages中排在第一位的页面将作为应用程序的默认页面,也就是打开应用程序后显示的第一个页面。运行上述代码,首先显示的第一个页面如图5.22所示。
单击“跳转到第二个页面”按钮将会跳转到第二个页面,如图5.23所示。
图5.22页面路由示例的第一个页面
图5.23页面路由示例的第二个页面
单击页面上的两个按钮都会跳转到第一个页面,不同的地方是左边的按钮使用返回方式回到原页面,因此更像
返回操作,而右边的按钮使用uri跳转到原页面,因此更像前进操作。
5.5动画
5.5.1transform静态动画
静态动画的核心是transform样式,其中包含3种变换类型,且每一次的样式设置只能支持一种类型的变化。下面对3种类型进行逐一讲解。
首先,translate变换类型可以将组件沿水平或垂直方向移动一定的距离,创建JS项目工程,修改index.hml和index.css文件
,示例是一个水平向右移动的示例代码,代码如下:
hello
/* index.css */
.container {
flex-direction: column;
align-items: center;
}
.translate {
height: 300px;
width: 400px;
font-size: 100px;
background-color: #008000;
transform: translateX(300px);
}
上述代码实现了一个text组件水平向右移动的效果,translateX(300px)将text组件水平从基准线向右移动300px,其中右为正值,左为负值。同理,若修改为translateY(),则是以Y轴基准线为标准,下为正值,上为负值。运行结果如图5.24所示,
灰线为基准线。
scale样式可将组件沿横向或纵向,缩小或放大一定比例。下面对text组件进行横向放大,代码如下:
hello
/* index.css */
.container {
flex-direction: column;
align-items: center;
}
.scale {
height: 300px;
width: 400px;
font-size: 100px;
background-color: #008000;
transform: scaleX(1.5);
}
其中,scaleX(1.5)表示将text文本横向放大1.5倍,运行上述代码可以直观看到效果,如图5.25所示。
图5.24静态动画平移示例效果图
图5.25静态动画放大示例效果图
rotate样式可以将组件沿横轴或纵轴或中心点,旋转一定的角度,如下示例将text文本绕X轴顺时针旋转45°,代码如下:
hello
/* index.css */
.container {
flex-direction: column;
align-items: center;
}
.rotate {
height: 300px;
width: 400px;
font-size: 100px;
background-color: #008000;
transform-origin: 200px 100px;
transform: rotateX(45deg);
}
图5.26静态动画旋转
示例效果图
运行上述代码,结果如图5.26所示。
图5.26中Z轴垂直穿出屏幕。一般的rotateX()和rotateY()表示绕X和Y轴顺时针旋转,而rotate()表示绕Z轴旋转。
与连续动画不同,静态动画只有开始状态和结束状态,而不能设置中间状态,如果需要设置中间的过渡状态和转换效果,
则只能由连续动画实现。
5.5.2animation连续动画
前面讲过的静态动画只有开始状态和结束状态,而没有中间状态,因此静态动画看起来更像是图片之间的切换而不是真正意义上的动画。为了使动画变得连贯,HarmonyOS中的JS引入了连续动画。连续动画最主要的功能贡献者就是animation样式,通过它可以定义动画的开始、结束状态及期间变化的速度。在引入连续动画之后,可以定义组件的宽、高、颜色和透明度等的变化速度和程度,利用这一点可以实现一些有趣的功能,例如进度条、渐变色块等。在本节中利用animation实现颜色、透明度和宽度变化的功能。首先新建JS工程,修改代码如下:
在页面中定义了两个文本组件,分别用来演示颜色变化,以及透明度和宽度变化。input组件的单击事件show()在文件中的实现代码如下:
//animation.js
export default {
data: {
colorParam: '',
opacityParam: '',
},
show: function () {
this.colorParam = ''
this.opacityParam = ''
this.colorParam = 'color'
this.opacityParam = 'opacity'
},
}
其中,colorParam和opacityParam分别与hml文件中的样式进行数据绑定,在show()方法中,首先将这两个参数设置为默认格式,并在css文件中进行动画实现,css文件代码如下:
/* animation.css */
.item-container {
margin-bottom: 50px;
margin-right: 60px;
margin-left: 60px;
flex-direction: column;
align-items: flex-start;
}
.group {
margin-bottom: 150px;
flex-direction: column;
align-items: flex-start;
}
.header {
margin-bottom: 20px;
}
.item {
background-color: #191FF7;
}
.txt {
text-align: center;
width: 200px;
height: 100px;
}
.button {
width: 200px;
font-size: 30px;
color: #ffffff;
background-color: #09ba07;
}
.color {
animation-name: Color-frames; /*动画由Color-frames定义*/
animation-duration: 8000ms;
}
.opacity {
animation-name: Opacity-frames; /*动画由Opacity-frames*/
animation-duration: 8000ms;
}
@keyframes Color-frames { /*颜色变换效果动画*/
from {
background-color: #191FF7; /*初始颜色*/
}
to {
background-color: #09ba07; /*最终颜色*/
}
} @keyframes Opacity-frames { /*透明度、宽度变换效果动画*/
from {
width: 600px; /*初始宽度*/
opacity: 0.9; /*初始透明度*/
}
to {
width: 0px; /*最终宽度*/
opacity: 0.0; /*最终透明度*/
}
}
在.color和.opacity样式中,使用animationname属性定义了各自的动画样式(@keyframes)。其中@keyframes可以自定义动画样式,例如代码中定义的Colorframes和Opacityframes,from代表动画的开始状态,to代表结束状态,期间的过渡动画由系统自动计算完成,当然也可以使用animationtimingfunction属性来描述动画执行的速度曲线,使动画更加平滑。运行上述代码,初始页面如图5.27所示。
单击“开始”按钮后,会播放定义的动画(按时间顺序排列),如图5.28所示。
图5.27连续动画示例的初始状态
图5.28连续动画示例的过程(a)和结束状态(b)
可以看到“颜色”块的背景色从蓝色最终变为绿色,“透明度”块的透明度从不透明变为全透明,并且宽度从最开始一直变为0,类似一个反向的进度条。在这里还可以使用animation的其他属性来定义更多有趣的动画效果,读者可以自行尝试。