DEV Community

HarmonyOS
HarmonyOS

Posted on

Building a Real-Time Compass App on HarmonyOS NEXT Wearables with ArkTS

Read the original article:Building a Real-Time Compass App on HarmonyOS NEXT Wearables with ArkTS

🧭Introduction

Wearable devices are evolving beyond simple step counters and notification tools. They are now used for safety, navigation, and real-time awareness — especially during outdoor activities such as hiking, biking, or emergency travel. In this article, we’ll walk through how to build a Compass Application using ArkTS for HarmonyOS NEXT Wearables, leveraging sensor data to display the user’s current direction in degrees (azimuth).

We’ll make use of the ROTATION_VECTOR sensor, a powerful input that combines data from the accelerometer and gyroscope to detect orientation accurately. The result? A fully functional, lightweight compass running on your HarmonyOS-powered watch.

🖼️ Screenshot Preview

🧱Project Overview

  • Platform: HarmonyOS NEXT (Wearables)
  • Language: ArkTS (Ark TypeScript)
  • Kit Used: SensorServiceKit
  • Sensor: ROTATION_VECTOR
  • Permission Required: ohos.permission.ACCELEROMETER
  • UI Framework: ArkUI with Stack, Column, Text, Image
  • Use Case: Directional navigation and outdoor assistance

Why ROTATION_VECTOR?

The ROTATION_VECTOR sensor provides the device's orientation in 3D space using quaternion mathematics. Compared to using raw accelerometer and magnetometer data, this sensor offers:

  • Faster response
  • Better stability
  • Less noise
  • No need for manual filtering

By converting the quaternion data into azimuth degrees, we can determine which direction (North, South, East, or West) the user is facing.

🔐Adding Permissions

In your module.json5, declare the required sensor permission:

"requestPermissions": [
  {
    "name": "ohos.permission.ACCELEROMETER"
  }
]
Enter fullscreen mode Exit fullscreen mode

This permission is essential to access sensor data on HarmonyOS NEXT wearables.

Implementing Compass Logic with ArkTS

Here's the core logic that powers the Compass App:

import { sensor } from "@kit.SensorServiceKit";

@Entry
@Component
export struct Index {
  @State azimuth: number = 0

  onPageShow() {
    sensor.on(sensor.SensorId.ROTATION_VECTOR, (data: sensor.RotationVectorResponse) => {
      const { x, y, z, w } = data;

      const siny_cosp = 2 * (w * z + x * y)
      const cosy_cosp = 1 - 2 * (y * y + z * z)
      const azimuthRad = Math.atan2(siny_cosp, cosy_cosp)
      const azimuthDeg = (azimuthRad * 180 / Math.PI + 360) % 360

      this.azimuth = Math.round(azimuthDeg)
    }, {
      interval: 100_000_000  // 100ms
    })
  }

  aboutToAppear() {
    this.onPageShow()
  }

  aboutToDisappear() {
    sensor.off(sensor.SensorId.ROTATION_VECTOR)
  }

  build() {
    NavDestination() {
      Stack() {
        Rect()
          .width('100%')
          .height('100%')

        Column({ space: 20 }) {
          Text(`Azimuth: ${this.azimuth}°`)
            .fontSize(15)
            .fontWeight(FontWeight.Bold)
            .fontColor(Color.White)

          Image($r('app.media.compass_vector'))
            .width(150)
            .height(150)
            .rotate({ angle: -this.azimuth })
        }
      }
      .width('100%')
      .height('100%')
    }
    .hideTitleBar(true)
  }
}
Enter fullscreen mode Exit fullscreen mode

How Azimuth is Calculated

The calculation uses the following steps:

  • Extract quaternion values (x, y, z, w) from RotationVectorResponse.
  • Use the standard atan2 formula to calculate azimuth in radians:

const azimuthRad = Math.atan2(siny_cosp, cosy_cosp)

Convert to degrees and normalize:

const azimuthDeg = (azimuthRad * 180 / Math.PI + 360) % 360

Display and rotate the compass image accordingly.

This method ensures fast and accurate direction tracking, even when the user rotates or tilts the device.

UI Design: Stack + Rotation

The UI uses a Stack layout to layer elements, and a rotating Image for the compass direction:

Image($r('app.media.compass_vector'))
  .width(150)
  .height(150)
  .rotate({ angle: -this.azimuth })
Enter fullscreen mode Exit fullscreen mode

The compass image rotates in real-time based on azimuth, delivering a fluid and intuitive directional guide.

⚙️ Optimization Tips

  • Use interval: 100_000_000 to avoid battery drain while keeping updates responsive.
  • Disable the sensor listener in aboutToDisappear() to free resources.
  • For outdoor modes, consider adding GPS fallback if magnetic interference is detected.

✅ Conclusion

By using HarmonyOS NEXT and ArkTS, you can easily build a modern, responsive compass app tailored for wearable devices. Leveraging the ROTATION_VECTOR sensor provides real-time orientation data, enabling practical use cases for adventurers, travelers, and everyday users.

This project demonstrates the power of HarmonyOS’s wearable SDKs and opens the door for further innovation on wrist-based apps.

Written by Muhammet Cagri Yilmaz

Top comments (0)