HarmonyOS 鸿蒙Next如何自定义Gauge,增加刻度及将指针置于圆中间

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

HarmonyOS 鸿蒙Next如何自定义Gauge,增加刻度及将指针置于圆中间 有人知道如何自定义Gauge,增加刻度吗,指针放圆的中间

2 回复

参考demo

// CircularSlider.ets
import componentUtils from '@ohos.arkui.componentUtils'
import { JSON } from '@kit.ArkTS'
@Entry
@Component
export struct CircularSlider {
  @State @Watch('onCountUpdated') progressNum: number = 98
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  private context1: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  @State Max_Num: number = 100
  @State angleChange: number = 270 / this.Max_Num;
  @State X: number = 60
  @State Y: number = 10
  @State angle: number = (135 + this.angleChange * this.progressNum) * (Math.PI / 180)
  @State circleX: number = 0
  @State circleY: number = 0
  circleCenterX: number = 60
  circleCenterY: number = 60
  onCountUpdated(): void {
    if (Math.round(this.progressNum * 10) / 10 > this.Max_Num) {
      console.info('progressNum:', this.progressNum)
      this.progressNum = 0
    }
    this.setProgress()
  }
  setProgress = (): void => {
    this.context.clearRect(0, 0, 200, 200)
    //画底层灰色进度条,数值固定不动
    let endAngle: number = this.progressNum //读取当前数值
    if (endAngle > this.Max_Num) {
      endAngle = 0
    } //防止溢出
    let modePosition: componentUtils.ComponentInfo = componentUtils.getRectangleById('flag1'); //获取相对位置信息
    console.log('[modePosition]', JSON.stringify(modePosition))
    this.circleX = px2vp(modePosition?.localOffset?.x + modePosition.size?.width * 0.5) //flag相对父组件的位置加上自身长度,将px转换成pv
    this.circleY = px2vp(modePosition?.localOffset?.x + modePosition.size?.width * 0.5)
    console.log('[circleX]', JSON.stringify(this.circleX))
    console.log('[circleY]', JSON.stringify(this.circleY))
    // 外圈
    this.context.beginPath()
    this.context.arc(this.circleX, this.circleY, 78, 135 * (Math.PI / 180), 45 * (Math.PI / 180))
    this.context.lineWidth = 5
    this.context.strokeStyle = "#fda935"
    this.context.lineCap = 'round'
    this.context.stroke()
    //画选中进度条
    this.context.beginPath()
    let angleChange1: number = (135 + this.angleChange * endAngle + 0.01) * (Math.PI / 180) //计算弧形进度条的结束位置
    this.context.arc(this.circleX, this.circleY, 78, 135 * (Math.PI / 180), angleChange1)
    this.context.lineWidth = 5
    this.context.strokeStyle = "#eeedeb"
    this.context.lineCap = 'round'
    this.context.stroke()
    // 指针
    this.context1.clearRect(0, 0, 200, 200)
    this.context1.beginPath()
    this.context1.moveTo(this.circleCenterX + 50 * Math.cos(this.angle),
      this.circleCenterY + 50 * Math.sin(this.angle)) //起点
    this.context1.lineTo(this.circleCenterX + 0 * Math.cos(this.angle),
      this.circleCenterY + 0 * Math.sin(this.angle)) //终点
    this.context1.lineWidth = 3
    this.context1.strokeStyle = "#fd6eee4a"
    this.context1.lineCap = 'round'
    this.context1.stroke()
    //画内层虚线进度条
    let outerRadius = 70 //外部圆圈半径
    let inerRadius = 65 //内部圆圈半径
    let addAngle: number = 5 * this.angleChange * (Math.PI / 180) //设置数值每变化1,画一条线,防止过于密集
    for (let angle = 135 * (Math.PI / 180); angle <= 405 * (Math.PI / 180); angle += addAngle) {
      this.context.beginPath()
      this.context.moveTo(this.circleX + outerRadius * Math.cos(angle),
        this.circleY + outerRadius * Math.sin(angle)) //起点
      this.context.lineTo(this.circleX + inerRadius * Math.cos(angle),
        this.circleY + inerRadius * Math.sin(angle)) //终点
      this.context.strokeStyle = "#60ffffff"
      this.context.lineWidth = 1 //线段宽度
      this.context.stroke()
    }
  }
  build() {
    RelativeContainer() {
      Canvas(this.context)
        .width("100%")
        .height('100%')
        .onReady(() => {
          this.setProgress()
        })
        .id('canvas1')
      Row() {
        // 圆心(60,60)
        Canvas(this.context1)
          .width("100%")
          .height('100%')
          .borderRadius('50%')
          .position({ y: 0 })
          .onReady(() => {
            this.setProgress()
          })
      }
      .width(120)
      .height(120)
      .borderRadius(60)
      .position({ x: 41, y: 41 })
      Text(this.progressNum.toString())
        .position({ y: '50%', x: '43%' })
        .fontSize(18)
        .fontColor(Color.White)
        .textAlign(TextAlign.Center)
      Text('MB/S')
        .position({ y: '58%', x: '43%' })
        .fontSize(12)
        .fontColor(Color.White)
      Button('num++')
        .onClick((event: ClickEvent) => {
          this.progressNum = Number(Math.round(this.progressNum * 10) / 10 + 1)
          let angleChange1: number = (135 + this.angleChange * this.progressNum) * (Math.PI / 180)
          if (this.angle < angleChange1) {
            this.angle += this.angleChange * (Math.PI / 180)
            console.log('angle: ' + this.angle)
          } else {
            this.angle = 135 * (Math.PI / 180)
          }
        })
        .id('btn')
        .alignRules({
          'bottom': { 'anchor': '__container__', 'align': VerticalAlign.Bottom },
          'middle': { 'anchor': '__container__', 'align': HorizontalAlign.Center }
        })
    }
    .height(300)
    .width(200)
    .id('flag1')
    .backgroundColor('#ff9602')
  }
}

更多关于HarmonyOS 鸿蒙Next如何自定义Gauge,增加刻度及将指针置于圆中间的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,自定义Gauge(仪表盘)组件并增加刻度以及将指针置于圆中间,可以通过以下步骤实现:

  1. 自定义Gauge组件

    • 使用XML布局文件定义Gauge组件,或通过代码动态创建。
    • 自定义Gauge的属性,如大小、颜色等,以满足设计需求。
  2. 增加刻度

    • 在Gauge组件上绘制刻度。可以通过Canvas绘制刻度线,或者使用自定义Drawable资源。
    • 计算并均匀分布刻度线,确保刻度的准确性和可读性。
  3. 将指针置于圆中间

    • 指针通常是一个子View或者Drawable,需要将其定位在Gauge的中心。
    • 通过布局参数或者Canvas的transform方法,将指针的中心点对齐到Gauge的中心点。
    • 根据数据动态调整指针的角度,以反映当前值。

需要注意的是,HarmonyOS提供了丰富的UI组件和绘制API,但具体的实现细节可能因版本和需求而异。开发者应参考最新的HarmonyOS开发文档和API指南,以确保代码的正确性和兼容性。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。在这里,你可以获得更专业的技术支持和解决方案。

回到顶部