鸿蒙项目:动效示例(ArkTS)

打印 上一主题 下一主题

主题 810|帖子 810|积分 2430

中工学子带你探索 ArkTS 动效示例:打造炫酷交互体验

摘要: 本文聚焦于使用 ArkTS 为组件属性添加过渡动态结果的项目实践,详细阐述了项目实现的功能、涉及的相关概念、使用方法以及约束限制,旨在分享如何通过 ArkTS 提拔用户体验,为前端开发爱好者提供有益参考。作为中原工学院的学生,盼望借此机会与偕行交流学习,共同进步。
一、引言

在当今数字化时代,用户对于应用的交互体验要求越来越高。动效作为提拔用户体验的关键因素之一,能够让应用更加生动、有趣且易于操纵。ArkTS 作为一种强盛的开发工具,为我们实现炫酷动效提供了便捷途径。在中原工学院的学习过程中,接触到这个基于 ArkTS 的动效示例项目,深感其魅力,遂决定深入分析并分享给大家。
二、项目功能亮点

(一)中心旋转动画

点击动画触发按钮,这一简单操纵引发了极具视觉冲击力的结果 —— 动画图标仿佛从甜睡中苏醒,由中心优雅地旋转而出,瞬间捉住用户的目光。而当再次点击中心按钮时,动画图标又犹如收到归巢指令,从四周有序地缩回,整个过程流畅自然,为用户带来新奇的交互感受。这种动态的出现方式不但增加了趣味性,还使得界面操纵逻辑更加清晰,用户能够直观地知晓按钮的触发结果。
(二)图标个性化动画

当用户将注意力转移到单个图标上,点击它时,图标仿佛被赋予了生命。它会迅速做出反应,先是举行缩放,仿佛在向用户 “打招呼”,展示本身;接着开始旋转,犹如在欢快地舞蹈,吸引用户的进一步关注;同时,透明度也会发生变化,营造出一种若隐若现的梦幻感。这些动画结果的组合,让图标不再是静态的标识,而是成为了与用户互动的小精灵,极大地提拔了用户与界面的交互深度。
(三)滑动条控制图标数量

为了满足用户多样化的需求,项目还知心地设置了滑动条组件(Slider)。通过滑动下方的滑动条,用户能够轻松掌控动画图标的数量。滑动条的调节范围经过经心设计,最少可以显示 3 个动画图标,包管界面不会过于空旷;最多则可到达 6 个,当用户想要更多视觉元素点缀时,能够随心调整。这种灵活的设置方式,使得应用能够顺应不同用户的审美偏好以及不同场景下的展示需求。
三、环境搭建

(一)、导入模块

  1. import { AnimationWidgets } from '../view/AnimationWidgets';
  2. import { CountController } from '../view/CountController';
  3. import Common from '../common/constants/Const';
  4. import {IconsModel} from '../viewmodel/IconsModel';
复制代码
这里导入了几个关键模块:


  • AnimationWidgets:应该是负责处理动画相关的组件模块,从 ../view/ 路径引入,大概率包含了创建和管理各种动画结果的函数或组件类,好比前面提到的图标旋转、缩放等动画逻辑可能封装在此模块内。
  • CountController:看样子是用于控制数量的组件模块,同样来自 ../view/ 路径,推测与控制动画图标数量有关,可能包含处理滑动条交互以及根据数量调整界面显示的功能。
  • Common:是从 ../common/constants/Const 导入的,它通常作为一个公共的常量设置模块,可能包含如默认的宽度(DEFAULT_FULL_WIDTH)、高度(DEFAULT_FULL_HEIGHT)、图像最小数量(IMAGES_MIN)、偏移半径(OFFSET_RADIUS)等常量定义,方便在整个项目中同一使用,避免硬编码带来的维护题目。
  • IconsModel:从 ../viewmodel/ 路径引入,这应该是与图标数据模型相关的模块,用于创建图标相关的数据模型实例,它接收图标数量和偏移半径等参数来初始化,以便管理图标相关的业务逻辑,如图标状态、动画属性关联等。
(二)、组件定义

  1. @Entry
  2. @Component
  3. struct Index {
  4.   @State quantity: number = Common.IMAGES_MIN;
  5.   @Provide iconModel: IconsModel = new IconsModel(this.quantity, Common.OFFSET_RADIUS);
  6.   build() {
  7.     Column() {
  8.       AnimationWidgets({
  9.         quantity: $quantity
  10.       })
  11.       CountController({
  12.         quantity: $quantity
  13.       })
  14.     }
  15.    .width(Common.DEFAULT_FULL_WIDTH)
  16.    .height(Common.DEFAULT_FULL_HEIGHT)
  17.    .backgroundColor($r('app.color.bgColor'))
  18.   }
  19. }
