【代码案例】HarmonyOS鸿蒙Next直播界面双击效果动画实现案例
【代码案例】HarmonyOS鸿蒙Next直播界面双击效果动画实现案例 HarmonyOS Next应用开发案例(持续更新中……)
本案例完整代码,请访问:https://gitee.com/harmonyos-cases/cases/tree/master/CommonAppDevelopment/feature/clickanimation
本案例已上架 HarmonyOS NEXT 开源组件市场,如需获取或移植该案例,可安装此插件。开发者可使用插件获取鸿蒙组件,添加到业务代码中直接编译运行。
介绍
本示例展示了如何通过使用 LazyForEach 和 组件内转场 (transition) 实现双击或连续快速点击时的图标动画效果,增强用户交互体验。每次用户双击或连续快速点击特定区域时,都会动态显示图标并带有生动的动画效果,如图标放大淡出或向上移动淡出等。

使用说明
- 背景视频播放:页面加载完成后,背景视频会自动循环播放。
- 点击动画效果:用户双击或连续快速点击页面任意无遮挡的区域,除首次点击外设备轻微振动,在点击位置放大淡入随机图标,并带有抖动效果,然后图标放大淡出消失,每次触发动画页面右下角点赞数加一。
实现思路
ClickAnimationComponent 是一个能够在用户进行双击或连续快速点击交互时展示图标动画,如图标放大淡出或向上移动淡出等动画效果的自定义功能组件。它使用 LazyForEach 动态加载控制点击时图标的上下树,并使用 Stack 布局使出现的图标可叠加显示。源码参考 ClickAnimationComponent.ets。
- 组件使用 Stack 布局承载背景视频和点击区域,以及可能存在的其他功能模块,其中背景视频和其他功能模块都可以由父组件使用 BuilderParam 传入进行自定义配置。
@BuilderParam videoBackgroundSlotParam: () => void = this.videoBackgroundSlot;
@BuilderParam otherFunctionModuleSlotParam: () => void;
build(){
Stack() {
// 背景视频插槽
this.videoBackgroundSlotParam();
// 点击效果区域
Stack(){
// ...
}
// 其他功能模块
if (this.otherFunctionModuleSlotParam) {
this.otherFunctionModuleSlotParam()
}
}
.height($r('app.string.click_animation_full_size'))
.width($r('app.string.click_animation_full_size'))
}
- 点击效果区域使用 Stack 组件,结合 LazyForEach 实现图像元素的动态上下树和叠加显示。
// 点击效果区域
Stack() {
LazyForEach(this.data, (item: ClickIconItem, index: number) => {
Image(item.icon)
.width(this.iconWidth)
.height(this.iconHeight)
// ...
}, (item: ClickIconItem, index: number) => item.id);
}
- 为点击效果区域添加 TapGesture 手势,当用户双击或连续快速点击区域时,如果点击间隔小于500ms,添加新的图标项到 LazyForEach 数据源末尾,此时如果父组件设置了点击回调,则执行回调。
// 点击效果区域
Stack() {
LazyForEach(this.data, (item: ClickIconItem, index: number) => {
// ...
}, (item: ClickIconItem, index: number) => item.id);
}
.gesture(
TapGesture({ count: 1 })
.onAction((event: GestureEvent) => {
if (this.isDoubleClick) {
// 添加新的图标项到数据源,并更新编号
this.data.pushData({
id: this.num.toString(),
icon: this.iconArray[Math.floor(Math.random() * 5)],
position: {
x: event.fingerList[0].localX,
y: event.fingerList[0].localY
}
});
this.num++;
if (this.isOpenVibration) {
// 设置振动效果
this.setVibrator();
}
// 如果父组件设置了点击回调,则执行回调
if (this.clickCallback) {
this.clickCallback();
}
} else {
this.isDoubleClick = true;
}
// 防抖控制,每次点击后都重置定时器,最后一次点击后,延时500ms后,isDoubleClick恢复为false
if (this.timeoutId !== null) {
clearTimeout(this.timeoutId);
}
this.timeoutId = setTimeout(() => {
this.isDoubleClick = false;
this.timeoutId = null;
}, 500);
})
)
- Image 组件设置 transition 转场动画实现图标的动画效果。
- 为显示图标的 Image 组件设置 transition 属性实现转场动画,在入场动画结束后,从数据源移除对应的图标数据,保证图标数据不会一直累积。
LazyForEach(this.data, (item: ClickIconItem, index: number) => {
Image(item.icon)
.width(this.iconWidth)
.height(this.iconHeight)
.position({
x: item.position.x !== undefined ? (item.position.x as number) - this.iconWidth / 2 : 0,
y: item.position.y !== undefined ? (item.position.y as number) - this.iconHeight / 2 : 0,
})
.rotate({ angle: this.iconRotateAngle * (Math.random() * 2 - 1) })
.transition(
this.getAnimation(),
(transitionIn: boolean) => {
// 入场动画结束后,从数据源移除数据
if (transitionIn) {
this.data.shiftData();
}
}
)
}, (item: ClickIconItem, index: number) => item.id);
-
根据设定的动画类型(ScaleUpAndFadeOut 或 MoveUpAndFadeOut),应用不同的动画效果。
-
动画类型为 ScaleUpAndFadeOut 时,入场动画使用 combine 函数组合设置透明度、缩放比例和旋转角度的过渡动画,实现图标放大抖动淡入的效果,出场动画同时设置透明度和缩放比例的过渡动画,实现图标放大淡出的效果。
-
动画类型为 MoveUpAndFadeOut 时,入场动画设置透明度、旋转角度和缩放比例的过渡动画,实现图标缩小抖动淡入的效果,出场动画同时设置透明度、位移和缩放比例的过渡动画,实现图标放大淡出和位移的效果。
ClickAnimationSamplePage 基于 ClickAnimationComponent 组件,通过自定义背景内容和上方叠加的其他 UI 元素构建了一个完整的直播双击点赞场景,并且可以通过传入参数自定义动画行为,例如调整动画速度、改变图标尺寸等。源码参考 ClickAnimationSamplePage.ets。
- 引入功能组件 ClickAnimationComponent,并初始化相关参数,其中 animationType 为动画类型,videoBackgroundSlotParam 和 otherFunctionModuleSlotParam 为 UI 插槽元素,clickCallback 为父组件设置的点击回调。
ClickAnimationComponent({
animationType: this.animationType,
videoBackgroundSlotParam: this.videoBackgroundSlotParam,
otherFunctionModuleSlotParam: () => {
this.otherFunctionModuleSlotParam();
},
clickCallback: this.clickCallback
})
- 通过设置点击回调,可以在每次点击触发图标动画后执行特定操作,例如更新点赞计数。
// 点击回调
private clickCallback: () => void =
() => {
// 每次触发动画,点赞数+1
this.likeNumber++;
};
高性能知识点
点击时出现的图标数据通过 LazyForEach 进行动态加载,并在入场动画结束后从数据源移除数据,以提升性能。
工程结构 & 模块类型
clickanimation // har类型
|---/src/main/ets/components
| |---ClickAnimationComponent.ets // 封装的点击图标动画功能组件
|---/src/main/ets/model
| |---ClickIconDataModel.ets // 数据模型层-点击图标动画功能组件的类型定义和LazyForEach数据模型
| |---ReviewDataModel.ets // 数据模型层-场景页面的类型定义和LazyForEach数据模型
|---/src/main/ets/mock
| |---MockData.ets // mock数据
|---/src/main/ets/utils
| |---Logger.ets // 日志工具类
|---/src/main/ets/views
| |---ClickAnimationSamplePage.ets // 视图层-点击动画场景主页面
模块依赖
- 本示例依赖 动态路由模块 来实现页面的动态加载。
参考资料
更多关于【代码案例】HarmonyOS鸿蒙Next直播界面双击效果动画实现案例的实战教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中实现直播界面双击效果动画,可以使用ArkUI框架提供的动画能力。以下是一个简单的实现案例:
-
定义动画效果: 使用
[@State](/user/State)装饰器定义动画状态,并通过animateTo函数实现动画效果。[@State](/user/State) scale: number = 1.0; [@State](/user/State) opacity: number = 0.0; -
绑定双击事件: 在需要触发动画的组件上绑定
onDoubleClick事件,双击时触发动画。Button() { Text('双击触发动画') } .onDoubleClick(() => { animateTo({ duration: 500 }, () => { this.scale = 1.5; this.opacity = 1.0; }); }) -
应用动画效果: 使用
scale和opacity属性将动画应用到组件上。Image($r('app.media.live')) .scale({ x: this.scale, y: this.scale }) .opacity(this.opacity) -
恢复初始状态: 动画结束后,可以通过
setTimeout函数恢复组件的初始状态。setTimeout(() => { animateTo({ duration: 500 }, () => { this.scale = 1.0; this.opacity = 0.0; }); }, 1000);
通过以上步骤,可以在HarmonyOS鸿蒙Next中实现直播界面双击效果动画。
更多关于【代码案例】HarmonyOS鸿蒙Next直播界面双击效果动画实现案例的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中实现直播界面双击效果动画,可以使用Animator和Component来完成。以下是一个简单示例:
import { Animator, Component, Node } from '@ohos.animator';
@Component
export class DoubleTapAnimation {
private animator: Animator;
onDoubleTap(node: Node) {
this.animator = new Animator(node);
this.animator
.scale({ x: 1.2, y: 1.2 }, 100) // 放大效果
.then(() => this.animator.scale({ x: 1, y: 1 }, 100)) // 恢复原状
.start();
}
}
使用时,在双击事件中调用onDoubleTap方法,传入需要动画的Node即可实现双击放大效果。

