当前位置: 首页 > news >正文

鸿蒙(HarmonyOS)ArkTS 实战:animate属性动画可复用圆形扩散菜单

圆形扩散菜单这几年在APP中比较少见了,记得15年左右APP都有各种各样炫酷的动画效果,看到设计搞出来的动画效果就头大因为我不会在当时。这份内容讲一下实现原理已经完整代码。

最终效果

  • 点击主按钮,子菜单沿圆形轨迹向外扩散展开
  • 再次点击,菜单平滑收回、缩放、渐隐
  • 包含位移、透明度、缩放组合动画
  • 支持自定义菜单数量、半径、起始角度、间隔角度

核心原理

  1. 布局:使用Stack堆叠容器,实现菜单居中叠加
  2. 坐标计算:以主按钮为圆心,子菜单中心距离主按钮中心为半径,通过三角函数将角度转为坐标 这样很容易得到子菜单的中心点。
  3. 动画:translate + opacity + scale + 弹簧曲线组合动效。
  4. 通信:父组件控制开关,子组件负责渲染动画(@Prop父子通信)

完整代码

import{curves}from"@kit.ArkUI";// 坐标类型:x + yinterfaceMenuPoint{x:number;y:number;}@Componentexportstruct SpreadMenu{// 接收父组件传:菜单是否打开 + 菜单列表@Prop isOpen:boolean;@Prop menuList:string[];// 配置privateradius:number=90;privatestartAngle:number=180;privateangleStep:number=45;build(){Stack(){// 自动生成菜单ForEach(this.getMenuPositions(),(item:MenuPoint,index:number)=>{this.buildItem(item.x,item.y,this.menuList[index]);})}.width("100%").height("100%");}// 获取所有坐标privategetMenuPositions():MenuPoint[]{constpositions:MenuPoint[]=[];for(leti:number=0;i<this.menuList.length;i++){// 开始角度 + 偏移角度constangle:number=this.startAngle+i*this.angleStep;// 存储每一个子菜单的中心点positions.push({x:this.getX(angle),y:this.getY(angle)});}returnpositions;}// 角度 => XprivategetX(angle:number):number{constradian:number=(angle-90)*Math.PI/180;returnthis.radius*Math.cos(radian);}// 角度 => YprivategetY(angle:number):number{constradian:number=(angle-90)*Math.PI/180;returnthis.radius*Math.sin(radian);}// 子菜单@BuilderbuildItem(x:number,y:number,label:string){Column(){Text(label).fontColor(Color.White).fontSize(12)}.width(50).height(50).backgroundColor("#007AFF").borderRadius(25).justifyContent(FlexAlign.Center).translate({x:this.isOpen?x:0,y:this.isOpen?y:0}).opacity(this.isOpen?1:0).scale({x:this.isOpen?1:0.5,y:this.isOpen?1:0.5}).animation({duration:350,curve:curves.springMotion()});}}@Entry @Component struct SpreadMenuPage{@State isOpen:boolean=false;@State menuList:string[]=["用户","搜索","添加","删除","分享"];build(){Stack({alignContent:Alignment.Center}){// 菜单组件(父组件控制状态)SpreadMenu({isOpen:this.isOpen,menuList:this.menuList})// 主按钮(外置)Button({stateEffect:true,buttonStyle:ButtonStyleMode.NORMAL}){Text('菜单').fontColor(Color.White).textAlign(TextAlign.Center)}.width(60).height(60).backgroundColor("#007AFF").borderRadius(30).onClick(()=>{this.isOpen=!this.isOpen;}).zIndex(999)// 周期1,阻尼0.25 稍微来点弹簧效果.animation({curve:curves.springMotion(1,0.25),duration:1000})}.width('100%').height('100%').backgroundColor('#f5f5f5');}}

菜单动画参数说明

  • translate:沿圆形轨迹移动
  • opacity:渐显渐隐
  • scale:缩放动画
  • springMotion:弹簧曲线

发挥奇思妙想拓展能力,是不是可以增加用手拨动旋转菜单呢。制作炫酷的动画需要一丢丢数学,和对动画路径的熟悉。

http://www.jsqmd.com/news/554052/

相关文章:

  • Qt 串口编程实战:keySight 34401A 万用表数据采集与存储
  • FlowState Lab参数调优实战:如何获得理想的模拟精度与速度
  • SpringBoot锁设计:让你的系统不再“抢”出问题!
  • 如何完整保存QQ空间历史记录?GetQzonehistory让数字回忆不再流失
  • ncmdump:破解NCM格式枷锁的音频自由解决方案
  • 别再只盯着model.score()了!Python机器学习模型评估的5种实用方法对比
  • Windows 11 LTSC微软商店终极解决方案:3分钟实现应用生态完整集成
  • 自动化深度学习-AutoKeras-和-Keras-Tuner-的温和介绍
  • 别再让蜂鸣器只会‘哔哔’叫了!用STM32F103的PWM和电容,DIY你的家电提示音库(附超级玛丽彩蛋)
  • 5分钟快速上手:使用Ag-PSD高效处理Photoshop文档的完整指南
  • 2026年钢格栅板厂家年度排名,哪家靠谱 - 工业推荐榜
  • Calibre中文路径翻译问题全解析:从诊断到解决方案
  • 中国象棋AlphaZero终极指南:5步从零构建你的AI象棋大师
  • 天草逆向教程笔记-全-
  • 避开这些坑!STM32G474 DAC输出正弦波失真、毛刺的排查与优化指南
  • 【CTF | pwn篇】从栈溢出到ROP:ctfshow pwn实战技巧精讲
  • EagleEye效果实测:在JetPack 6.0 + Orin AGX上实现15ms推理的边缘部署方案
  • 自进化人工智能时代已经到来
  • 2026年京津冀好用的钢格栅板定制生产厂家排名 - myqiye
  • Face3D.ai Pro效果展示:不同光照条件下正面人像的3D几何还原精度对比
  • Qwen3Guard-Gen-8B真实案例:如何用AI模型自动拦截不当言论
  • 循环单链表
  • 最佳数据科学家总是持续学习
  • 2026高端晾衣架怎么选?十大品牌选购指南来了! - 匠言榜单
  • 连云港市区本地人推荐的特色家常铁锅炖餐厅
  • 超越跑分:Gemini 3.1 Pro 2026年多维度能力评估体系深度拆解
  • 斯坦福-CS253-网络安全笔记-全-
  • 如何快速掌握Mesa:Python多智能体建模的完整指南
  • 百川2-13B微调实践:为OpenClaw定制专属的自动化指令集
  • OpenClaw技能市场巡礼:Qwen3-32B适配度最高的5个工具