[Huawei Developers] ask011:
Article Introduction

In this article, I have explained to develop a custom watch faces for Huawei Wearable device using Huawei DevEco Studio and using HTML Canvas APIs in Harmony OS. The Canvas API provides a means for drawing graphics with JavaScript and the HTML element.

Huawei Wearable Device

Requirements

1) DevEco IDE

2) Wearable watch (Can use cloud emulator also)

New Project (Wearable)

After installation of DevEco Studio, make new project.

Select Wearable in Device and select Empty Feature Ability(JS) in Template.

After the project is created, its directory as shown in image.

hml files describe the page layout.

css files describe the page style.

js files process the interactions between pages and users.

The app.js file manages global JavaScript logics and application lifecycle.

The pages directory stores all component pages.

The java directory stores java files related to the projects.

Integration process

Design the UI

Step 1: Create the canvas in the hml file.

As the first step, we can create a canvas that will be holding the watch face which will filled by the watch hands later.

Create and add the canvas HTML element. In javascript file take the canvas reference using this.$refs.canvasref. Save the canvas context for further painting operation.

index.hml

<div class="container" onswipe="touchMove">
<canvas ref="canvasref" style="width: 430px; height: 430px; background-color:#00FFFFFF"></canvas>
</div>

index.css

.container {
flex-direction: column;
justify-content: center;
align-items: center;
}

Add the below code in index.js

const canvas = this.$refs.canvasref;
var ctx = canvas.getContext("2d");

Step 2: Paint outside rim arc and centre arc for watch face.

Create arc using canvas arc APIs. The arc() creates an arc/curve (used to create circles or part of circles). Use the stroke() and fill() method to draw the arc on the canvas. Take the radius roughly half of the canvas height, in this case it is 200. Fill the arc with desired colour using fillStyle(). Draw another arc circle in centre to hold the watch hands.

Add the below code in index.js

var radius = 215
ctx.beginPath();
ctx.translate(radius, radius);
radius = radius * 0.90
ctx.arc(0, 0, radius, 0 , 2 * Math.PI);
ctx.fillStyle = "#61c7e6";
ctx.fill();

ctx.beginPath();
ctx.arc(0, 0, radius * 0.05, 0, 2 * Math.PI);
ctx.fillStyle = '#292d2e';
ctx.fill();
},

Step 3: Paint the numbers in the watch face.

We don’t need to draw the watch face and number every second or time update, so we have flag to check and make sure that.

Add the below code in index.js

paintClock(ctx, radius) {
if (this.intialDraw == false) {
this.paintNumber(ctx, radius)
}
this.intialDraw = true
this.paintTime(ctx, radius)
},

Here we will display numbers 3, 6, 9, 12 and other positions will be just line markers. We use rotate() to move to the position of the numbers and paint the text at the position. The position navigation is helped by finding the radian value from the number value itself. Set the font for the text.

Add the below code in index.js

var ang;
var num;
ctx.font = radius * 0.30 + "px arial";
ctx.textBaseline = "middle";
ctx.textAlign = "center";

For painting the line markers use the lineTo(). For painting the numbers use fillText()

Add the below code in index.js

for (num = 1; num < 13; num++) {
var reminder = num % 3
if (reminder != 0) {
ang = num * Math.PI / 6;
ctx.beginPath();
ctx.lineWidth = 3;
ctx.lineCap = "square";
ctx.moveTo(178,0);
ctx.rotate(ang);
ctx.lineTo(300, 0);
ctx.strokeStyle = '#292d2e';
ctx.stroke();
ctx.rotate(-ang);
} else {
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius * 0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius * 0.85);
ctx.rotate(-ang);
}
}

Step 4: Paint watch hands for hour, minutes and seconds

To draw a hands we will use the line graphics. Date object of JavaScript can be used for get current time information. Calculate hour, minutes and seconds value as shown in the code.

Add the below code in index.js

var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds(); hour = hour % 12;
hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60)); minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60));

Draw a watch hand for hour using the hour value calculate above. Set the width, lineCap, strokeStyle and call stroke() to draw the line.Move to (0, 0) and rotate to the hour position and draw the line from (0, 0) to (0, –length).

Add the below code in index.js

paintHour(ctx, hour, length, width) {
ctx.beginPath();
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.moveTo(0,0);
ctx.rotate(hour);
ctx.lineTo(0, -length);
ctx.strokeStyle = '#292d2e';
ctx.stroke();
ctx.rotate(-hour);
},

Similarly draw hand for minute value too.

Add the below code in index.js

paintMinutes(ctx, minute, second, length, width) {
ctx.beginPath();
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.moveTo(0,0);
ctx.rotate(minute);
ctx.lineTo(0, -length);
ctx.strokeStyle = '#292d2e';
ctx.stroke();
ctx.rotate(-minute);
this.lastMinutes = minute
},

Use lastMinutes to save the previous minute value globally, so for next minute tick we have to clear this minute hand.

Add the below code in index.js

if (this.lastMinutes > -1 && this.lastMinutes != pos) {
//clear old minute hand
}

Similarly draw hand for second value too. Clear previous second hand also as we did for minute hand.

Add the below code in index.js

ctx.beginPath();
ctx.lineWidth = width;
ctx.lineCap = "square";
ctx.moveTo(0,0);
var pos = (second * Math.PI / 30);
ctx.rotate(pos);
ctx.lineTo(0, -length);
ctx.strokeStyle = '#ff0000';
ctx.stroke();
ctx.rotate(-pos);

Step 5: Display date and day of the week.

Using date object save the day of the week and date globally.

Add the below code in index.js

var now = new Date();var days = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']
var day = days[now.getDay()]
this.dayString = day + " " + date

Use the Canvas text API to paint text. Use rotate and translate to navigate to position and paint text.

Add the below code in index.js

ctx.font = radius * 0.10 + "px arial";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.rotate(Math.PI / 2);
ctx.translate(0, -radius * 0.85);
ctx.rotate(-Math.PI / 2);
ctx.fillstyle = "#9c949a"
ctx.fillText(this.dayString, -80, 0);
ctx.rotate(Math.PI / 2);
ctx.translate(0, 215 * 0.85);
ctx.rotate(-Math.PI / 2);

Step 6: Start the clock tick

Using JavaScript timeout APIs and 1000 milliseconds interval update time tick.

Add the below code in index.js

while (true) {
setTimeout(this.paintClock(ctx, radius), 1000)
}

Tips and Tricks

You can use Wearable emulator for development. We can more text and more content in watch face. We can add blood pressure and heart rate fields in watch face using the wearable sensor APIs. Even we can add steps counts in the watch face.

Conclusion

In this article, we have learnt how to create simple custom face using Harmony OS UI components. We have explored HTML Canvas APIs for designing trendy watch faces.

References

Document

developer.harmonyos.com