Qt QML Canvas requestPaint does not repaint immedi

2019-07-10 08:45发布

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;
    }
}

1条回答
男人必须洒脱
2楼-- · 2019-07-10 09:27

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 call requestPaint multiple times in a single JS function, you will only receive one onPaint 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.

查看更多
登录 后发表回答