【代码案例】HarmonyOS鸿蒙Next直播界面双击效果动画实现案例

【代码案例】HarmonyOS鸿蒙Next直播界面双击效果动画实现案例 HarmonyOS Next应用开发案例(持续更新中……)

本案例完整代码,请访问:https://gitee.com/harmonyos-cases/cases/tree/master/CommonAppDevelopment/feature/clickanimation

本案例已上架 HarmonyOS NEXT 开源组件市场,如需获取或移植该案例,可安装此插件。开发者可使用插件获取鸿蒙组件,添加到业务代码中直接编译运行。

介绍

本示例展示了如何通过使用 LazyForEach组件内转场 (transition) 实现双击或连续快速点击时的图标动画效果,增强用户交互体验。每次用户双击或连续快速点击特定区域时,都会动态显示图标并带有生动的动画效果,如图标放大淡出或向上移动淡出等。

效果图预览

使用说明

  1. 背景视频播放:页面加载完成后,背景视频会自动循环播放。
  2. 点击动画效果:用户双击或连续快速点击页面任意无遮挡的区域,除首次点击外设备轻微振动,在点击位置放大淡入随机图标,并带有抖动效果,然后图标放大淡出消失,每次触发动画页面右下角点赞数加一。

实现思路

ClickAnimationComponent 是一个能够在用户进行双击或连续快速点击交互时展示图标动画,如图标放大淡出或向上移动淡出等动画效果的自定义功能组件。它使用 LazyForEach 动态加载控制点击时图标的上下树,并使用 Stack 布局使出现的图标可叠加显示。源码参考 ClickAnimationComponent.ets

  1. 组件使用 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'))
}
  1. 点击效果区域使用 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);
}
  1. 为点击效果区域添加 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);
    })
)
  1. 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

  1. 引入功能组件 ClickAnimationComponent,并初始化相关参数,其中 animationType 为动画类型,videoBackgroundSlotParam 和 otherFunctionModuleSlotParam 为 UI 插槽元素,clickCallback 为父组件设置的点击回调。
ClickAnimationComponent({
  animationType: this.animationType,
  videoBackgroundSlotParam: this.videoBackgroundSlotParam,
  otherFunctionModuleSlotParam: () => {
    this.otherFunctionModuleSlotParam();
  },
  clickCallback: this.clickCallback
})
  1. 通过设置点击回调,可以在每次点击触发图标动画后执行特定操作,例如更新点赞计数。
// 点击回调
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            // 视图层-点击动画场景主页面

模块依赖

  1. 本示例依赖 动态路由模块 来实现页面的动态加载。

参考资料


更多关于【代码案例】HarmonyOS鸿蒙Next直播界面双击效果动画实现案例的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

在HarmonyOS鸿蒙Next中实现直播界面双击效果动画,可以使用ArkUI框架提供的动画能力。以下是一个简单的实现案例:

  1. 定义动画效果: 使用[@State](/user/State)装饰器定义动画状态,并通过animateTo函数实现动画效果。

    [@State](/user/State) scale: number = 1.0;
    [@State](/user/State) opacity: number = 0.0;
    
  2. 绑定双击事件: 在需要触发动画的组件上绑定onDoubleClick事件,双击时触发动画。

    Button() {
        Text('双击触发动画')
    }
    .onDoubleClick(() => {
        animateTo({ duration: 500 }, () => {
            this.scale = 1.5;
            this.opacity = 1.0;
        });
    })
    
  3. 应用动画效果: 使用scaleopacity属性将动画应用到组件上。

    Image($r('app.media.live'))
        .scale({ x: this.scale, y: this.scale })
        .opacity(this.opacity)
    
  4. 恢复初始状态: 动画结束后,可以通过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中实现直播界面双击效果动画,可以使用AnimatorComponent来完成。以下是一个简单示例:

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即可实现双击放大效果。

回到顶部