0

我需要每两三秒刷新一次 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 文件。一个包含所有的点、线和标签。第二个仅包含必须显示的点和标签。

4

2 回答 2

3

设置画布的尺寸会完全清除它,所以线条:

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

可能会使您的画布“闪烁”。GET 请求是异步的,因此在计算和绘制点数据之前清除画布。

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

于 2013-06-17T16:41:55.543 回答
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......他们都只给出一个估计值)。

于 2013-06-17T21:16:02.910 回答