Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
2b8baa88
D
Docs
项目概览
OpenHarmony
/
Docs
大约 1 年 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
2b8baa88
编写于
5月 26, 2023
作者:
O
openharmony_ci
提交者:
Gitee
5月 26, 2023
浏览文件
操作
浏览文件
下载
差异文件
!18689 新增案例【不需要翻译】
Merge pull request !18689 from duangavin123/master
上级
549b4a83
aee081da
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
303 addition
and
0 deletion
+303
-0
zh-cn/third-party-cases/Readme-CN.md
zh-cn/third-party-cases/Readme-CN.md
+1
-0
zh-cn/third-party-cases/figures/waterwaves.gif
zh-cn/third-party-cases/figures/waterwaves.gif
+0
-0
zh-cn/third-party-cases/water-wave-animation.md
zh-cn/third-party-cases/water-wave-animation.md
+302
-0
未找到文件。
zh-cn/third-party-cases/Readme-CN.md
浏览文件 @
2b8baa88
...
...
@@ -20,6 +20,7 @@
-
[
如何实现列表的二级联动
](
interact-lists.md
)
-
[
时钟开发示例
](
time-styles-shift.md
)
-
[
弹簧动画开发
](
how-to-develop-spring-animation.md
)
-
[
水波纹动画开发
](
water-wave-animation.md
)
-
[
如何使用OpenGL实现3D图形
](
how-to-use-opengl-to-draw-3d-graphics.md
)
### 网络管理
-
[
如何请求并加载网络图片
](
how-to-load-images-from-internet.md
)
...
...
zh-cn/third-party-cases/figures/waterwaves.gif
0 → 100644
浏览文件 @
2b8baa88
76.3 KB
zh-cn/third-party-cases/water-wave-animation.md
0 → 100644
浏览文件 @
2b8baa88
# 水波纹动画开发
## 场景介绍
在日常应用场景中,水波纹的效果比较常见,例如数字键盘按键效果、听歌识曲、附近搜索雷达动效等等,本文就以数字按键为例介绍水波纹动效的实现。
## 效果呈现
本例最终效果图如下:
![
waterwaves
](
figures/waterwaves.gif
)
## 环境要求
本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:
-
IDE: DevEco Studio 3.1 Beta2
-
SDK: Ohos_sdk_public 3.2.11.9(API Version 9 Release)
## 实现思路
本实例涉及到的主要特性及其实现方案如下:
*
UI框架:使用Grid,GridItem等容器组件组建UI框架。
*
按钮渲染:通过自定义numBtn组件(含Column、Button、Stack、Text等关键组件以及visibility属性),进行数字按钮的渲染。
*
按钮状态变化:设置状态变量unPressed,控制按钮的当前状态,向Column组件添加onTouch事件,监听按钮的当前状态。
*
默认状态为按钮放开状态(unPressed为true)。
*
当按钮按下时,更新按钮的状态(unPressed:true -> false)。
*
当按钮放开时,更新按钮的状态(unPressed:false -> true)。
*
按钮动画展示:使用属性动画以及组件内转场动画绘制按钮不同状态下的动画。
*
当按钮按下时,使用显式动画(animateTo)加载动画:插入按下时的Row组件,同时加载水波的聚拢效果。
*
当按钮放开时,使用组件内转场加载动画:插入放开时的Row组件,同时加载水波的扩散效果。
## 开发步骤
针对实现思路中所提到的内容,具体关键开发步骤如下:
1.
先通过Grid,GridItem等容器组件将UI框架搭建起来,在GuidItem中引用步骤2中的自定义数字按钮numBtn构建出数字栅格。
具体代码如下:
```ts
private numGrid: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, -1, 0, -1]
...
Column() {
Grid() {
ForEach(this.numGrid, (item: number, index: number) => {
GridItem() {
...
}
}, item => item)
}
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr 1fr 1fr')
.columnsGap(10)
.rowsGap(10)
.width(330)
.height(440)
}.width('100%').height('100%')
```
2.
通过Column、Button、Stack、Text等关键组件以及visibility属性构建自定义数字按钮numBtn。
具体代码如下:
```ts
@Component
struct numBtn {
···
build() {
Column() {
Button() {
stack(){
...
Text(`${this.item}`).fontSize(30)
}
...
}
.backgroundColor('#ccc')
.type(ButtonType.Circle)
.borderRadius(100)
.width(100)
.height(100)
}
.visibility(this.item == -1 ? Visibility.Hidden : Visibility.Visible)
.borderRadius(100)
}
}
```
3.
设置状态变量unPressed,监听当前数字按钮的状态,同时向Column组件添加onTouch事件,获取并更新按钮的当前状态,从而可以根据监听到的按钮状态加载对应的动画效果。
具体代码块如下:
```ts
//状态变量unPressed,用于监听按钮按下和放开的状态
@State unPressed: boolean = true
...
// 添加onTouch事件,监听状态
.onTouch((event: TouchEvent) => {
// 当按钮按下时,更新按钮的状态(unPressed:true -> false)
if (event.type == TouchType.Down) {
animateTo({ duration: 400 }, () => {
this.unPressed = !this.unPressed
this.currIndex = this.index
})
}
// 当按钮放开时,更新按钮的状态(unPressed:false -> true)
if (event.type == TouchType.Up) {
animateTo({ duration: 400 }, () => {
this.unPressed = !this.unPressed
})
}
})
```
4.
根据按钮组件的按下/放开状态,通过if-else语句选择插入的Row组件,并随之呈现不同的水波动画效果(按下时水波聚拢,放开时水波扩散)。
具体代码块如下:
```ts
Stack() {
Row() {
// 判断当前按钮组件为放开状态
if (this.unPressed && this.currIndex == this.index) {
// 插入Row组件,配置过渡效果
Row()
.customStyle()
.backgroundColor('#fff')
// 水波纹扩散动画:从Row组件的中心点开始放大,scale{0,0}变更scale{1,1}(完整显示)
.transition({
type: TransitionType.Insert,
opacity: 0,
scale: { x: 0, y: 0, centerY: '50%', centerX: '50%' }
})
}
// 判断当前按钮组件为按下状态
else if (!this.unPressed && this.currIndex == this.index) {
// 插入Row组件,配置过渡效果
Row()
.customStyle()
.backgroundColor(this.btnColor)
.scale(this.btnScale)
.onAppear(() => {
// 水波纹聚拢动画:Row组件backgroundColor属性变更(#ccc -> #fff),插入动画过渡效果,scale{1,1}(完整显示)变化为scale{0,0}
animateTo({ duration: 300,
// 聚拢动画播放完成后,需要衔接扩散动画,Row组件backgroundColor属性变更(#fff -> #ccc),插入动画过渡效果,scale{0,0}变化为scale{1,1}(完整显示)
onFinish: () => {
this.btnColor = '#ccc'
this.btnScale = { x: 1, y: 1 }
} },
() => {
this.btnColor = '#fff'
this.btnScale = { x: 0, y: 0 }
})
})
}
// 其他状态
else {
Row()
.customStyle()
.backgroundColor('#fff')
}
}
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
.borderRadius(100)
Text(`${this.item}`).fontSize(30)
}
.customStyle()
```
## 完整代码
示例代码如下:
```
ts
@
Entry
@
Component
export
default
struct
dragFire
{
private
numGrid
:
number
[]
=
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
-
1
,
0
,
-
1
]
build
()
{
Column
()
{
Grid
()
{
ForEach
(
this
.
numGrid
,
(
item
:
number
,
index
:
number
)
=>
{
GridItem
()
{
numBtn
({
item
:
item
,
index
:
index
})
}
},
item
=>
item
)
}
.
columnsTemplate
(
'
1fr 1fr 1fr
'
)
.
rowsTemplate
(
'
1fr 1fr 1fr 1fr
'
)
.
columnsGap
(
10
)
.
rowsGap
(
10
)
.
width
(
330
)
.
height
(
440
)
}.
width
(
'
100%
'
).
height
(
'
100%
'
)
}
}
@
Component
struct
numBtn
{
private
currIndex
:
number
=
-
1
//状态变量unPressed,用于控制按钮的状态
@
State
unPressed
:
boolean
=
true
@
State
btnColor
:
string
=
'
#ccc
'
index
:
number
item
:
number
@
State
btnScale
:
{
x
:
number
,
y
:
number
}
=
{
x
:
1
,
y
:
1
}
@
Styles
customStyle
(){
.
width
(
'
100%
'
)
.
height
(
'
100%
'
)
.
borderRadius
(
100
)
}
build
()
{
Column
()
{
Button
()
{
Stack
()
{
Row
()
{
// 判断当前组件为放开状态
if
(
this
.
unPressed
&&
this
.
currIndex
==
this
.
index
)
{
// 插入Row组件,配置过渡效果
Row
()
.
customStyle
()
.
backgroundColor
(
'
#fff
'
)
// 水波纹扩散动画:Row组件backgroundColor属性变更(#fff -> #ccc),系统插入动画过渡效果,从组建的中心点开始放大,scale{0,0}变更scale{1,1}
.
transition
({
type
:
TransitionType
.
Insert
,
opacity
:
0
,
scale
:
{
x
:
0
,
y
:
0
,
centerY
:
'
50%
'
,
centerX
:
'
50%
'
}
})
}
// 判断当前组件为按下状态
else
if
(
!
this
.
unPressed
&&
this
.
currIndex
==
this
.
index
)
{
// 插入Row组件,配置过渡效果
Row
()
.
customStyle
()
.
backgroundColor
(
this
.
btnColor
)
.
scale
(
this
.
btnScale
)
.
onAppear
(()
=>
{
// 水波纹聚拢动画:Row组件backgroundColor属性变更(#ccc -> #fff),插入动画过渡效果,scale{1,1}变化为scale{0,0}
animateTo
({
duration
:
300
,
// 聚拢动画播放完成后,需要衔接扩散动画,此时Row组件backgroundColor属性变更(#fff -> #ccc),插入动画过渡效果,scale{0,0}变化为scale{1,1}
onFinish
:
()
=>
{
this
.
btnColor
=
'
#ccc
'
this
.
btnScale
=
{
x
:
1
,
y
:
1
}
}
},
()
=>
{
this
.
btnColor
=
'
#fff
'
this
.
btnScale
=
{
x
:
0
,
y
:
0
}
})
})
}
// 其他状态
else
{
Row
()
.
customStyle
()
.
backgroundColor
(
'
#fff
'
)
}
}
.
justifyContent
(
FlexAlign
.
Center
)
.
alignItems
(
VerticalAlign
.
Center
)
.
borderRadius
(
100
)
Text
(
`
${
this
.
item
}
`
).
fontSize
(
30
)
}
.
customStyle
()
}
.
stateEffect
(
false
)
.
backgroundColor
(
'
#ccc
'
)
.
type
(
ButtonType
.
Circle
)
.
borderRadius
(
100
)
.
width
(
100
)
.
height
(
100
)
}
.
visibility
(
this
.
item
==
-
1
?
Visibility
.
Hidden
:
Visibility
.
Visible
)
.
borderRadius
(
100
)
// onTouch事件,监听状态
.
onTouch
((
event
:
TouchEvent
)
=>
{
// 当按钮按下时,更新按钮的状态(unPressed:true -> false)
if
(
event
.
type
==
TouchType
.
Down
)
{
animateTo
({
duration
:
400
},
()
=>
{
this
.
unPressed
=
!
this
.
unPressed
this
.
currIndex
=
this
.
index
})
}
// 当按钮放开时,更新按钮的状态(unPressed:false -> true)
if
(
event
.
type
==
TouchType
.
Up
)
{
animateTo
({
duration
:
400
},
()
=>
{
this
.
unPressed
=
!
this
.
unPressed
})
}
})
}
}
```
## 参考
[
Guid
](
../application-dev/reference/arkui-ts/ts-container-grid.md
)
[
GridItem
](
../application-dev/reference/arkui-ts/ts-container-griditem.md
)
[
显式动画
](
../application-dev/reference/arkui-ts/ts-explicit-animation.md
)
[
组件内转场
](
../application-dev/reference/arkui-ts/ts-transition-animation-component.md
)
[
Stack
](
../application-dev/reference/arkui-ts/ts-container-stack.md
)
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录