复制代码

  • @Entry 和 @Component 装饰器:

    • @Entry 标记这个 Index 组件是应用的入口组件,意味着当应用启动时,起首渲染的就是这个组件。
    • @Component 表明这是一个自定义组件,遵循特定的组件化开发规范,方便举行模块化管理和复用。

  • 组件状态:

    • @State quantity: number = Common.IMAGES_MIN;:定义了一个名为 quantity 的状态变量,它初始化为 Common 模块中定义的 IMAGES_MIN 常量值,这个状态变量很可能用于存储当前显示的动画图标数量,而且由于使用了 @State 装饰器,当它的值发生改变时,组件会自动重新渲染,以反映最新的状态。

  • 数据提供:

    • @Provide iconModel: IconsModel = new IconsModel(this.quantity, Common.OFFSET_RADIUS);:创建了一个 IconsModel 实例并通过 @Provide 装饰器提供给子组件使用,它传入当前的图标数量 this.quantity 和偏移半径 Common.OFFSET_RADIUS,子组件可以通过依赖注入的方式获取这个数据模型,以便协同处理图标相关的业务逻辑,包管数据的一致性和高效传递。

  • build 方法:

    • 构建了一个 Column 布局组件,它将作为容器垂直排列子组件。
    • 在 Column 内包含了两个子组件:

      • AnimationWidgets({ quantity: $quantity }):向 AnimationWidgets 组件传递了当前的图标数量 $quantity(这里 $ 符号通常表现对状态变量的引用,确保传递的是动态变化的值),这个组件负责展示动画结果,如前面提到的图标从中心旋转收支、点击图标后的缩放旋转等动画逻辑应该在此组件内部实现。
      • CountController({ quantity: $quantity }):同样接收 $quantity,用于展示和控制图标数量,内里应该包含了滑动条组件以及相应的交互逻辑,实现通过滑动条调整图标数量,而且及时更新 quantity 状态,反馈到整个界面。

    • 末了设置了 Column 的宽度为 Common.DEFAULT_FULL_WIDTH,高度为 Common.DEFAULT_FULL_HEIGHT,配景颜色为 $r('app.color.bgColor'),这里 $r 可能是一个资源引用函数,用于获取应用资源中的配景颜色值,确保界面在视觉上的一致性和规范性。

总体而言,这段代码构建了一个应用的入口组件,通过整合动画展示组件和数量控制组件,实现了一个具备动态图标结果和可调节图标的交互界面,同时遵循精良的模块化开发和数据管理规范。
(三).核心代码

  1. import hilog from '@ohos.hilog';
  2. import UIAbility from '@ohos.app.ability.UIAbility';
  3. import Window from '@ohos.window';
  4. export default class EntryAbility extends UIAbility {
  5.     onCreate(want, launchParam) {
  6.         hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
  7.         hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  8.         hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
  9.         hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
  10.     }
  11.     onDestroy() {
  12.         hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
  13.         hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  14.     }
  15.     onWindowStageCreate(windowStage: Window.WindowStage) {
  16.         // Main window is created, set main page for this ability
  17.         hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
  18.         hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
  19.         windowStage.loadContent('pages/Index', (err, data) => {
  20.             if (err.code) {
  21.                 hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.ERROR);
  22.                 hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
  23.                 return;
  24.             }
  25.             hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
  26.             hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
  27.         });
  28.     }
  29.     onWindowStageDestroy() {
  30.         // Main window is destroyed, release UI related resources
  31.         hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
  32.         hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  33.     }
  34.     onForeground() {
  35.         // Ability has brought to foreground
  36.         hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
  37.         hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  38.     }
  39.     onBackground() {
  40.         // Ability has back to background
  41.         hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO);
  42.         hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  43.     }
  44. }
