Building a Professional RGB Color Wheel Picker for HarmonyOS PC with ArkTS
This tutorial walks through creating a high-performance HSV-based color wheel component for HarmonyOS PC using ArkTS and ArkUI, covering mathematical foundations, bidirectional RGB/HSV/Hex synchronization, mouse interaction handling, and on-device verification with DevEco Studio and HDC commands.
The article begins by explaining why HarmonyOS PC development demands custom high-performance components, shifting from mobile "small-screen interaction" to desktop "large-screen precise operation." A professional color picker must provide intuitive geometric interaction via a color wheel mapping hue (angle) and saturation (radius), real-time bidirectional binding across RGB, HSV, and Hex values, and 60 FPS performance on high-DPI displays.
Mathematical Foundations: HSV Color Model and Coordinate Conversion
The color wheel is essentially a polar-to-RGB mapping. The HSV model aligns with human intuition: Hue (0–360°) represents the angle around the wheel, Saturation (0–100%) is the radial distance from center (white) to edge (pure color), and Value (brightness) is controlled via a separate slider.
When a user clicks at coordinates (x, y) relative to the wheel center:
Distance calculation: distance = sqrt((x - centerX)² + (y - centerY)²) Angle calculation: angle = atan2(y - centerY, x - centerX) * 180 / PI, normalized to 0–360°
Mapping: Hue = angle; Saturation = (distance / radius) * 100
An accompanying diagram illustrates the polar coordinate system overlaid on the color wheel.
Development Environment
IDE: DevEco Studio 6.0.2 Beta 2 or later
SDK: OpenHarmony SDK Version 12+
Runtime: Built-in PC emulator (virtual machine)
Third-party libraries recommended on AtomGit (https://atomgit.com)
Core Implementation
ColorUtils.ts – Color Space Conversions
A static utility class handles HSV↔RGB↔Hex conversions:
export class ColorUtils { // HSV to RGB static hsvToRgb(h: number, s: number, v: number) { s /= 100; v /= 100; let c = v * s; let x = c * (1 - Math.abs((h / 60) % 2 - 1)); let m = v - c; let r = 0, g = 0, b = 0; if (h < 60) { r = c; g = x; } else if (h < 120) { r = x; g = c; } else if (h < 180) { g = c; b = x; } else if (h < 240) { g = x; b = c; } else if (h < 300) { r = x; b = c; } else { r = c; b = x; } return { r: Math.round((r + m) * 255), g: Math.round((g + m) * 255), b: Math.round((b + m) * 255) }; } // RGB to Hex string static rgbToHex(r: number, g: number, b: number): string { const toHex = (n: number) => n.toString(16).padStart(2, '0').toUpperCase(); return `#${toHex(r)}${toHex(g)}${toHex(b)}`; }}RGBColorWheel.ets – Interactive Component
The component uses @State for reactive properties: selectedColor (Hex), hue, saturation, value, and separate red, green, blue channels. Private constants define wheel geometry ( wheelRadius = 120, center at 150,150).
Click handling: handleWheelClick computes distance and angle from click coordinates, clamps within radius, updates hue and saturation, then calls syncColor(true) to propagate HSV→RGB→Hex.
private handleWheelClick(event: ClickEvent): void { const x = event.x - this.centerX; const y = event.y - this.centerY; const distance = Math.sqrt(x * x + y * y); if (distance <= this.wheelRadius) { let angle = Math.atan2(y, x) * 180 / Math.PI; if (angle < 0) angle += 360; this.hue = Math.round(angle); this.saturation = Math.round((distance / this.wheelRadius) * 100); this.syncColor(true); }}Bidirectional sync: syncColor(fromHsv: boolean) converts HSV→RGB when fromHsv is true, otherwise RGB→Hex. The Hex string is always updated via ColorUtils.rgbToHex.
UI structure: A Stack contains a white Circle as the wheel base, a draggable indicator Circle positioned using polar math ( cos(hue)*saturation*radius, sin(hue)*saturation*radius), and a center preview Circle filled with selectedColor. The Stack has an onClick handler. Below, three Slider rows (R/G/B, 0–255) call syncColor(false) on change, enabling RGB→HSV→Hex updates and moving the indicator accordingly. A
@Builder RGBControlRowencapsulates each slider row.
On-Device Verification with DevEco Studio and HDC
Previewer alone is insufficient; mouse events and performance must be validated on the PC emulator.
Launch VM: Open Device Manager in DevEco Studio, start "HarmonyOS PC" emulator, wait for desktop.
Check connection: hdc list targets → shows emulator-5554.
Install HAP: Push via
hdc file send ./entry/build/default/outputs/hap/debug/entry-default-debug.hap /data/local/tmp/, then
hdc shell "bm install -p /data/local/tmp/entry-default-debug.hap".
Launch app:
hdc shell "aa start -a EntryAbility -b com.example.myapplication".
Monitor logs: hdc hilog | grep "ColorPicker" to verify no conversion exceptions.
Verification Results
Wheel click test: Clicking the blue edge region instantly updates center preview to blue, Hex shows #0000FF, B slider moves high, R/G sliders drop.
Slider linkage test: Dragging R slider changes center color in real time; wheel indicator repositions per computed HSV, confirming bidirectional HSV<->RGB sync correctness.
A GIF demonstrates the live interaction.
Summary
Starting from color science, the article combines ArkTS declarative UI architecture to deliver a fully functional RGB color wheel picker with PC-grade desktop interaction. Testing on the HarmonyOS PC emulator confirms smooth 60 FPS performance and zero calculation drift. The author encourages developers to leverage DevEco Studio, NDK, and ArkTS to port more professional tools into the HarmonyOS PC ecosystem. Project source: https://atomgit.com/aasd23/music_player
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
HarmonyOS Developer Technology
HarmonyOS developers provide key technology analysis, version updates, Codelabs practice, and event information for HarmonyOS. Welcome developers to join the HarmonyOS ecosystem and create infinite possibilities together!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
