我需要每两到三秒刷新一次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文件。一个包含所有点,线和标签。第二个只包含必须显示的点和标签。
答案 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
是......它们都只给出估计值。)