复制代码
  1. import { IconsModel } from '../viewmodel/IconsModel';
  2. import { IconAnimation } from './IconAnimation';
  3. import Common from '../common/constants/Const';
  4. import IconItem from '../viewmodel/IconItem';
  5. @Component
  6. export struct AnimationWidgets {
  7.   @State mainFlag: boolean = false;
  8.   @Link @Watch('onQuantityChange') quantity: number;
  9.   @Consume iconModel: IconsModel;
  10.   onQuantityChange() {
  11.     this.iconModel.addImage(this.quantity);
  12.   }
  13.   aboutToAppear() {
  14.     this.onQuantityChange();
  15.   }
  16.   animate() {
  17.     animateTo(
  18.       {
  19.         delay: Common.DELAY_10,
  20.         tempo: Common.TEMPO,
  21.         iterations: 1,
  22.         duration: Common.DURATION_500,
  23.         curve: Curve.Smooth,
  24.         playMode: PlayMode.Normal
  25.       }, () => {
  26.         this.mainFlag = !this.mainFlag;
  27.     })
  28.   }
  29.   build() {
  30.     Stack() {
  31.       Stack() {
  32.         ForEach(this.iconModel.imagerArr, (item: IconItem) => {
  33.           IconAnimation({
  34.             item: item,
  35.             mainFlag: $mainFlag
  36.           })
  37.         }, (item: IconItem) => JSON.stringify(item.index))
  38.       }
  39.       .width(Common.DEFAULT_FULL_WIDTH)
  40.       .height(Common.DEFAULT_FULL_HEIGHT)
  41.       .rotate({
  42.         x: 0,
  43.         y: 0,
  44.         z: 1,
  45.         angle: this.mainFlag ? Common.ROTATE_ANGLE_360 : 0
  46.       })
  47.       Image(
  48.           this.mainFlag
  49.           ? $r("app.media.imgActive")
  50.           : $r("app.media.imgInit")
  51.       )
  52.         .width($r('app.float.size_64'))
  53.         .height($r('app.float.size_64'))
  54.         .objectFit(ImageFit.Contain)
  55.         .scale({
  56.           x: this.mainFlag ? Common.INIT_SCALE : 1,
  57.           y: this.mainFlag ? Common.INIT_SCALE : 1
  58.         })
  59.         .onClick(() => {
  60.           this.iconModel.reset();
  61.           this.animate();
  62.         })
  63.       Text($r('app.string.please_click_button'))
  64.         .fontSize($r('app.float.size_16'))
  65.         .opacity(Common.OPACITY_06)
  66.         .fontColor($r('app.color.fontGrayColor'))
  67.         .fontWeight(Common.FONT_WEIGHT_500)
  68.         .margin({
  69.           top: $r('app.float.size_100')
  70.         })
  71.     }
  72.     .width(Common.DEFAULT_FULL_WIDTH)
  73.     .layoutWeight(1)
  74.   }
  75. }
复制代码

 

 

 

四、使用分析

(一)动画触发操纵

当用户进入首页,映入眼帘的便是那个充满魔力的按钮。初次点击,系统迅速相应,根据当前滑动条设定的图标数量,相应数量的图标以中心旋转的方式华丽登场。这一场景就像是一场精彩演出的开场,瞬间点燃用户的探索欲望。而当用户想要收起这些图标时,再次点击按钮,图标们便默契地从四周旋转缩回原点,整个过程犹如一场完满编排的舞蹈,收放自如。
(二)滑动条调节

位于界面下方的滑动条,设计得简洁明了。用户只需轻轻滑动手指,就能及时看到动画图标数量的变化。向左滑动,图标数量渐渐减少至最少 3 个,界面变得简洁清新,适合追求简约风格的用户;向右滑动,图标数量增多,最多可达 6 个,为那些喜好丰富视觉结果的用户提供更多选择。这种及时反馈的调节机制,让用户能够快速找到本身心仪的界面布局。
(三)图标点击交互

每个动画图标都等待着用户的 “宠幸”。当用户手指点击某个图标时,它立刻开启专属的表演。先是快速缩放,以突出自身,吸引用户的注意力;接着开始旋转,仿佛在向用户展示它的灵动;同时,透明度也随之变化,在旋转与缩放过程中营造出层次感。这一系列动画结果的无缝衔接,让用户与图标之间建立起独特的互动接洽,进一步加强了用户对应用的好感度。
五、约束与限制

(一)运行平台限制

必要注意的是,本示例目前仅支持尺度系统上运行,且适配的设备为华为手机或运行在 DevEco Studio 上的华为手机设备模仿器。这意味着在其他品牌手机或非尺度系统环境下,可能无法完满出现预期的动效,甚至可能出现兼容性题目。这一方面是由于 ArkTS 在不同平台上的适配工作尚未全面铺开,另一方面也与项目所依赖的华为特定底层技能有关。
(二)版本要求

本示例基于 Stage 模型构建,对 API version 有明白要求,仅支持 API version 9。这就犹如搭建高楼大厦必要特定规格的基石一样,较低版本的 API 可能缺少实现这些炫酷动效所需的功能接口,而过高版本则可能存在兼容性隐患。同时,在编译运行环节,必须使用 DevEco Studio 3.1 Release 版本。这是由于该版本的编译器针对本示例的代码结构、依赖库等举行了优化,能够确保项目顺利运行,避免因版本差异导致的编译错误或运行时异常。
六、总结与展望

通过对这个 ArkTS 动效示例项目的深入研究与实践,作为中原工学院的学生,不但把握了前沿的前端开发技能,更体会到了动效设计对于提拔用户体验的巨大代价。在项目实施过程中,虽然碰到了运行平台和版本限制等挑衅,但也正是这些题目促使我们更加深入地了解技能底层原理。将来,盼望 ArkTS 能够进一步拓展跨平台兼容性,让更多开发者能够使用其打造出惊艳的动效作品。同时,我们也将在校园学习中继承探索,将这些技能应用到更多现实项目中,为推动数字化交互设计发展贡献本身的力量。
盼望本文能够对广大 CSDN 读者有所帮助,接待大家一起交流探讨 ArkTS 开发中的点点滴滴,共同成长进步!
如侵权必删!!
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

光之使者

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表