HarmonyOS 鸿蒙Next弧形菜单实现是否有demo参考

发布于 1周前 作者 eggper 来自 鸿蒙OS

HarmonyOS 鸿蒙Next弧形菜单实现是否有demo参考 这种弧形菜单是否有demo参考?

126a3631ab9f0df1f640fcf35f5001f1.gif


更多关于HarmonyOS 鸿蒙Next弧形菜单实现是否有demo参考的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复
您好,可以参考如下demo

```kotlin
import { componentUtils, display } from '[@kit](/user/kit).ArkUI';
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';

[@Component](/user/Component)
export struct Index {
  [@State](/user/State) stackAngle: number = 0
  private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.All })
  [@State](/user/State) ImageWidth: number = 100
  [@State](/user/State) ImageHeight: number = 200
  [@State](/user/State) x1: number = 0
  [@State](/user/State) y1: number = 0
  [@State](/user/State) x2: number = 0
  [@State](/user/State) y2: number = 0
  [@State](/user/State) distance: number = 0
  [@State](/user/State) screenWidth: number = 0
  private imageList: Array<string> =
    ["app.media.a", "app.media.b", "app.media.c", "app.media.a", "app.media.b", "app.media.b", "app.media.b",
      "app.media.b", "app.media.b", "app.media.b", "app.media.b", "app.media.b", "app.media.b", "app.media.c",
      "app.media.c", "app.media.c", "app.media.c"]
  // 
  private points: number[][] = [];

  aboutToAppear(): void {
    this.getScreenWidth()
    this.calculatePointsOnCircle(0, 200, 200, this.imageList.length);
  }

  [@State](/user/State) planA: boolean = true;

  build() {
    NavDestination() {
      Column() {
        Stack() {
          ForEach(this.imageList, (item: string, index: number) => {
            Image($r(item))
              .width(this.ImageWidth)
              .height(this.ImageHeight)
              .border({ color: "#FFF", width: 2 })
              .position({
                x: this.points[index][0],
                y: this.points[index][1]
              })
              .rotate({ centerX: 100 / 2, centerY: 200 / 2, angle: this.getAngele(index) })
              .zIndex(this.imageList.length - index)
              .id(`${index}`)
          })
        }
        //centerY = 图片高度 + 圆的半径
        .rotate({ angle: this.stackAngle, centerY: 200 + 100 })
      }.height('100%')
      .width('100%')
      .backgroundColor("#ffa7a7a7")
      .gesture(
        PanGesture(this.panOption)
          .onActionStart((event: GestureEvent) => {
            console.info('Pan start', event.offsetX)
            let info = event.fingerList[0]
            this.x1 = px2vp(this.screenWidth) / 2 - info.globalX
            this.y1 = 200 + 100 - info.globalY
            console.log('Pan start', this.x1, this.y1)
          })
          .onActionEnd((event: GestureEvent) => {
            console.info('Pan end', event.offsetY)
            console.log('Pan end', this.x2, this.y2)
          })
          .onActionUpdate((event: GestureEvent) => {
            console.log("this.stackAngle = " + this.stackAngle)
            if (event) {
              let info = event.fingerList[0]
              this.x2 = px2vp(this.screenWidth) / 2 - info.globalX
              this.y2 = 200 + 100 - info.globalY
              this.distance = Math.sqrt((event.offsetX) * (event.offsetX) + (event.offsetY) * (event.offsetY))
              if ((this.x1 * this.y2 - this.x2 * this.y1) > 0) {
                this.stackAngle = (this.stackAngle + (this.distance / 60)) % 360
              } else {
                this.stackAngle = (this.stackAngle - (this.distance / 60)) % 360
              }
            }
          })
      )
    }
  }

  getAngele(index: number): number {
    let length = this.imageList.length;
    let midIndex = length / 2
    if (index <= midIndex) {
      console.log('角度1 = ' + 360 / length * index)
      return 360 / length * index
    } else {
      console.log('角度2 = ' + (-360 / length * (length - index)))
      return -360 / length * (length - index)
    }
  }

  /**
   * 输入 圆心x,y、 半径、均匀分布的数量
   * 返回一组坐标x=0 / y=200 /r=100
   */
  calculatePointsOnCircle(x: number, y: number, r: number, n: number) {
    const theta = (2 * Math.PI) / n;
    for (let i = 0; i < n; i++) {
      const cx: number = r * Math.cos(i * theta - Math.PI / 2);
      const cy: number = r * Math.sin(i * theta - Math.PI / 2);
      const pointX: number = Math.ceil(x + cx);
      const pointY: number = Math.ceil(y + cy);
      console.log('坐标 x = ' + pointX + ', y = ' + pointY)
      this.points.push([pointX, pointY]);
    }
  }

  getScreenWidth() {
    let displayClass: Array<display.Display> = [];
    display.getAllDisplays((err: BusinessError, data: Array<display.Display>) => {
      this.screenWidth = data[0].width
      console.log('width = ' + this.screenWidth)
      const errCode: number = err.code;
      if (errCode) {
        console.error(`Failed to obtain all the display objects. Code: ${err.code}, message: ${err.message}`);
        return;
      }
      console.info(`Succeeded in obtaining all the display objects. Data: ` + JSON.stringify(data));
    });
  }
}

更多关于HarmonyOS 鸿蒙Next弧形菜单实现是否有demo参考的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


先mark下,蹲个解决方案

鸿蒙Next弧形菜单实现的确存在相关的Demo参考。鸿蒙系统作为华为自主研发的操作系统,提供了丰富的UI组件和动画效果,以便开发者实现多样化的用户界面。

对于弧形菜单,鸿蒙系统本身可能不直接提供一个完整的弧形菜单组件,但开发者可以通过组合使用鸿蒙提供的现有组件(如列表、网格、动画等)来实现这一功能。在鸿蒙的开发者社区或官方示例代码中,可以搜索到一些类似的自定义组件或动画效果的实现,这些都可以作为实现弧形菜单的参考。

具体来说,开发者可能需要:

  1. 定义一个自定义的弧形布局,通过调整子视图的位置和角度来形成弧形。
  2. 使用动画效果来实现菜单项的展开和收起,增加用户体验。
  3. 监听用户的点击或滑动事件,实现菜单项的交互功能。

在鸿蒙的开发者文档中,有详细的UI组件和动画效果的介绍,开发者可以参考这些文档来实现自己的弧形菜单。

如果开发者在实现过程中遇到困难,除了参考官方文档和示例代码外,还可以考虑在鸿蒙的开发者社区中寻求帮助。当然,如果问题依旧没法解决请联系官网客服,官网地址是:

回到顶部