QML Canvas.requestAnimationFrame explodes

I am trying to use QML Canvas.requestAnimationFrame to draw some custom animation. I expected the provided callback to be called once for each frame, about 60 times per second. The code I have is:

 Canvas { id: canvas width: 600 height: 600 function draw() { } Component.onCompleted: { var i = 1; function drawFrame() { requestAnimationFrame(drawFrame) console.log("Frame callback: " + i++) draw() } drawFrame() } onPaint: { draw() } } 

What I see is that the callback is called the way more often. The counter reaches 70,000 in a few seconds, after which the application becomes completely immune.

What am I doing wrong?

+6
source share
3 answers

Your drawFrame() function is passed as a callback function for rendering, and you drawFrame() up in a loop. You either want to render on demand only, for example, after user input, to save resources at least, or you have some kind of logic that changes every frame or you just need continuous rendering.

If temporary rendering is what you want, just use Timer :

 import QtQuick 2.4 Canvas { id: cvs width: 600; height: 600 contextType: "2d" property real i : 0 onPaint: { console.timeEnd("t") if (context) { context.clearRect (0, 0, width, height) context.fillRect(i, 50, 50, 50 + i) } console.time("t") } Timer { interval: 1 repeat: true running: true onTriggered: { cvs.i = (cvs.i + 0.1) % cvs.width cvs.requestPaint() } } } 

Edit:

Just updated the code:

onPaint calls are synchronized with the display frame rate, even if the timer interval is set to 1 ms, as you can see from the log when you run the example above. In fact, the entire block assigned to the onTriggered signal is executed every millisecond, but requestPaint() allows you to synchronize the rendering calls for better performance, as requestAnimationFrame() does for the HTML canvas.

Apparently requestAnimationFrame() inside QML.Canvas does not work as expected, and there is not much documentation ...

Hope this helps!

+2
source

Just a small update on this topic. I ran into the same issue with Qt qml Canvas and requestAnimationFrame while I was working on my project. The solution I found is to switch the rendering strategy to Threaded and use the onPainted signal. The qCring sample code with my updates is as follows:

 import QtQuick 2.4 Canvas { id: cvs width: 600; height: 600 //renderStrategy: Canvas.Cooperative // Will work as well but animation chops on my computer from time to time renderStrategy: Canvas.Threaded contextType: "2d" property real i : 0 function animate() { cvs.i = (cvs.i + 0.1) % cvs.width; } onPaint: { console.timeEnd( "t" ) if ( context ) { context.clearRect( 0, 0, width, height ) context.fillRect( i, 50, 50, 50 + i ) } console.time("t") cvs.requestAnimationFrame(animate); } onPainted: { cvs.requestPaint(); } } 
+1
source

Prior to Qt 5.9, an error occurred with requestAnimationFrame() . This bug has been fixed.

This code works as expected and is desirable for continuous repainting of the canvas.

 Canvas { width:100; height:100; property var ctx onAvailableChanged: if (available) ctx = getContext('2d'); onPaint: { if (!ctx) return; ctx.clearRect(0, 0, width, height); // draw here requestAnimationFrame(paint); } } 
0
source

Source: https://habr.com/ru/post/988722/


All Articles