鸿蒙开发:自定义一个圆形动画菜单

前言

在最近上架的应用趣谜语中,有一个功能,点击悬浮菜单后,弹出子菜单,效果如下:

很简单的一个功能,也就是常见的卫星菜单功能,那么在鸿蒙开发中如何来实现呢?想必大家猜到了,也就是利用最简单的属性动画来实现。

最终实现效果

全圆效果

显示在左半边

显示在上半边

当然了,效果展示可以支持8个方位,太多了,这里就不粘贴了,后续大家可以直接看相关Demo即可。

如何实现

原理很简单,默认情况下,所有的卫星菜单都是缩小为0,点击主菜单的时候,让卫星菜单在平移的时候,放大为1即可,唯独需要考虑的就是,卫星菜单的移动位置,需要按照圆的形式进行平移。

算法如下,起始角度和结束角度,可以控制卫星菜单的展示位置,radius半径可以确定卫星菜单和主菜单的距离,平移位置,由于是按圆的形式进行移动,所以,这里需要确认平移角度,利用Math.PI来实现。

TypeScript 复制代码
/**
 * 在圆的指定角度范围内均匀排列小球(修复全圆问题)
 * @param {number} centerX - 圆心X
 * @param {number} centerY - 圆心Y
 * @param {number} radius - 半径
 * @param {number} n - 小球数量
 * @param {number} startAngle - 起始角度(弧度)
 * @param {number} endAngle - 结束角度(弧度)
 * @param {boolean} isFullCircle - 是否是完整圆(特殊处理)
 * @returns {Array} 小球坐标数组
 */
function calculateArcPoints(centerX: number, centerY: number, radius: number, n: number, startAngle: number,
  endAngle: number, isFullCircle = false) {
  const points: ArcPoints[] = [];

  if (n <= 0) {
    return points;
  }

  // 确保角度范围正确
  let angleRange = endAngle - startAngle;
  if (angleRange < 0) {
    angleRange += 2 * Math.PI;
  }

  // 特殊处理:完整圆时,我们希望最后一个点不和第一个点重合
  // 因此角度间隔为 angleRange / n
  // 非完整圆时,角度间隔为 angleRange / (n - 1)
  const angleStep = isFullCircle
    ? angleRange / n
    : (n > 1 ? angleRange / (n - 1) : 0);

  for (let i = 0; i < n; i++) {
    const angle = startAngle + (angleStep * i);
    const x = centerX + radius * Math.cos(angle);
    const y = centerY + radius * Math.sin(angle);

    points.push(new ArcPoints(x, y));
  }

  return points;
}

class ArcPoints {
  x?: number
  y?: number

  constructor(x?: number, y?: number) {
    this.x = x
    this.y = y
  }
}

快速实现

目前我已经封装好了组件,也上传至了中心仓库中,大家如果想快速的实现,可以直接使用。

中心仓库地址:

ohpm.openharmony.cn/#/cn/detail...

依赖

方式一:在Terminal窗口中,执行如下命令安装三方包,DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。

建议:在使用的模块路径下进行执行命令。

TypeScript 复制代码
ohpm install @abner/circle_navigation

方式二:在模块的oh-package.json5中设置三方包依赖,配置示例如下:

TypeScript 复制代码
"dependencies": { "@abner/circle_navigation": "^1.0.1"}

代码使用

需要实现三个属性,parentLayout属性是,父布局,也就是触发的视图,childLayout是子布局,是圆形导航菜单,clickStatus是展示状态,当然了,也有默认的一套UI,如果符合,也可以直接使用默认的。

TypeScript 复制代码
CircleNavigation({
  clickStatus: this.clickStatus,
  parentLayout: () => {
    this.parentLayout()
  },
  childLayout: (position: number) => {
    this.childLayout(position)
  }
})

完整案例

TypeScript 复制代码
@Entry
  @ComponentV2
  struct FullPage {
    @Local clickStatus: boolean = false

    @Builder
    parentLayout() {
      Column() {

      }
      .width(100)
        .height(100)
        .borderRadius(100)
        .backgroundColor(Color.Blue)
        .onClick(() => {
          //点击
          this.clickStatus = !this.clickStatus
        })
    }

    @Builder
    childLayout(position: number) {
      Column() {
        Text((position + 1).toString())
          .fontColor(Color.White)
          .fontWeight(FontWeight.Bold)
      }
      .justifyContent(FlexAlign.Center)
        .width(50)
        .height(50)
        .borderRadius(50)
        .backgroundColor(Color.Blue)
    }

    build() {
      RelativeContainer() {
        ActionBar({ title: "全圆" })
          .alignRules({
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          })
        CircleNavigation({
          clickStatus: this.clickStatus,
          parentLayout: () => {
            this.parentLayout()
          },
          childLayout: (position: number) => {
            this.childLayout(position)
          }
        })
          .alignRules({
            center: { anchor: '__container__', align: VerticalAlign.Center },
            middle: { anchor: '__container__', align: HorizontalAlign.Center }
          })
      }
      .height('100%')
        .width('100%')
    }
  }

相关属性

CircleType

圆形导航菜单位置

相关总结

一个特别简单的卫星菜单,本身并不难,唯独需要掌握就是,卫星菜单移动的圆形位置,其他都是简单的属性动画,希望可以帮助到您。

相关推荐
ToDesk_Daas6 小时前
深度适配鸿蒙生态,ToDesk 迎来版本升级,全面优化远程操控体验
华为·harmonyos
贾伟康6 小时前
【化学实验室|15】HarmonyOS ArkTS 本地状态持久化实战:让保存、删除和页面返回后的数据即时一致
harmonyos·arkts·本地存储·arkui·preferences
芝麻别开门7 小时前
gst-shark安卓编译使用方法
android·gstreamer·gst-shark
老李IT笔记10 小时前
关掉设备上的 AI 扩展:两个键各管一层,配错了等于没配
人工智能·ios·智能手机
2501_9159214310 小时前
iOS应用耗电测试:使用Energy Log、Keymob和Instruments进行性能监控与能源消耗分析
android·ios·小程序·https·uni-app·iphone·webview
蒲公英内测分发11 小时前
热成像仪交付客户后,Android 配套 App 不上架,怎么持续下载安装和更新
android·机器人·项目管理·智能家居·智能硬件
脚踏实地,坚持不懈!11 小时前
Android 常见性能问题总结
android
高旭的旭12 小时前
图解 Android 系统架构:从 App、Framework、HAL 到 Linux 驱动
android·linux·系统架构
hunterandroid12 小时前
Navigation Component 多模块导航与深度链接实战
android
行者-全栈开发12 小时前
【共创稿事节】HarmonyOS 7 轻量悬浮窗口选型与闪控窗接入:闪控球、闪控窗、系统悬浮窗到底怎么选
harmonyos·鸿蒙·arkui·闪控窗·api 26·选型决策树·闪控球