15. Canvas制作汽车油耗仪表盘

1. 说明

本篇文章在14. 利用Canvas组件制作时钟的基础上进行一些更改,想查看全面的代码可以点击链接查看即可。

效果展示:

2. 整体代码

cpp 复制代码
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"
    }
}
相关推荐
bbqz0077 天前
Qml Console
c++·qt·qml
prog_61039 天前
【笔记】当个自由的书籍收集者从canvas得到png转pdf
pdf·canvas·js·png
wuhen_n15 天前
Canvas特效实例:黑客帝国-字母矩阵(字母雨)
前端·javascript·矩阵·html5·canvas·canva可画
机器视觉知识推荐、就业指导21 天前
开源QML控件:进度条滑动控件(含源码下载链接)
前端·qt·开源·qml
_lucas23 天前
用canvas做个场景编辑器
前端·javascript·canvas
byxdaz24 天前
QML TabBar 和 TabButton 组件
qml
red润24 天前
浏览器离屏渲染 vs. Electron离屏渲染——核心区别与应用场景
前端·electron·canvas
八了个戒24 天前
「数据可视化 D3系列」入门第十章:饼图绘制详解与实现
前端·javascript·信息可视化·数据可视化·canvas·d3
八了个戒1 个月前
「数据可视化 D3系列」入门第六章:比例尺的使用
前端·javascript·信息可视化·数据可视化·canvas