鸿蒙HarmonyOS开发实例:【简单时钟】

简单时钟

介绍

本示例通过使用[@ohos.display]接口以及Canvas组件来实现一个简单的时钟应用。

效果预览

主页
main

使用说明

1.界面通过setInterval实现周期性实时刷新时间,使用Canvas绘制时钟,指针旋转角度通过计算得出。

例如:"2 * Math.PI / 60 * second"是秒针旋转的角度。

鸿蒙开发应用知识已更新gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md参考前往。

搜狗高速浏览器截图20240326151547.png

具体实现

鸿蒙学习文档前往mau123789是v添加即可
  • 本示例展示简单时钟的方法主要封装在Index中,源码参考:[Index.ets] 。
/** Copyright (c) 2022 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import display from '@ohos.display'import Logger from '../model/Logger'const HOURS: Array<string> = ['3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '1', '2']const HEIGHT_ADD: number = 150 // 表盘下面需要绘制时间,canvas高度是宽度加150const TAG: string = 'Index'@Entry@Componentstruct Clock {private settings: RenderingContextSettings = new RenderingContextSettings(true)private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)@State canvasWidth: number = 300 // 300是表盘默认大小private radius: number = 150 // 默认表盘半径private intervalId: number = 0updateTime = () => {this.context.clearRect(0, 0, this.canvasWidth, this.canvasWidth + HEIGHT_ADD)let nowTime = new Date()let hour = nowTime.getHours()let minute = nowTime.getMinutes()let second = nowTime.getSeconds()let time = `${this.fillTime(hour)}:${this.fillTime(minute)}:${this.fillTime(second)}`this.drawBackGround()this.drawHour(hour, minute)this.drawMinute(minute)this.drawSecond(second)this.drawDot()this.drawTime(time)this.context.translate(-this.radius, -this.radius)}fillTime(time: number) {return time < 10 ? `0${time}` : `${time}`}aboutToAppear() {this.getSize()}// 获取设备宽高计算表盘大小async getSize() {let mDisplay = await display.getDefaultDisplay()Logger.info(TAG, `getDefaultDisplay mDisplay = ${JSON.stringify(mDisplay)}`)this.canvasWidth = px2vp(mDisplay.width > mDisplay.height ? mDisplay.height * 0.6 : mDisplay.width * 0.6)this.radius = this.canvasWidth / 2}drawBackGround() {// 绘制背景let grad = this.context.createRadialGradient(this.radius, this.radius, this.radius - 32, this.radius,this.radius, this.radius)grad.addColorStop(0.0, 'white')grad.addColorStop(0.9, '#eee')grad.addColorStop(1.0, 'white')this.context.fillStyle = gradthis.context.fillRect(0, 0, this.canvasWidth, this.canvasWidth)// 绘制外圈圆this.context.translate(this.radius, this.radius)this.context.lineWidth = 6this.context.beginPath()this.context.strokeStyle = '#fff'this.context.arc(0, 0, this.radius - 5, 0, 2 * Math.PI, false)this.context.stroke()// 绘制时间文字this.context.font = '30px'this.context.textAlign = "center"this.context.textBaseline = "middle"this.context.fillStyle = '#000'this.context.save()HOURS.forEach((num, index) => {let rad = 2 * Math.PI / 12 * indexlet x = Math.cos(rad) * (this.radius - 38)let y = Math.sin(rad) * (this.radius - 38)this.context.fillText(num, x, y)})this.context.restore()// 绘制刻度for (let i = 0; i < 60; i++) {let rad = 2 * Math.PI / 60 * ilet x = Math.cos(rad) * (this.radius - 12)let y = Math.sin(rad) * (this.radius - 12)this.context.beginPath()this.context.moveTo(x, y)if (i % 5 == 0) {let x1 = Math.cos(rad) * (this.radius - 20)let y1 = Math.sin(rad) * (this.radius - 20)this.context.strokeStyle = '#000'this.context.lineWidth = 2this.context.lineTo(x1, y1)} else {let x1 = Math.cos(rad) * (this.radius - 18)let y1 = Math.sin(rad) * (this.radius - 18)this.context.strokeStyle = '#ccc'this.context.lineWidth = 1this.context.lineTo(x1, y1)}this.context.stroke()}this.context.restore()}// 绘制时针drawHour(hour: number, minute: number) {this.context.save()this.context.beginPath()this.context.lineWidth = 8this.context.lineCap = 'round'let rad = 2 * Math.PI / 12 * hourlet mrad = 2 * Math.PI / 12 / 60 * minutethis.context.rotate(rad + mrad)this.context.moveTo(0, 10)this.context.strokeStyle = '#000'this.context.lineTo(0, -this.radius / 2)this.context.stroke()this.context.restore()}// 绘制分针drawMinute(minute: number) {this.context.save()this.context.beginPath()this.context.lineWidth = 5this.context.lineCap = 'round'let rad = 2 * Math.PI / 60 * minutethis.context.rotate(rad)this.context.moveTo(0, 10)this.context.strokeStyle = '#000'this.context.lineTo(0, -this.radius + 40)this.context.stroke()this.context.restore()}// 绘制秒针drawSecond(second: number) {this.context.save()this.context.beginPath()this.context.lineWidth = 2this.context.lineCap = 'round'let rad = 2 * Math.PI / 60 * secondthis.context.rotate(rad)this.context.moveTo(0, 10)this.context.strokeStyle = '#05f'this.context.lineTo(0, -this.radius + 21)this.context.stroke()this.context.restore()}// 绘制中心点drawDot() {this.context.save()this.context.beginPath()this.context.fillStyle = '#05f'this.context.arc(0, 0, 4, 0, 2 * Math.PI, false)this.context.fill()this.context.restore()}// 绘制表盘下面时间文本drawTime(time: string) {this.context.save()this.context.beginPath()this.context.font = '90px'this.context.textAlign = "center"this.context.textBaseline = "middle"this.context.fillStyle = '#000'this.context.fillText(time, 0, this.radius + 80)this.context.restore()}build() {Stack({ alignContent: Alignment.Center }) {Canvas(this.context).padding({ top: 76 }).width(this.canvasWidth).height(this.canvasWidth + HEIGHT_ADD).onReady(() => {this.updateTime()this.intervalId = setInterval(this.updateTime, 1000)})}.width('100%').height('100%')}onPageHide() {clearInterval(this.intervalId)}aboutToDisappear(){clearInterval(this.intervalId)}}
  • 设置表盘大小:通过Index中的display.getDefaultDisplay()方法来获取设备宽高计算表盘大小;
  • 获取当前时间:调用updateTime函数,执行new Date().getHours()、new Date().getMinutes()、new Date().getSeconds()获取当前时间。
  • 绘制表盘内容:通过[CanvasRenderingContext2D] 来画表盘背景、时针、分针、秒针、圆心以及表盘下方文本;
  • 启动时钟:添加setInterval定时器,每隔1s执行一次updateTime函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/803222.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Microsoft Visio 参与者 [actor] - 人的形状图标

Microsoft Visio 参与者 [actor] - 人的形状图标 1. 更多形状 -> 搜索形状2. 参与者References 1. 更多形状 -> 搜索形状 2. 参与者 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

【简单讲解下如何Java中文乱码浅析及解决方案】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

力扣经典150题(1)

文章目录 6.Z字形变换82.删除排序链表中的重复元素||61.旋转链表100.相同的树 6.Z字形变换 将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时&#xff0c;排列如下&#xff1…

Spring循环依赖

Java开发常见面试题详解&#xff08;LockSupport&#xff0c;AQS&#xff0c;Spring循环依赖&#xff0c;Redis&#xff09;_java 常见面试题详解(locksupport-CSDN博客 循环依赖现象在spring容器中注入依赖的对象&#xff0c;有2种情况 构造器方式注入依赖&#xff08;不可行…

基于遗传优化的SVD水印嵌入提取算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于遗传优化的的SVD水印嵌入提取算法。对比遗传优化前后SVD水印提取性能&#xff0c;并分析不同干扰情况下水印提取效果。 2.测试软件版本以及运行结果展示 MA…

根据mysql的执行顺序来写select

过滤顺序指的是mysql的逻辑执行顺序&#xff0c;个人觉得我们可以按照执行顺序来写select查询语句。 目录 一、执行顺序二、小tips三、案例第一轮查询&#xff1a;统计每个num的出现次数第二轮查询&#xff1a;计算**最多次数**第三轮查询&#xff1a;找到所有出现次数为最多次…

Linux使用宝塔面板安装MySQL结合内网穿透实现公网连接本地数据库

文章目录 推荐前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…

【docker】Docker 简介

Docker 简介 什么是虚拟化、容器化?为什么要虚拟化、容器化&#xff1f;虚拟化实现方式应用程序执行环境分层虚拟化常见类别虚拟机容器JVM 之类的虚拟机 常见虚拟化实现主机虚拟化(虚拟机)实现容器虚拟化实现容器虚拟化实现原理容器虚拟化基础之 NameSpace 什么是虚拟化、容器…

ADC电路项目1——10bit SAR ADC 设计,smic18工艺,有工艺库,有效位数ENOB为9.8

分享一个入门SAR ADC的完整电路项目&#xff0c;适合新手小白学习 10bit 20MHz SAR ADC&#xff08;WX:didadidadidida313&#xff0c;加我备注&#xff1a;CSDN 10 bit SAR ADC&#xff0c;谢绝白嫖哈&#xff09; 概述&#xff1a; 本设计采用 smic18mmrf CMOS 工艺&#xf…

【自然语言】使用词袋模型,TF-IDF模型和Word2Vec模型进行文本向量化

一、任务目标 python代码写将 HarryPorter 电子书作为语料库&#xff0c;分别使用词袋模型&#xff0c;TF-IDF模型和Word2Vec模型进行文本向量化。 1. 首先将数据预处理&#xff0c;Word2Vec 训练时要求考虑每个单词前后的五个词汇&#xff0c;地址为 作为其上下文 &#xf…

OpenHarmony开发-连接开发板调试应用

在 OpenHarmony 开发过程中&#xff0c;连接开发板进行应用调试是一个关键步骤&#xff0c;只有在真实的硬件环境下&#xff0c;我们才能测试出应用更多的潜在问题&#xff0c;以便后续我们进行优化。本文详细介绍了连接开发板调试 OpenHarmony 应用的操作步骤。 首先&#xf…

java访问修饰符的访问范围 and 面向对象特征与区别

文章目录 java访问修饰符的访问范围java面向对象的基本特征面向对象与面向过程的区别其他链接 预定义类&#xff1a;由JDK提供的类 java访问修饰符的访问范围 java面向对象的基本特征 java面向对象的基本特征&#xff1a;封装、继承、多态&#xff08;接口&#xff09; 关键字…

蓝桥杯-油漆面积

代码及其解析:(AC80%&#xff09; 思路:是把平面划成单位边长为1&#xff08;面积也是1&#xff09;的方格。每读入一个矩形&#xff0c;就把它覆盖的方格标注为已覆盖&#xff1b;对所有矩形都这样处理&#xff0c;最后统计被覆盖的方格数量即可。编码极其简单&#xff0c;但…

python笔记整理

解释性语言&#xff08;javascript、python&#xff09; 不需要预编译每次使用都要重新解释代码python中没有内置常量类型&#xff1b;默认只有变量 一般将大写的变量作为常量来用 变量命名规则 字母、数字、下划线、中文等&#xff08;做好别用中文&#xff09;数字不能打头不…

【JavaEE框架技术】spring-1

目录 一、使用maven管理spring项目 1.1搭建开发环境 1.1.1修改settings.xml文件 1.1.2把该文件拷入.m2目录 1.1.3打开ecplise&#xff0c;建立maven项目 1.1.4向pom.xml文件中添加spring的坐标&#xff1a; 1.4.1.1代码含义 1.4.1.2代码说明 1.2创建spring配置文件 二…

1653. 使字符串平衡的最少删除次数

1653. 使字符串平衡的最少删除次数 题目 链接&#xff1a;使字符串平衡的最少删除次数 题解 class Solution {public int minimumDeletions(String s) {int left0,right0;int ns.length();for(int i0;i<n;i){if(s.charAt(i)a){right;}}int resright;for(int i0;i<s.…

基于数据沙箱与LLM用例自愈的UI自动化测试平台

UI自动化测试能够在一定程度上确保产品质量&#xff0c;尤其在降本提效的大背景下&#xff0c;其重要性愈发凸显。理想情况下&#xff0c;UI自动化测试不仅能够能帮我们规避不少线上问题&#xff0c;又能加快产品上线速度。然而现实却往往相去甚远&#xff0c;在多数情况下&…

Mac资源库的东西可以删除吗?mac资源库在哪里打开 cleanmymacx是什么 cleanmymac免费下载

在使用Mac电脑的过程中&#xff0c;用户可能会遇到存储空间不足的问题。一种解决方法是清理不必要的文件&#xff0c;其中资源库&#xff08;Library&#xff09;文件夹是一个常被提及但又让人迷惑的目标。Mac资源库的东西可以删除吗&#xff1f;本文旨在解释Mac资源库的作用、…

公开课学习——JVM虚拟机面试核心点与性能优化点

文章目录 jdk的体系结构图Java语言的跨平台的特性&#xff0c;怎么实现的&#xff1f;jvm内部组成呢&#xff1f;pc的值怎么变得&#xff1f;main方法的栈帧有一点点区别&#xff0c;Math()是new出来的&#xff0c;放在堆区&#xff0c;这个堆区的math和我们栈帧中的局部变量表…

37-代码测试(下):Go语言其他测试类型及IAM测试介绍

。 Go中的两类测试&#xff1a;单元测试和性能测试。 我就来介绍下Go 语言中的其他测试类型&#xff1a;示例测试、TestMain函数、Mock测试、Fake测试等&#xff0c; 示例测试 示例测试以Example开头&#xff0c;没有输入和返回参数&#xff0c;通常保存在example_test.go…