Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Change NumberAnimation while running
Forum Updated to NodeBB v4.3 + New Features

Change NumberAnimation while running

Scheduled Pinned Locked Moved Solved QML and Qt Quick
9 Posts 3 Posters 2.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mark81
    wrote on last edited by
    #1

    I wonder how to change the property of a NumberAnimation (say "loops" or "to") while it's running.
    Of course I tried to use a variable but it has no effect. Example:

    SequentialAnimation {
        id: anim
    
        // change rotation centers
        PropertyAction { target: rotSpin; property: "origin.x"; value: xCenterNeedle }
        PropertyAction { target: rotSpin; property: "origin.y"; value: yCenterNeedle }
    
        NumberAnimation { id: numAnim; target: rotSpin; property: "angle"; easing.type: Easing.Linear; to: _degree; duration: _time; }
    
        onStopped: {_isSpinning = false; }
    }
    

    I start it:

    function startSpin() {
        _degree += 360;
        _time = _timeForSector * 12;
        anim.loops = Animation.Infinite
        _isSpinning = true;
        anim.start()
    }
    

    and now I want to change something:

    function stopSpin()
    {
        if (_isSpinning)
        {
            var angle = rotSpin.angle;  // current angle
            var currSector = Math.floor(angle / 30); // current sector
    
            numAnim.to = (currSector + 1) * 30; // angle of the next sector
            anim.loops = 1;  // stop when reach the requested angle
        }
    }
    

    but nothing happens.
    Where's my error?

    By the way, the specific goal is to stop a spinning needle on a precise angle (x * 30) when requested.

    1 Reply Last reply
    0
    • 6thC6 Offline
      6thC6 Offline
      6thC
      wrote on last edited by 6thC
      #2

      I don't know the answer to your more than one rotation... but I do know Rotations are easier with RotationAnimation QML Type - this way you can cross that 0-360 degree boundary without a full opposite wind.

      I have things like:

      onValueChanged:
         RotationAnimation {
             target: root;
             property: "rotation"
             easing.type: Easing.InOutSine;
             to:root.value; 
             direction: RotationAnimator.Shortest;
             duration: 300; 
      
      1 Reply Last reply
      0
      • M Offline
        M Offline
        Mark81
        wrote on last edited by
        #3

        Thanks, but I don't need the shortest path.
        I only need to rotate an Image until a signal fires. At that moment, let's say the angle is 53 degrees, I need to stop the animation when it reaches 60 degrees.

        1 Reply Last reply
        0
        • 6thC6 Offline
          6thC6 Offline
          6thC
          wrote on last edited by
          #4

          @Mark81 said in Change NumberAnimation while running:

          NumberAnimation

          Well, I'm not trying to sell you! I just know that that NumberAnimation will not spin but start counting down from the number that is in your angle just before it crosses the threshold.

          Your "rotate an image until a signal fires" - won't work very well when for example it's winding up / clockwise up close to a full rotation - at which point the value crosses and if the intent is keep spinning - instead for that single animation it will unwind counterclockwise, then the next update continuing to the next target clockwise.

          It just looks very wrong - you do what you recon - maybe you know the value is never reaching a full rotation - but "spin" to me indicated you wish to perform one or more rotations.

          I'll leave you to figure out your target angle - that math is basic - or ... maybe you could just use states

          Dunno, just trying to give you leads to get moving again...

          states: State {
                      name: "SectorOne"; when: (value >= 0 && value <= 30 )
           // change rotation centers
              PropertyAction { target: rotSpin; property: "origin.x"; value: xCenterNeedle }
              PropertyAction { target: rotSpin; property: "origin.y"; value: yCenterNeedle }
              PropertyAction { target: rotSpin; property: "angle"; value: 30 }
              NumberAnimation { id: numAnim; target: rotSpin; property: "angle"; easing.type: Easing.Linear; to: _degree; duration: _time;
          }
          State {
                      name: "SectorTwo"; when: (value > 30 && value <= 60 )
           // change rotation centers
              PropertyAction { target: rotSpin; property: "origin.x"; value: xCenterNeedle }
              PropertyAction { target: rotSpin; property: "origin.y"; value: yCenterNeedle }
              PropertyAction { target: rotSpin; property: "angle"; value: 60 }
              NumberAnimation { id: numAnim; target: rotSpin; property: "angle"; easing.type: Easing.Linear; to: _degree; duration: _time; }
          
          1 Reply Last reply
          1
          • M Offline
            M Offline
            Mark81
            wrote on last edited by
            #5

            Thanks a lot for your answer.
            I will try your approach, but I'm not sure I explained the scenario very well. I'm going to try with a simpler example.

            Let's image to have a stopwatch, with a single needle. When the stopwatch start, the needle begins to "spin" forever.
            But when the user decides to stop it (i.e. the stopSpin() event is fired) the needle cannot just stop where it is but it has to reach the very next "hour". I.e. if the event fired when the needle was pointing to 85 degrees, it should stop ONLY when it has reached 90 degrees.

            Right now I ended up with a workaround.
            In the stopSpin() function I stop the animation and in the onStopped event I read the current angle of my needle. Then I start again the same animation setting the new target and duration fields to reach the desired angle.
            It works (as you said, it's a matter of basic maths) but sometimes the needle stops a while before moving again. Instead the animation should be flawless.

            1 Reply Last reply
            0
            • 6thC6 Offline
              6thC6 Offline
              6thC
              wrote on last edited by
              #6

              I think you'd need to interrupt your animation. I'd be looking for a solution where you just update your target and indeed get flawless animation.

              I haven't had to deal with interrupted animations - I have known baud rates and controls that are reactive (not responsive to user input) so it's easy to setup animation speeds to always complete slightly faster than my configured baud rate.

              Maybe you'll find http://doc.qt.io/qt-5/qml-qtquick-smoothedanimation.html is better for you?

              M 1 Reply Last reply
              0
              • 6thC6 6thC

                I think you'd need to interrupt your animation. I'd be looking for a solution where you just update your target and indeed get flawless animation.

                I haven't had to deal with interrupted animations - I have known baud rates and controls that are reactive (not responsive to user input) so it's easy to setup animation speeds to always complete slightly faster than my configured baud rate.

                Maybe you'll find http://doc.qt.io/qt-5/qml-qtquick-smoothedanimation.html is better for you?

                M Offline
                M Offline
                Mark81
                wrote on last edited by
                #7

                @6thC said in Change NumberAnimation while running:

                Maybe you'll find http://doc.qt.io/qt-5/qml-qtquick-smoothedanimation.html is better for you?

                I will give it a try, but unfortunately I cannot use any Easing type but the Linear one. Anyway perhaps I might find a way to use it. It's not clear to me what does the maximumEasingTime property mean. I'm going to play a little with it.

                1 Reply Last reply
                0
                • timdayT Offline
                  timdayT Offline
                  timday
                  wrote on last edited by
                  #8

                  I have wanted to do similar things before but eventually decided I was expecting too much from the QML Animation types suddenly trying to get them to something else part way through an animation. I decided to just take more control instead... here's an example minute-hand clock (runs in Qt 5.9.1's qmlscene); click the window to start and stop the clock movement:

                  import QtQuick 2.7
                  
                  Rectangle {
                    id: main
                    width: 512
                    height: 512
                  
                    Rectangle {
                      x: 0.5*parent.width
                      y: 0.5*parent.height
                      width: 10
                      height: 200
                      radius: 5
                      color: 'red'
                      transformOrigin: Item.Top
                      rotation: (((control.spinning ? clock.time : control.stopTime)-control.lostTime)/60.0)%360.0   
                    }
                  
                    Timer {
                      id: clock
                      interval: 1000.0/60.0
                      repeat: true
                      running: true
                      triggeredOnStart: true
                      onTriggered: time=(new Date()).getTime()
                      property real time
                    }
                  
                    MouseArea {
                      id: control
                      anchors.fill: parent
                      onClicked: {
                        if (spinning) {
                          stopTime=clock.time
                          spinning=false
                        } else {
                          startTime=clock.time
                          lostTime+=(startTime-stopTime)
                          spinning=true
                        }
                      }
                      property bool spinning: true
                      property real stopTime: 0.0
                      property real startTime: 0.0
                      property real lostTime: 0.0
                    }
                  }
                  

                  I was actually a little paranoid about the resolution of the QML/javascript-world timers so in an actual app I replace that QML Timer with a QTimer with setTimerType(Qt::PreciseTimer) in the hosting C++ QQuickView. Not sure it makes any difference though.

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    Mark81
                    wrote on last edited by
                    #9

                    Thanks for the hint. Here the changes I've made to allow stopping on defined position:

                    rotation: {
                            if (control.spinning || clock.time < control.stopTime)
                            {
                                return ((clock.time - control.lostTime) / 60.0) % 360.0;
                            }
                            else
                            {
                                return (( control.stopTime - control.lostTime) / 60.0) % 360.0;
                            }
                        }
                    

                    and in the stop event:

                    if (spinning)  {
                            stopTime=clock.time + 500 // set the stop position
                            spinning=false
                    }
                    ...
                    
                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved