Read the original article:How to Create an Interactive Trivia Wheel on Wearables with mpchart?
How to Create an Interactive Trivia Wheel on Wearables with mpchart?
Requirement Description
This article describes how to implement an interactive, spinning trivia wheel application on a wearable device. The application, built with ArkUI, utilizes the @ohos/mpchart library to display a pie chart. When a user taps a button, the chart spins and randomly selects a trivia category, which is then displayed on the screen.
Background Knowledge
Wearable devices present unique challenges due to their limited screen size and processing power. Effectively visualizing data and creating engaging user experiences within these constraints is crucial. The @ohos/mpchart library, a port of the popular openharmony library, is an excellent choice for this purpose. It offers a wide range of chart types and customization options, while also being optimized for performance. ArkUI's declarative nature simplifies the UI development process, allowing for the creation of fluid and responsive interfaces.
Implementation Steps
-
Project Setup: Ensure the
@ohos/mpchartdependency is added to your project'soh-package.json5file. -
Chart Initialization: In the
aboutToAppearlifecycle hook, an instance ofPieChartModelis created. Key properties are configured to disable the description, legend, hole, and user touch interactions, creating a clean, focused visual. -
Data Population: The
setDatamethod populates the pie chart with data. It createsPieEntryobjects for each trivia category, adds them to aPieDataSet, and assigns custom colors to each slice. -
Spin Animation Logic: The
startGunmethod handles the spinning animation. It uses theanimatormodule to create a rotation animation with a defined duration and easing curve. This creates a realistic "spin-down" effect. -
Result Calculation: Once the animation is complete (
onfinish), the final rotation angle is used to determine which pie slice the pointer is aligned with. ThecurrentIndexis calculated to correspond to the selected category from thepartiesarray. -
UI Interaction: A button is placed at the center of the pie chart. Tapping this button triggers the
startGunmethod, initiating the spin. The selected topic's name is then displayed, providing instant feedback to the user.
Code Snippet / Configuration
import {
JArrayList,
MPPointF,
PieChart,
PieChartModel,
PieData,
PieDataSet,
PieEntry
} from '@ohos/mpchart';
import animator, { AnimatorOptions, AnimatorResult } from '@ohos.animator';
@Entry
@Component
export default struct Index {
model: PieChartModel = new PieChartModel();
private animatorResult: AnimatorResult | null = null
@State chooseText: string = 'Spin';
@State onePartAngle: number = 0;
@State count: number = 6;
@State currentIndex: number = 0;
parties: string[] = ['History', 'Science', 'Art', 'Sports', 'Cinema', 'Music'];
@State isSpinning:boolean = true;
@State topic:string = ''
@State selectedTopic:string = ''
aboutToAppear(): void {
this.init();
}
build() {
NavDestination(){
Column() {
Stack(){
Stack() {
PieChart({ model: this.model })
.width('99%')
.aspectRatio(1)
Text('▼')
.fontSize(26)
.fontWeight(FontWeight.Bolder)
.alignSelf(ItemAlign.Start)
.height('100%')
.textAlign(TextAlign.Start)
.align(Alignment.Top)
.margin({ top: -15 })
Button(){
Text(this.chooseText).fontWeight(FontWeight.Bold)
}
.onClick(() => {
this.startGun();
})
.alignSelf(ItemAlign.Center)
.fontColor(Color.White)
.fontWeight(FontWeight.Bold)
.width(75)
.height(75)
.borderRadius(200)
.backgroundColor('#2071ff')
.align(Alignment.Center)
.shadow({
offsetX: 1,
offsetY: 1,
color: Color.Black,
radius: 10
})
}.height('100%')
}.align(Alignment.Bottom)
}
.justifyContent(FlexAlign.Center)
.width('100%')
.height('100%')
.backgroundColor(Color.Black)
}
.hideTitleBar(true);
}
init() {
this.model.getDescription()?.setEnabled(false);
this.model.setDrawHoleEnabled(false);
this.model.getLegend()?.setEnabled(false);
this.model.disableScroll();
this.model.setRotationEnabled(true);
this.model.setHighlightPerTapEnabled(true);
this.model.setEntryLabelTextSize(14)
this.model.setEntryLabelColor(Color.White)
this.model.setTouchEnabled(false);
this.setData(5);
}
private async setData(range: number): Promise<void> {
let entries: JArrayList<PieEntry> = new JArrayList<PieEntry>();
for (let i = 0; i < this.count; i++) {
entries.add(new PieEntry(range,
this.parties[i % this.parties.length]));
}
let dataSet: PieDataSet = new PieDataSet(entries, "Election Results");
dataSet.setSliceSpace(1);
dataSet.setIconsOffset(new MPPointF(0, 40));
dataSet.setSelectionShift(0);
dataSet.setValueTextColor(Color.White);
dataSet.setDrawValues(false);
const customColors: number[] = [
0x9066bd,
0xB572CA,
0xee66bb,
0xf4777c,
0xF7AC7C,
0xFAC166
];
let colors: JArrayList<number> = new JArrayList();
for (let color of customColors) {
colors.add(color);
}
dataSet.setColorsByList(colors);
let data: PieData = new PieData(dataSet);
this.onePartAngle = 360 / this.count;
this.model.setRotationAngle(-90 - this.onePartAngle / 2);
this.model.setData(data);
}
startGun() {
this.isSpinning = true
let currentAngle = this.model.getRotationAngle();
let randomRotation = Math.floor(Math.random() * 360);
let end = 7200 + currentAngle + randomRotation;
let options: AnimatorOptions = {
duration: 11000,
easing: "ease",
delay: 0,
fill: "forwards",
direction: "normal",
begin: currentAngle,
end: end,
iterations: 1
};
this.animatorResult = animator.create(options);
this.animatorResult.onframe = (value) => {
this.model.setRotationAngle(value);
this.model.invalidate();
};
this.animatorResult.onfinish = () => {
let finalRotation = end % 360;
let adjustedAngle = finalRotation + 90;
if (adjustedAngle > 360) {
adjustedAngle -= 360;
}
let index = Math.floor(adjustedAngle / this.onePartAngle);
this.currentIndex = (this.count - 1) - index;
this.chooseText = this.parties[this.currentIndex];
this.isSpinning = false
};
this.animatorResult.play();
}
}
Test Results
The application was successfully tested on a standard HarmonyOS wearable emulator and a real device. The pie chart renders correctly and fills the screen. Tapping the central button triggers a smooth, decelerating spin animation. The selected topic is accurately identified and displayed after the spin ends, confirming the animation and calculation logic work as expected.
Limitations or Considerations
Not applicable to apps targeting API Level < 9.

Top comments (0)