素材巴巴 > 程序开发 >

14. 利用Canvas自制时钟组件

程序开发 2023-09-06 06:59:56

1. 说明

在自定义时钟组件时,使用到的基本控件主要是Canvas,在绘制相关元素时有两种方式:一种时在同一个canvas中绘制所有的部件元素,这样需要不断的对画笔和画布的属性进行保存和恢复,容易混乱;另一种就是创建多个canvas组件,每一部分的元素绘制都在各自的画布进行绘制,逻辑比较清晰,但是canvas组件会相对较多,本文使用的是第二种方式。
效果展示:
在这里插入图片描述

2. 整体代码

import QtQuick 2.15
 import QtQuick.Controls 2.15Item{id:rootimplicitWidth: 400implicitHeight: implicitWidth// 尺寸属性property real outerCircleRadius:root.width / 2.05property real innerCircleRadius:root.width / 2.05// 颜色属性property color bgColor:"white"property color outerColor:"black"property color innerColor:"black"property color innerRootColor:"lightSlateGray"property color innerLineColorL:"#484D58"property color innerLineColorS:"#63677A"property color textColor:"black"property color hourLineColor:"#484D58"property color minuteLineColor:"#484D58"property color secondLineColor:"red"property color timeTxtColor:"black"// 时间属性property var hoursproperty var minutesproperty var secondsproperty var currentTimeproperty alias hoursAngle:hourLine.angleproperty alias minutesAngle:minuteLine.angleproperty alias secondsAngle:secondLine.angle// 组件加载完成后先初始化当前时间Component.onCompleted: {calculateAngle()}// 时间计算function calculateAngle(){var date = new Date()hours = date.getHours()// 模除得到12小时制的小时数hours = hours % 12minutes = date.getMinutes()seconds = date.getUTCSeconds()currentTime = hours + ":" + minutes + ":" + secondshoursAngle = Math.PI*2/12*hours+Math.PI*2*minutes/12/60-Math.PIminutesAngle = Math.PI*2*minutes/60 + Math.PI*2*seconds/60/60 -Math.PIsecondsAngle = Math.PI*2*seconds/60-Math.PI}// 绘制背景Canvas{id:bgCirclewidth: root.widthheight: root.heightanchors.centerIn: parentonPaint: {// 绘制背景var ctx = getContext("2d")  ctx.save()ctx.lineWidth = root.width/50   ctx.fillStyle = bgColorctx.beginPath()ctx.arc(root.width/2,root.height/2,outerCircleRadius,0,Math.PI * (12/6))ctx.fill()ctx.restore()}}// 绘制圆环轮廓Canvas{id:outerCirclewidth: root.widthheight: root.heightanchors.centerIn: parentonPaint: {var ctx = getContext("2d")  //创建画师//为画师创建画笔并设置画笔属性ctx.lineWidth = root.width/50   //设置画笔粗细ctx.strokeStyle = outerColor    //设置画笔颜色ctx.beginPath()     //每次绘制调用此函数,重新设置一个路径// 按照钟表刻度进行划分,一圈是Math.PI * 2,分成12个刻度,每个刻度占用 1/6// canvas绘制圆弧,是按照顺时针绘制,起点默认在三点钟方向ctx.arc(root.width/2,root.height/2,outerCircleRadius,0,Math.PI * (12/6))ctx.stroke()    //根据strokeStyle对边框进行描绘}}// 绘制圆环内衬Canvas{id:innerCirclewidth: root.widthheight: root.heightanchors.centerIn: parentproperty real endAngle:Math.PI * (12/6)onPaint: {var ctx = getContext("2d")  ctx.save()ctx.lineWidth = root.width/50   ctx.strokeStyle = innerColor     ctx.beginPath()     ctx.arc(root.width/2,root.height/2,innerCircleRadius,0,endAngle)ctx.stroke()    ctx.restore()// 绘制指针根部圆圈ctx.save()ctx.lineWidth = root.width/50   ctx.fillStyle = innerRootColorctx.beginPath()ctx.arc(root.width/2,root.height/2,innerCircleRadius/16,0,endAngle)ctx.fill()ctx.restore()}}// 绘制刻度线Canvas{id:innerLinewidth: root.widthheight: root.heightanchors.centerIn: parentproperty real lineNums:60onPaint: {var ctx = getContext("2d")  for (var i = 0; i <= lineNums; ++i){ctx.beginPath();var angle = 2 * Math.PI / 60 * i;var dx = Math.cos(angle)*(outerCircleRadius-15);var dy = Math.sin(angle)*(outerCircleRadius-15);var dx2 = Math.cos(angle)*(outerCircleRadius-7);var dy2 = Math.sin(angle)*(outerCircleRadius-7);if (i % 5 === 0){ctx.lineWidth = root.width/100ctx.strokeStyle = innerLineColorL}else{ctx.lineWidth = root.width/200ctx.strokeStyle = innerLineColorS}ctx.moveTo(root.width/2+dx,root.height/2+dy);ctx.lineTo(root.width/2+dx2,root.height/2+dy2);ctx.stroke();}}}// 绘制数字Canvas{id:drawTextwidth: root.widthheight: root.heightanchors.centerIn: parentproperty var numbers : [1,2,3,4,5,6,7,8,9,10,11,12]onPaint: {var ctx = getContext("2d")  ctx.font = "18px Arial";ctx.textAlign = "center";ctx.textBaseline = "middle";for(var i = 0; i < 12; ++i){ctx.fillStyle = textColorvar angle = 2 * Math.PI / 12 * numbers[i] - 3.14 / 2;var dx = Math.cos(angle)*(outerCircleRadius-30);var dy = Math.sin(angle)*(outerCircleRadius-30);ctx.fillText(numbers[i],root.width/2 + dx,root.height / 2 + dy);ctx.fill()}}}// 绘制时针线Canvas{id:hourLinewidth: root.widthheight: root.heightanchors.centerIn: parentproperty real angleonPaint: {var ctx = getContext("2d")  // 先清空画布上之前的内容ctx.clearRect(0,0,width,height)ctx.save()ctx.beginPath()ctx.lineWidth = root.width/100ctx.strokeStyle=hourLineColor// 平移坐标点(注意:坐标系原点先平移,再旋转)ctx.translate(root.width/2,root.height/2)// 旋转坐标系ctx.rotate(angle)// 坐标原点变化之后再进行实际的绘图ctx.moveTo(0,-20);ctx.lineTo(0,outerCircleRadius / 2 - 15);ctx.stroke()ctx.restore()}}// 绘制分针线Canvas{id:minuteLinewidth: root.widthheight: root.heightanchors.centerIn: parentproperty real angleonPaint: {var ctx = getContext("2d")  ctx.clearRect(0,0,width,height)ctx.save()ctx.beginPath()ctx.lineWidth = root.width/100ctx.strokeStyle=minuteLineColor// 平移坐标点(注意:坐标系原点先平移,再旋转)ctx.translate(root.width/2,root.height/2)// 旋转坐标系ctx.rotate(angle)// 坐标原点变化之后再进行实际的绘图ctx.moveTo(0,-25);ctx.lineTo(0,outerCircleRadius / 2 - 5);ctx.stroke()ctx.restore()}}// 绘制秒针线Canvas{id:secondLinewidth: root.widthheight: root.heightanchors.centerIn: parentproperty real angleonPaint: {var ctx = getContext("2d")  ctx.clearRect(0,0,width,height)ctx.save()ctx.beginPath()ctx.lineWidth = root.width/100ctx.strokeStyle=secondLineColor// 平移坐标点(注意:坐标系原点先平移,再旋转)ctx.translate(root.width/2,root.height/2)// 旋转坐标系ctx.rotate(angle)// 坐标原点变化之后再进行实际的绘图ctx.moveTo(0,-30);ctx.lineTo(0,outerCircleRadius / 1.5);ctx.stroke()ctx.restore()}}// 当前时间显示Text{id:timeTxty:root.height * 0.75anchors.horizontalCenter: root.horizontalCentertext: currentTimefont.pixelSize: root.width/12color: timeTxtColor}// 使用定时器(每秒钟进行计算)Timer{id:angleCalinterval: 1000repeat: truerunning: trueonTriggered: {calculateAngle()hourLine.requestPaint()minuteLine.requestPaint()secondLine.requestPaint()}}
 }

标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。