import QtQuick as Quick import QtQuick.Controls import Fluent ProgressBar{ property int duration: 2000 property real strokeWidth: 6 property bool progressVisible: false property Quick.color color: FluTheme.primaryColor property Quick.color backgroundColor : FluTheme.dark ? Qt.rgba(99/255,99/255,99/255,1) : Qt.rgba(214/255,214/255,214/255,1) id:control indeterminate : true clip: true background: Quick.Rectangle { implicitWidth: 56 implicitHeight: 56 radius: control.width/2 color:"transparent" border.color: control.backgroundColor border.width: control.strokeWidth } onIndeterminateChanged:{ canvas.requestPaint() } Quick.QtObject{ id:d property real _radius: control.width/2-control.strokeWidth/2 property real _progress: control.indeterminate ? 0.0 : control.visualPosition on_ProgressChanged: { canvas.requestPaint() } } Quick.Connections{ target: FluTheme function onDarkChanged(){ canvas.requestPaint() } } contentItem: Quick.Item { id:layout_item Quick.Canvas { id:canvas anchors.fill: parent antialiasing: true renderTarget: Canvas.Image property real startAngle: 0 property real sweepAngle: 0 Quick.SequentialAnimation on startAngle { loops: Animation.Infinite running: control.visible && control.indeterminate Quick.PropertyAnimation { from: 0; to: 450; duration: control.duration/2 } Quick.PropertyAnimation { from: 450; to: 1080; duration: control.duration/2 } } Quick.SequentialAnimation on sweepAngle { loops: Animation.Infinite running: control.visible && control.indeterminate Quick.PropertyAnimation { from: 0; to: 180; duration: control.duration/2 } Quick.PropertyAnimation { from: 180; to: 0; duration: control.duration/2 } } onStartAngleChanged: { requestPaint() } onPaint: { var ctx = canvas.getContext("2d") ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.save() ctx.lineWidth = control.strokeWidth ctx.strokeStyle = control.color ctx.lineCap = "round" ctx.beginPath() if(control.indeterminate){ ctx.arc(width/2, height/2, d._radius , Math.PI * (startAngle - 90) / 180, Math.PI * (startAngle - 90 + sweepAngle) / 180) }else{ ctx.arc(width/2, height/2, d._radius , -0.5 * Math.PI , -0.5 * Math.PI + d._progress * 2 * Math.PI) } ctx.stroke() ctx.closePath() ctx.restore() } } } Text{ text:(control.visualPosition * 100).toFixed(0) + "%" visible: { if(control.indeterminate){ return false } return control.progressVisible } anchors.centerIn: parent } }