在描边画布中获取鼠标位置

get mouse positions in stroke canvas

本文关键字:获取 鼠标 位置 布中      更新时间:2023-09-26

我在qml中用canvas创建了一个自定义弧线进度。我在画布上根据时间的流逝画出了进度。现在我需要查找进度条,就像音乐查找条一样,我们如何在画布中获得笔画中正确的x,y位置。

这是绘制圆弧的代码

import QtQml 2.2
import QtQuick 2.0
// draws two arcs (portion of a circle)
// fills the circle with a lighter secondary color
// when pressed
Canvas {
    id: canvas
    width: canvasWidth
    height: canvasHeight
    antialiasing: true
    property color primaryColor: "grey"
    property color secondaryColor: "white"
    property int canvasWidth: 0
    property int canvasHeight: 0
    property real centerWidth: width / 2
    property real centerHeight: height / 2
    property real radius: Math.min(canvas.width, canvas.height) / 2 - 2
    property real minimumValue: 0
    property real maximumValue: 100
    property real currentValue: 33
    // this is the angle that splits the circle in two arcs
    // first arc is drawn from 0 radians to angle radians
    // second arc is angle radians to 2*PI radians
    property real angle: ((currentValue - minimumValue) / (maximumValue - minimumValue) * 2 * Math.PI)
    // we want both circle to start / end at 12 o'clock
    // without this offset we would start / end at 9 o'clock
    property real angleOffset: (-Math.PI / 2)
    property string text: "Text"
    signal clicked()
    onPrimaryColorChanged: requestPaint()
    onSecondaryColorChanged: requestPaint()
    onMinimumValueChanged: requestPaint()
    onMaximumValueChanged: requestPaint()
    onCurrentValueChanged: requestPaint()
    onPaint: {
        var ctx = getContext("2d");
        ctx.save();
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        // First, thinner arc
        // From angle to 2*PI
        ctx.beginPath();
        ctx.lineWidth = 3;
        ctx.strokeStyle = primaryColor;
        ctx.arc(canvas.centerWidth,
                canvas.centerHeight,
                canvas.radius,
                angleOffset + canvas.angle ,
                (angleOffset-0.1) + 2*Math.PI );
        ctx.stroke();

        // Second, thicker arc
        // From 0 to angle
        ctx.beginPath();
        ctx.lineWidth = 3;
        ctx.strokeStyle = canvas.secondaryColor;
        ctx.arc(canvas.centerWidth,
                canvas.centerHeight,
                canvas.radius,
                canvas.angleOffset,
                canvas.angleOffset + canvas.angle);
        ctx.stroke();
        ctx.restore();

    }

    function xOnArc(radius, radianAngle) {
           var x = canvas.centerWidth + radius * Math.cos(radianAngle);
           return   x-(rect.width/2)
       }
    function yOnArc(radius, radianAngle) {
           var y = canvas.centerHeight + radius * Math.sin(radianAngle);
           return y-rect.height/2
       }

    Rectangle
   {
       id: rect
       color: "white"
       height: 10
       width: 10
       radius: 10/2
       x: xOnArc(canvas.radius,canvas.angleOffset + canvas.angle)
       y: yOnArc(canvas.radius,canvas.angleOffset + canvas.angle)

//       Behavior on x
//       {
//           NumberAnimation {properties: "x"; duration:10}
//       }
//       Behavior on y
//       {
//           NumberAnimation {properties: "y"; duration:10}
//       }
   }
}

下面的代码将根据经过的时间显示进度

import QtQuick 2.0
Item {
    anchors.fill: parent
    property real value: 0
    height: canvasHeights
    width: canvasWidths
    property real total_time: 180
    property real progress_time: 0
    property bool isPlaying: song_timer.running
    signal songCompleted()
    property int canvasWidths: 240
    property int canvasHeights: 240
    property int text_margin_progress: 0
    /**
      A custom control which draws the the progress Arc in canvas
      */
    ProgressArc
    {
        id: circle
        currentValue: value
        anchors.centerIn: parent
        canvasWidth: canvasWidths
        canvasHeight: canvasHeights

        /**
          A timer will be started when the song starts playing this controls the progress of the song
          */
        Timer
        {
            id: song_timer
            running: false
            repeat: true
            interval: 1000
            onTriggered:
            {
                //progress_time will be incremented after each second which will be used to calculate the progress percentage and
                //and time
                progress_time = progress_time + 1;
                value = calculateStepValue(progress_time)
                circle.currentValue = value;
                time.text = fmtMSS(progress_time)
                /**
                  When value reaches 100 then the song is completed and a signal will be send to the corresponsing class
                  */
                if(value >=100)
                {
                    song_timer.stop()
                    songCompleted()
                }
            }
        }

        /**
          Elapsed time will be shown in the text
          */
        Text
        {
            id: time
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.bottom: parent.bottom
            anchors.bottomMargin: text_margin_progress
            color: "white"
            font.pointSize: (canvasHeights == (350*scaleFactor-(20*scaleFactor)))?20:10
        }
    }
    /**
      Convert seconds to human readable format
      eg:- 68 sec eq 1:08 min
      */
    function fmtMSS(time){
        // Hours, minutes and seconds
        var hrs = ~~(time / 3600);
        var mins = ~~((time % 3600) / 60);
        var secs = time % 60;
        // Output like "1:01" or "4:03:59" or "123:03:59"
        var ret = "";
        if (hrs > 0) {
            ret += "" + hrs + ":" + (mins < 10 ? "0" : "");
        }
        ret += "" + mins + ":" + (secs < 10 ? "0" : "");
        ret += "" + secs;
        return ret;
    }

    /**
      Calculate the step value from the progress time
      */
    function calculateStepValue(current_time)
    {
        return (100 - (((total_time - current_time)/total_time)*100))
    }

    /**
      pause playing music
      */
    function pausePlaying()
    {
        song_timer.stop();
    }
    /**
      Resume playing music
      */
    function resumePlaying()
    {
        if(value>100)
            songCompleted()
        else
            song_timer.start()
    }
    /**
      Start playing song. Before playing set the progress time to 0{song from start}
      */
    function startPlaying()
    {
        progress_time = 0
        song_timer.start()
    }
}

要得到您想要的,您需要将MouseArea添加到Item或直接添加到ProgressArc(来自第二个清单):

MouseArea {
    anchors.fill: parent
    onClicked: {
        console.log("Clicked on " + mouse.x + " " + mouse.y)
        var percent = calcPercentBasedOnMousePos(mouse.x, mouse.y)
        jumpToPosition(percent)
    }
}

不要忘记设置锚来填充父项(否则这个MouseArea将是0x0大小,无法处理任何点击)。

你可以看到onClicked处理器的虚拟实现——这是关于我如何看待你的任务。因此,您可以自由地操作xy的值自己。