I'm trying to adapt the Html JS library Char.js to QML QtQuick 2.4.
The library have a function to animate the scene. Everything works great if I don't animate it (eg animate with only 1 step of animation).
When the animation is used, the canvas freeze until the animation is finished, and then the scene is redraw. Here is the animationLoop function:
animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){
var currentStep = 0,
easingFunction = easingEffects[easingString] || easingEffects.linear;
var animationFrame = function(){
currentStep++;
var stepDecimal = currentStep/totalSteps;
var easeDecimal = easingFunction(stepDecimal);
callback.call(chartInstance,easeDecimal,stepDecimal, currentStep);
onProgress.call(chartInstance,easeDecimal,stepDecimal);
if (currentStep < totalSteps){
chartInstance.animationFrame = chartInstance.chart.canvas.requestAnimationFrame(animationFrame);
} else{
onComplete.apply(chartInstance);
}
};
chartInstance.chart.canvas.requestAnimationFrame(animationFrame);
},
Each time the onAnimationProgress callback is called, I call the Canvas requestPaint function to redraw the scene. Unfortunately, the onPaint function will not be called until every step of the animation have finished.
The Canvas object is accessible with : chartInstance.chart.canvas
. I tried to call directely chartInstance.chart.canvas.requestPaint() at each iteration too, which do not work. I still have to wait until the animation finished to see the scene redraw correctly.
onAnimationProgress: function(easeDecimal,stepDecimal) {
skipNextChartUpdate = true;
requestPaint();
}
onPaint: {
if (!chartInstance) {
initializeChart()
} else if(!skipNextChartUpdate) {
chartInstance.scale.update({width:width,height:height});
chartInstance.resize(chartInstance.update);
} else {
skipNextChartUpdate = false;
}
}
This is more or less as I would expect.
requestPaint
is not an immediate operation, it's a request to repaint at a later point. So if you callrequestPaint
multiple times in a single JS function, you will only receive oneonPaint
event per (vsync) frame.So if you want to drive an animation, you should be driving them inside onPaint, by calling requestPaint (to ask for another onPaint event in the future) if there is still more animation to show for instance.