1. 说明
本篇文章在14. 利用Canvas组件制作时钟的基础上进行一些更改,想查看全面的代码可以点击链接查看即可。
效果展示:
2. 整体代码
import QtQuick 2.15
import QtQuick.Controls 2.15
Item{
id:root
implicitWidth: 400
implicitHeight: implicitWidth
// 尺寸属性
property real outerCircleRadius:root.width / 2.05
property real innerCircleRadius:root.width / 2.05
// 颜色属性
property color bgColor:Qt.rgba(0,0,0,0)
property color outerColor:"black"
property color innerColor:"black"
property color innerRootColor:"lightSlateGray"
property color innerLineColorL:Qt.rgba(1,1,1,1)
property color innerLineColorS:Qt.rgba(1,1,1,0.8)
property color textColor:"white"
property color secondLineColor:"red"
// 指针
property var seconds
property alias secondsAngle:secondLine.angle
// 绘制背景
Canvas{
id:bgCircle
width: root.width
height: root.height
anchors.centerIn: parent
onPaint: {
// 绘制背景
var ctx = getContext("2d")
ctx.save()
ctx.lineWidth = root.width/50
ctx.fillStyle = bgColor
ctx.beginPath()
ctx.arc(root.width/2,root.height/2,outerCircleRadius,Math.PI * (5/6),Math.PI * (1/6))
ctx.fill()
ctx.restore()
}
}
// 绘制圆环轮廓
Canvas{
id:outerCircle
width: root.width
height: root.height
anchors.centerIn: parent
onPaint: {
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,Math.PI * (5/6),Math.PI * (1/6))
ctx.stroke() //根据strokeStyle对边框进行描绘
}
}
// 绘制秒针线
Canvas{
id:secondLine
width: root.width
height: root.height
anchors.centerIn: parent
property real angle:Math.PI * (8/6)
onPaint: {
var ctx = getContext("2d")
ctx.clearRect(0,0,width,height)
ctx.save()
ctx.beginPath()
ctx.lineWidth = root.width/100
ctx.strokeStyle=secondLineColor
// 平移坐标点(注意:坐标系原点先平移,再旋转)
ctx.translate(root.width/2,root.height/2)
// 旋转坐标系
ctx.rotate(angle)
// 坐标原点变化之后再进行实际的绘图
ctx.moveTo(0,-10);
ctx.lineTo(0,outerCircleRadius / 1.5);
ctx.stroke()
ctx.restore()
}
}
// 绘制圆环内衬
Canvas{
id:innerCircle
width: root.width
height: root.height
anchors.centerIn: parent
property 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,Math.PI * (5/6),Math.PI * (1/6))
ctx.stroke()
ctx.restore()
// 绘制指针根部圆圈
ctx.save()
ctx.lineWidth = root.width/50
ctx.fillStyle = innerRootColor
ctx.beginPath()
ctx.arc(root.width/2,root.height/2,innerCircleRadius/8,0,endAngle)
ctx.fill()
ctx.restore()
}
}
// 绘制刻度线
Canvas{
id:innerLine
width: root.width
height: root.height
anchors.centerIn: parent
property real lineNums:60
onPaint: {
var ctx = getContext("2d")
for (var i = 0; i <= lineNums; ++i){
if(i > 5 && i < 25){
continue
}
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 && i != 25 && i != 30){
ctx.lineWidth = root.width/100
ctx.strokeStyle = innerLineColorL
}else if(i >= 25 && i <= 30){
ctx.strokeStyle = "red"
}
else{
ctx.lineWidth = root.width/200
ctx.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:drawText
width: root.width
height: root.height
anchors.centerIn: parent
property 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 = textColor
var angle = 2 * Math.PI / 12 * numbers[i] - 3.14 / 2;
var dx = Math.cos(angle)*(outerCircleRadius-35);
var dy = Math.sin(angle)*(outerCircleRadius-35);
switch(i){
case 3:
ctx.fillText(1,root.width/2 + dx,root.height / 2 + dy);
ctx.fill()
break
case 7:
ctx.fillText(0,root.width/2 + dx,root.height / 2 + dy);
ctx.fill()
break
case 11:
ctx.fillText("1/2",root.width/2 + dx,root.height / 2 + dy);
ctx.fill()
break
default:
break
}
}
}
}
Image{
id:iconImg
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 5
scale: 0.25
source: "qrc:/油箱.png"
}
}