刷新时HTML5画布闪烁

时间:2013-06-17 16:05:30

标签: javascript jquery html5 html5-canvas setinterval

我需要每两到三秒刷新一次HTML5画布。

setInterval(writeCanvas, 2000);

此画布上填充了点和线。每个横坐标和纵坐标都存储在XML文件中。因此,在更新画布之前,我会对服务器上的文件执行异步请求。

问题是画布闪烁。我猜它在异步请求运行时消失了。

我怎么能解决这个问题?

这是writeCanvas的代码:

function drawLines(ctx, back, front, width, xArray, yArray) {
    ctx.strokeStyle = back;
    ctx.fillStyle = front;
    ctx.lineWidth = width;
    ctx.beginPath();
    ctx.moveTo(xArray[0], yArray[0]);
    for (var i=1; i<xArray.length; i++) {
        ctx.lineTo(xArray[i],yArray[i]);
    }
    ctx.fill();
    ctx.stroke();
    ctx.closePath();
}

function drawPoint(ctx, back, front, x, y, radius, startAngle, endAngle) {
    ctx.strokeStyle = back;
    ctx.fillStyle = front;
    ctx.beginPath();
    ctx.arc(x,y,radius,startAngle,endAngle,endAngle);
    ctx.fill();
    ctx.stroke();
    ctx.closePath();
}

function writeLabel(ctx, color, font, x, y, text) {
    ctx.fillStyle = color;
    ctx.font = font;
    ctx.beginPath();
    if(x < 0) {
        x = 0;
    }
    ctx.fillText(text, x, y);
    ctx.fill();
    ctx.closePath();
}

function writeCanvas()
{
    var elem = document.getElementById('profileCanvas');
    if (!elem || !elem.getContext) {
        return;
    }

    var ctx = elem.getContext('2d');
    if (!ctx) {
        return;
    }

    // apply the final size to the canvas
    elem.setAttribute('width', canvasWidth);
    elem.setAttribute('height', canvasHeight);

    $.get('profileStatus.xml', function(xml) {
        if(xml) {
            var testPoints = new Array();
            $(xml).find('TP').each(function() {
                var selected = $(this).find('SELECTED:first').text();
                if(selected == "YES") {
                    var name = $(this).find('MODULE_NAME:first').text();
                    var state = $(this).find('STATE:first').text();
                    var tp = new ProfileTp(name, state, selected);
                    testPoints.push(tp);
                }
            });

            $.get('profile.xml', function(data) {
                if(data) {
                    profileWidth = parseFloat($(data).find('MAIN > PROFILE > DIM_W').first().text());
                    profileHeight = parseFloat($(data).find('MAIN > PROFILE > DIM_H').first().text());

                    var backgroundColor = '#ddd';
                    var color = '#323232';
                    ctx.translate(0,canvasHeight);

                    var xArray = new Array();
                    var yArray = new Array();

                    $(data).find('PROFILE > POINT > X').each(function(){
                        var x=parseFloat($(this).text());
                        xArray.push(x);
                    });
                    $(data).find('PROFILE > POINT > Y').each(function(){
                        var y=parseFloat($(this).text());
                        yArray.push(y);
                    });
                    drawLines(ctx, backgroundColor, color, 2, xArray, yArray);

                    var finalArray = new Array();
                    $(data).find('TESTPOINTS > TP').each(function() {
                        var labelName = $(this).find('MODULE_NAME:first').text();
                        var tp = $.grep(testPoints, function(obj){ return obj.NAME == labelName; });
                        if(tp.length == 1) {
                            $(this).find('IHM').each(function(){
                                tp[0].LABEL_X = parseFloat($(this).find('LABEL > X:first').text());
                                tp[0].LABEL_Y = parseFloat($(this).find('LABEL > Y:first').text());
                                tp[0].MARKER_X = parseFloat($(this).find('MARKER > X:first').text());
                                tp[0].MARKER_Y = parseFloat($(this).find('MARKER >Y:first').text());
                            });
                            finalArray.push(tp[0]);
                        }
                    });
                    for(var i=0; i<finalArray.length; i++) {
                        writeLabel(ctx, color, fontSize+"px Arial",(finalArray[i].MARKER_X+finalArray[i].LABEL_X),(finalArray[i].MARKER_Y+finalArray[i].LABEL_Y), finalArray[i].NAME);
                        drawPoint(ctx, backgroundColor, color, finalArray[i].MARKER_X, finalArray[i].MARKER_Y, 8, 0, 2*Math.PI);
                    }
                } else {
                    console.error('No XML test points returned');
                }
            });
        }
    });
}

有两个XML文件。一个包含所有点,线和标签。第二个只包含必须显示的点和标签。

2 个答案:

答案 0 :(得分:3)

设置画布&#39;维度完全清除它,所以行:

elem.setAttribute('width', canvasWidth);
elem.setAttribute('height', canvasHeight);

可能会让你的画布眨眼。 GET请求是异步的,因此在计算和绘制点数据之前,画布将被清除。

要解决此问题,请在绘制之前更改请求回调中的维度。

答案 1 :(得分:0)

Crogo已经在答案中提到了可能的原因,但作为一项解决方法你可以做到:

if (elem.width !== canvasWidth || elem.height !== canvasHeight) {
    // apply the final size to the canvas
    elem.setAttribute('width', canvasWidth);
    elem.setAttribute('height', canvasHeight);
}

仅在尺寸更改时设置画布大小。

您还应该尝试避免使用setInterval(如果客户端处于缓慢/不稳定的连接上,则需要超过2秒才能加载数据...)。如果下载仍在进行中并且setInterval触发,您将在第一个下载时继续下载。当这些调用在事件队列中堆叠时,您还可能冒险将“双图”添加到画布:

而是从setTimeout

中触发writeCanvas()
function writeCanvas()
{
    //... load and draw

   setTimeout(writeCanvas, 1500); //compensate for time
}

当然,如果数据必须每两秒加载一次,这将是不准确的(不是setInterval是......它们都只给出估计值。)