鸿蒙NEXT自定义组件:太极Loading

【引言】(完整代码在最后面)
本文将介绍如何在鸿蒙NEXT中创建一个自定义的“太极Loading”组件,为你的应用增添独特的视觉效果。
【环境准备】
电脑系统:windows 10
开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806
工程版本:API 12
真机:mate60 pro
语言:ArkTS、ArkUI
【项目分析】
1. 组件结构
我们将创建一个名为 TaiChiLoadingProgress 的自定义组件,它将模拟太极图的旋转效果,作为加载动画展示给用户。组件的基本结构如下:
@Component
struct TaiChiLoadingProgress {
@Prop taiChiWidth: number = 400
@Prop @Watch('animationCurveChanged') animationCurve: Curve = Curve.Linear
@State angle: number = 0
@State cellWidth: number = 0
...
}
2. 绘制太极图案
使用鸿蒙NEXT提供的UI组件,如 Rect 和 Circle,构建太极图的黑白两部分。关键在于利用 rotate 方法实现太极图的旋转效果。
build() {
Stack() {
Stack() {
// 黑色半圆背景
Stack() {
Rect().width(`${this.cellWidth}px`).height(`${this.cellWidth / 2}px`).backgroundColor(Color.Black)
}.width(`${this.cellWidth}px`).height(`${this.cellWidth}px`).rotate({ angle: -90 }).align(Alignment.Top)
// 大黑球 上
Stack() {
Circle().width(`${this.cellWidth / 2}px`).height(`${this.cellWidth / 2}px`).fill(Color.Black)
Circle().width(`${this.cellWidth / 8}px`).height(`${this.cellWidth / 8}px`).fill(Color.White)
}.width(`${this.cellWidth}px`).height(`${this.cellWidth}px`).align(Alignment.Top)
// 大白球 下
Stack() {
Circle().width(`${this.cellWidth / 2}px`).height(`${this.cellWidth / 2}px`).fill(Color.White)
Circle().width(`${this.cellWidth / 8}px`).height(`${this.cellWidth / 8}px`).fill(Color.Black)
}.width(`${this.cellWidth}px`).height(`${this.cellWidth}px`).align(Alignment.Bottom)
}
.width(`${this.cellWidth}px`)
.height(`${this.cellWidth}px`)
.borderWidth(1)
.borderColor(Color.Black)
.borderRadius('50%')
.backgroundColor(Color.White)
.clip(true)
.rotate({
angle: this.angle
})
.onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => {
if (isVisible && currentRatio >= 1.0) {
this.startAnim()
}
if (!isVisible && currentRatio <= 0.0) {
this.endAnim()
}
})
}
.width(`${this.taiChiWidth}px`)
.height(`${this.taiChiWidth}px`)
}
3. 动画实现
通过 animateTo 方法设置太极图的旋转动画,可以自定义动画曲线以实现不同的动画效果。
startAnim() {
animateTo({
duration: 2000,
iterations: -1,
curve: this.animationCurve
}, () => {
this.angle = 360 * 2
})
}
endAnim() {
animateTo({
duration: 0
}, () => {
this.angle = 0
})
}
【完整代码】
@Component
struct TaiChiLoadingProgress {
@Prop taiChiWidth: number = 400
@Prop @Watch('animationCurveChanged') animationCurve: Curve = Curve.Linear
@State angle: number = 0
@State cellWidth: number = 0 animationCurveChanged() {
this.endAnim()
this.startAnim()
} startAnim() {
animateTo({
duration: 2000,
iterations: -1,
curve: this.animationCurve
}, () => {
this.angle = 360 * 2
})
} endAnim() {
animateTo({
duration: 0
}, () => {
this.angle = 0
})
} aboutToAppear(): void {
this.cellWidth = this.taiChiWidth / 2
} build() {
Stack() {
Stack() {
//黑色 半圆 背景
Stack() {
Rect().width(`${this.cellWidth}px`).height(`${this.cellWidth / 2}px`).backgroundColor(Color.Black)
}.width(`${this.cellWidth}px`).height(`${this.cellWidth}px`).rotate({ angle: -90 }).align(Alignment.Top) //大黑球 上
Stack() {
Stack() {
Circle().width(`${this.cellWidth / 2}px`).height(`${this.cellWidth / 2}px`).fill(Color.Black)
Circle().width(`${this.cellWidth / 8}px`).height(`${this.cellWidth / 8}px`).fill(Color.White)
}
}.width(`${this.cellWidth}px`).height(`${this.cellWidth}px`).align(Alignment.Top) //大白球 下
Stack() {
Stack() {
Circle().width(`${this.cellWidth / 2}px`).height(`${this.cellWidth / 2}px`).fill(Color.White)
Circle().width(`${this.cellWidth / 8}px`).height(`${this.cellWidth / 8}px`).fill(Color.Black)
}
}.width(`${this.cellWidth}px`).height(`${this.cellWidth}px`).align(Alignment.Bottom) }
.width(`${this.cellWidth}px`)
.height(`${this.cellWidth}px`)
.borderWidth(1)
.borderColor(Color.Black)
.borderRadius('50%')
.backgroundColor(Color.White)
.clip(true)
.rotate({
angle: this.angle
})
.onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => {
console.info('Test Row isVisible:' + isVisible + ', currentRatio:' + currentRatio)
if (isVisible && currentRatio >= 1.0) {
console.info('Test Row is fully visible.')
this.startAnim()
} if (!isVisible && currentRatio <= 0.0) {
console.info('Test Row is completely invisible.')
this.endAnim()
}
})
}
.width(`${this.taiChiWidth}px`)
.height(`${this.taiChiWidth}px`)
}
} @Entry
@Component
struct Page08 {
@State loadingWidth: number = 150
@State isShowLoading: boolean = true;
@State animationCurve: Curve = Curve.Linear build() {
Column({ space: 20 }) { Text('官方Loading组件')
Column() {
LoadingProgress().width(this.loadingWidth)
.visibility(this.isShowLoading ? Visibility.Visible : Visibility.None)
}.height(this.loadingWidth).width(this.loadingWidth) Text('自定义太极Loading组件')
Column() {
TaiChiLoadingProgress({ taiChiWidth: vp2px(this.loadingWidth), animationCurve: this.animationCurve })
.visibility(this.isShowLoading ? Visibility.Visible : Visibility.Hidden)
}.height(this.loadingWidth).width(this.loadingWidth) Row() {
Flex({ wrap: FlexWrap.Wrap }) {
Text('显示/隐藏')
.textAlign(TextAlign.Center)
.width('200lpx')
.height('200lpx')
.margin('10lpx')
.backgroundColor(Color.Black)
.borderRadius(5)
.backgroundColor(Color.Orange)
.fontColor(Color.White)
.clickEffect({ level: ClickEffectLevel.LIGHT })
.onClick(() => {
this.isShowLoading = !this.isShowLoading
})
Text('Linear动画')
.textAlign(TextAlign.Center)
.width('200lpx')
.height('200lpx')
.margin('10lpx')
.backgroundColor(Color.Black)
.borderRadius(5)
.backgroundColor(Color.Orange)
.fontColor(Color.White)
.clickEffect({ level: ClickEffectLevel.LIGHT })
.onClick(() => {
this.animationCurve = Curve.Linear
})
Text('FastOutLinearIn动画')
.textAlign(TextAlign.Center)
.width('200lpx')
.height('200lpx')
.margin('10lpx')
.backgroundColor(Color.Black)
.borderRadius(5)
.backgroundColor(Color.Orange)
.fontColor(Color.White)
.clickEffect({ level: ClickEffectLevel.LIGHT })
.onClick(() => {
this.animationCurve = Curve.FastOutLinearIn
})
Text('EaseIn动画')
.textAlign(TextAlign.Center)
.width('200lpx')
.height('200lpx')
.margin('10lpx')
.backgroundColor(Color.Black)
.borderRadius(5)
.backgroundColor(Color.Orange)
.fontColor(Color.White)
.clickEffect({ level: ClickEffectLevel.LIGHT })
.onClick(() => {
this.animationCurve = Curve.EaseIn
})
Text('EaseOut动画')
.textAlign(TextAlign.Center)
.width('200lpx')
.height('200lpx')
.margin('10lpx')
.backgroundColor(Color.Black)
.borderRadius(5)
.backgroundColor(Color.Orange)
.fontColor(Color.White)
.clickEffect({ level: ClickEffectLevel.LIGHT })
.onClick(() => {
this.animationCurve = Curve.EaseOut
})
Text('EaseInOut动画')
.textAlign(TextAlign.Center)
.width('200lpx')
.height('200lpx')
.margin('10lpx')
.backgroundColor(Color.Black)
.borderRadius(5)
.backgroundColor(Color.Orange)
.fontColor(Color.White)
.clickEffect({ level: ClickEffectLevel.LIGHT })
.onClick(() => {
this.animationCurve = Curve.EaseInOut
})
}.width('660lpx')
}.width('100%').justifyContent(FlexAlign.Center)
}
.height('100%')
.width('100%')
.backgroundColor("#f9feff")
}
}
鸿蒙NEXT自定义组件:太极Loading的更多相关文章
- vue自定义组件(vue.use(),install)+全局组件+局部组件
相信大家都用过element-ui.mintui.iview等诸如此类的组件库,具体用法请参考:https://www.cnblogs.com/wangtong111/p/11522520.html ...
- vue2 自定义全局组件(Loading加载效果)
vue2 自定义全局组件(Loading加载效果) github地址: https://github.com/ccyinghua/custom-global-component 一.构建项目 vue ...
- 【全网首发】鸿蒙开源三方组件--强大的弹窗库XPopup组件
目录: 1.介绍 2.效果一览 3.依赖 4.如何使用 5.下载链接 6.<鸿蒙开源三方组件>文章合集 1. 介绍 XPopup是一个弹窗库,可能是Harmony平台最好的弹窗库.它从 ...
- vue中自定义组件(插件)
vue中自定义组件(插件) 原创 2017年01月04日 22:46:43 标签: 插件 在vue项目中,可以自定义组件像vue-resource一样使用Vue.use()方法来使用,具体实现方法: ...
- [转] vue自定义组件(通过Vue.use()来使用)即install的使用
在vue项目中,我们可以自定义组件,像element-ui一样使用Vue.use()方法来使用,具体实现方法: 1.首先新建一个Cmponent.vue文件 // Cmponent.vue<te ...
- 微信小程序入坑之自定义组件
前言 最近接触微信小程序,再次之前公司用的前端框架是vue ,然后对比发现,开发小程序是各种限制,对于开发者非常不友好.各种槽点太多,完全吐槽不过来,所以在此不多说,打算下次专门写一篇文章吐槽一下.本 ...
- Writing Your Own Widget(自定义组件)
英文地址:http://dojotoolkit.org/reference-guide/1.10/quickstart/writingWidgets.html#quickstart-writingwi ...
- vue自定义组件(通过Vue.use()来使用)即install的使用
在vue项目中,我们可以自定义组件,像element-ui一样使用Vue.use()方法来使用,具体实现方法: 1.首先新建一个loading.vue文件 // Cmponent.vue <te ...
- Android开发之自定义组件和接口回调
说到自定义控件不得不提的就是接口回调,在Android开发中接口回调用的还是蛮多的.在这篇博客开始的时候呢,我想聊一下iOS的自定义控件.在iOS中自定义控件的思路是继承自UIView, 在UIVie ...
- Android自定义组件
[参考的原文地址] http://blog.csdn.net/l1028386804/article/details/47101387效果图: 实现方式: 一:自定义一个含有EditText和Butt ...
随机推荐
- containerd在线部署
containerd的作用以及跟docker的区别 Containerd是一个用于管理容器生命周期的开源项目.它最初是从Docker项目中分离出来的,现在已经成为了一个独立的项目.它可以用作容器镜像管 ...
- MFC树形控件加载Access数据库数据
研究了好几天,今天终于弄好了,下面是代码 [dlg.cpp] 在初始函数OnInitDialog()中加 HICON hIcon[3]; HTREEITEM hRoot; //加载三个图标 hIcon ...
- Hexo-GitHub部署魔改第一步-config
Hexo-GitHub部署魔改第一步_config.yml 1. config.yml # Hexo Configuration ## Docs: https://hexo.io/docs/confi ...
- zabbix 自定义用户key与参数userparameters监控监本输出
zabbix在模板中预定义了一些key,但通常情况,并不能满足我们的需求.幸运的是zabbix提供了自定义key的方法,因此我们可以灵活的监控各种我们想要监控的数据. 定义key有两种修改方式: vi ...
- 【GitHub】上传代码通用操作等(附下载单个文件夹或文件)
一.创建GitHub账号以及配置 参考我的另一篇文章:<[Mac系统 + Git]之上传项目代码到github上以及删除某个文件夹> 二.创建新的个人知识库 前面配置完之后,下面讲的再新建 ...
- 工具 – VS Code Extensions
前言 分享我用着的 Extensions. Angular Language Service 不用介绍,用 Angular 的必装. Better Comments 让注释有多点颜色 more col ...
- MDC – Checkbox
前言 Checkbox 不是搭配 TextField 使用, 而是搭配 FormField. 所以独立一篇来写. 参考 Docs – Selection controls: checkboxes 效果 ...
- 图形化客户端工具——Navicat
1.下载 下载地址:https://wwb.lanzoub.com/i4TuZ0g3okod 破解: 解压后有两个文件 先点击第一个文件依次安装 安装完成后 ...
- [34](CSP 集训)CSP-S 联训模拟 1
A 几何 重复若干次 -> 不能重叠,因此考虑直接暴力 DP 设 \(f_{i,j,k}\) 表示主串匹配到第 \(i\) 位(将前 \(i\) 位分别归为两类),其中 \(x\) 在重复了若干 ...
- 非常非常好用的一款账户密码保存工具-KeePass
非常非常好用的一款账户密码保存工具 下载地址: https://sourceforge.net/projects/keepass/files/KeePass%202.x/2.55/KeePass- ...