讨论广场 问答详情
我想用磁场传感器做一个简易指南针。请教下,我应该如何订阅磁场传感器并计算方向角度啊?
一叶知秋 2025-09-12 10:31:27
154 评论 分享
鸿蒙问答专区鸿蒙课程学习

我想用磁场传感器做一个简易指南针。请教下,我应该如何订阅磁场传感器并计算方向角度啊?
相关代码如下:

```ts
sensor.on(sensor.SensorId.MAGNETIC_FIELD, d => {
  const angle = Math.atan2(d.y, d.x) * 180 / Math.PI;
  console.log('heading', angle);
});
```

 

154 评论 分享
写回答
全部评论(1)
1 楼

实现思路
获取传感器权限:申请必要的传感器访问权限

订阅磁场传感器:监听设备磁场变化

数据处理与计算:将原始磁场数据转换为方向角度

UI 显示:将方向角度可视化展示为指南针界面

 

import sensor from '@ohos.sensor';
import { BusinessError } from '@ohos.base';

// 指南针组件
@Entry
@Component
struct CompassComponent {
  @State angle: number = 0;
  @State direction: string = '北';
  private sensorId: sensor.SensorId = sensor.SensorId.MAGNETIC_FIELD;
  private isActive: boolean = false;

  // 生命周期:组件出现时
  aboutToAppear() {
    this.startCompass();
  }

  // 生命周期:组件消失时
  aboutToDisappear() {
    this.stopCompass();
  }

  // 启动指南针
  startCompass() {
    if (this.isActive) return;
    
    try {
      // 订阅磁场传感器
      sensor.on(this.sensorId, (data: sensor.MagneticFieldResponse) => {
        // 计算方向角度
        this.calculateHeading(data.x, data.y);
      });
      
      this.isActive = true;
      console.info('指南针已启动');
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.error(`启动指南针失败. Code: ${err.code}, message: ${err.message}`);
    }
  }

  // 停止指南针
  stopCompass() {
    if (!this.isActive) return;
    
    try {
      // 取消订阅传感器
      sensor.off(this.sensorId);
      this.isActive = false;
      console.info('指南针已停止');
    } catch (error) {
      const err: BusinessError = error as BusinessError;
      console.error(`停止指南针失败. Code: ${err.code}, message: ${err.message}`);
    }
  }

  // 计算方向角度
  calculateHeading(x: number, y: number) {
    // 使用 atan2 计算角度(弧度)
    let angle = Math.atan2(y, x) * 180 / Math.PI;
    
    // 转换为 0-360 度范围
    if (angle < 0) {
      angle += 360;
    }
    
    // 调整角度使 0° 表示正北
    angle = (angle + 360) % 360;
    
    // 更新状态
    this.angle = angle;
    this.direction = this.getDirectionName(angle);
  }

  // 根据角度获取方向名称
  getDirectionName(angle: number): string {
    const directions = ['北', '东北', '东', '东南', '南', '西南', '西', '西北'];
    const index = Math.round(angle / 45) % 8;
    return directions[index];
  }

  // 构建UI
  build() {
    Column() {
      Text(`${this.angle.toFixed(1)}°`)
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 10 })

      Text(this.direction)
        .fontSize(24)
        .fontColor(Color.Blue)
        .margin({ bottom: 30 })

      // 指南针图形
      Stack() {
        // 指南针外圈
        Circle({ width: 200, height: 200 })
          .fill(Color.White)
          .stroke(Color.Gray)
          .strokeWidth(2)

        // 指南针指针
        Polygon()
          .points([[0, -80], [-10, 70], [0, 50], [10, 70]])
          .fill(Color.Red)
          .rotate({ angle: this.angle, centerX: 0, centerY: 0 })
      }
      .width(200)
      .height(200)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

 

2025-09-12 11:44:28