您当前的位置: 首页 > 

龚建波

暂无认证

  • 3浏览

    0关注

    312博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

QML Canvas 绘制进度条(环形和波浪水球)

龚建波 发布时间:2022-02-10 22:54:58 ,浏览量:3

效果展示:

代码链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qml/TestQml_20220210_ProgressBar

环形进度条代码:

import QtQuick 2.12
import QtQuick.Controls 2.12

//canvas绘制环形进度条
//龚建波 2022-02-10
Item {
    id: control

    implicitWidth: 160
    implicitHeight: 160

    property real from: 0 //最小值
    property real to: 100 //最大值
    property real value: 0 //当前值
    property real percent: (value-from)/(to-from) //百分比[0,1]
    //
    property int canvasMargin: 3
    property int canvasWidth: width < height ? width : height
    property int canvasRadius: canvasWidth / 2 - canvasMargin
    property int lineWidth: 16
    property int lineBorder: 6
    property color bgColor: "#0486FF"
    property color valueColor: "#0486FF"
    //
    property real _valueAngle: Math.PI/2+Math.PI*2*percent
    on_ValueAngleChanged: canvas.requestPaint()
    //
    property real speed: 0.1
    property real offset: 0

    Canvas {
        id: canvas
        width: canvasWidth
        height: canvasWidth
        onPaint: {
            var ctx = getContext("2d");
            ctx.clearRect(0, 0, canvasWidth, canvasWidth);
            ctx.lineCap = "round";

            drawBg(ctx);
            drawValue(ctx);
        }

        //context.arc(x,y,r,sAngle,eAngle,counterclockwise);
        //x:圆的中心的x坐标。
        //y:圆的中心的y坐标。
        //r:圆的半径。
        //sAngle:起始角,以弧度计。(弧的圆形的三点钟位置是0度)。
        //eAngle:结束角,以弧度计。
        //counterclockwise:可选参数。False=顺时针,true=逆时针。
        function drawBg(ctx)
        {
            var color_offset = offset>Math.PI?(1-(offset-Math.PI)/Math.PI):(offset/Math.PI);

            ctx.beginPath();
            ctx.arc(canvasWidth/2, canvasWidth/2, canvasRadius-lineWidth/2-lineBorder, 0, 2*Math.PI);
            ctx.lineWidth = lineWidth+lineBorder*2;
            ctx.strokeStyle = Qt.lighter(bgColor, 1.7+0.2*color_offset);
            ctx.stroke();

            ctx.beginPath();
            ctx.arc(canvasWidth/2, canvasWidth/2, canvasRadius-lineWidth/2-lineBorder, 0, 2*Math.PI);
            ctx.lineWidth = lineWidth;
            ctx.strokeStyle = Qt.lighter(bgColor, 1.6+0.2*color_offset);
            ctx.stroke();
        }

        function drawValue(ctx)
        {
            //ctx.save();
            //带阴影效果时cpu占用明显增高
            //ctx.shadowColor= valueColor;
            //ctx.shadowBlur= lineWidth/4;
            ctx.beginPath();
            ctx.arc(canvasWidth/2, canvasWidth/2, canvasRadius-lineWidth/2-lineBorder, Math.PI/2, _valueAngle, false);
            ctx.lineWidth = lineWidth;
            ctx.strokeStyle = valueColor;
            ctx.stroke();
            //ctx.restore();
        }

        Text {
            id: txt
            anchors.centerIn: parent
            font.family: "Microsoft YaHei"
            font.pixelSize: (canvasWidth-lineWidth)/6;
            font.bold: true
            color: valueColor
            text: qsTr("%1 %").arg(control.percent.toFixed(2)*100);
        }
    }

    //用定时器刷新
    Timer {
        running: visible
        repeat: true
        interval: 35
        onTriggered:{
            //波浪移动
            offset += speed;
            offset %= Math.PI*2;
            canvas.requestPaint();
        }
    }
    /*NumberAnimation {
        target: control
        running: visible
        loops: -1
        property: "offset"
        from: 0
        duration: 2000
        to: Math.PI*2
    }
    onOffsetChanged: canvas.requestPaint();*/
}

波浪进度球代码:

import QtQuick 2.12
import QtQml 2.12
import QtQuick.Controls 2.12

//canvas绘制波浪进度球
//龚建波 2022-02-10
Item {
    id: control

    implicitHeight: 160
    implicitWidth: 160

    property real from: 0 //最小值
    property real to: 100 //最大值
    property real value: 0 //当前值
    property real percent: (value-from)/(to-from) //百分比[0,1]
    //
    property int canvasMargin: 3
    property int canvasWidth: width < height ? width : height
    //
    property int fontPx: 34
    property string fontFamily: "Arial"
    property color waveColor: "#0486FF"
    property int waveBorder: 6
    property int waveRadius: canvasWidth / 2 - canvasMargin - waveBorder
    //
    property real waveWidth: 0.05   //波浪宽度,数越小越宽
    property real waveHeight: 5     //波浪高度,数越大越高
    property real speed: 0.1        //波浪速度,数越大速度越快
    property real offset: 0         //波浪x偏移量,用于动画

    Canvas {
        id: canvas
        width: canvasWidth
        height: canvasWidth
        onPaint: {
            var ctx = getContext("2d");
            ctx.clearRect(0, 0, canvasWidth, canvasWidth);
            ctx.lineCap = "round";

            ctx.save();
            ctx.beginPath();
            ctx.arc(canvasWidth/2, canvasWidth/2, waveRadius+waveBorder-canvasMargin, 0, 2*Math.PI);
            ctx.lineWidth = waveBorder;
            var color_offset = offset>Math.PI?(1-(offset-Math.PI)/Math.PI):(offset/Math.PI);
            ctx.strokeStyle = Qt.lighter(waveColor, 1.5+0.3*color_offset);
            ctx.stroke();

            var progress_text = qsTr("%1 %").arg(parseInt(percent*100));
            ctx.font = fontPx + "px '" + fontFamily + "'";
            ctx.textAlign = "center";
            ctx.fillStyle = waveColor;
            //canvas字体高度和居中还有点问题
            ctx.fillText(progress_text, canvasWidth/2, canvasWidth/2+fontPx/2-5);

            ctx.save();
            ctx.beginPath();
            ctx.lineWidth = 0;
            ctx.arc(canvasWidth/2, canvasWidth/2, waveRadius, 0, 2*Math.PI);
            ctx.clip();
            drawWave(ctx, waveColor, 0, 0, false);
            ctx.clip();
            ctx.font = fontPx + "px '" + fontFamily + "'";
            ctx.textAlign = "center";
            ctx.fillStyle = "white";
            ctx.fillText(progress_text, canvasWidth/2, canvasWidth/2+fontPx/2-5);
            ctx.restore();
        }

        //画笔,颜色,x偏移,y偏移,角度值取反
        function drawWave(ctx, w_color, x_offset, y_offset, reverse)
        {
            ctx.beginPath();
            var x_base = canvasWidth/2-waveRadius;
            var y_base = canvasWidth/2+waveRadius-waveRadius*2*percent;
            //正弦波浪,横坐标步进为5px,右侧多加5是为了填补不足步进的部分
            for(var x_value = 0; x_value             
关注
打赏
1655829268
查看更多评论
0.0838s