画布工作只要我使用它一次

时间:2014-01-24 08:17:54

标签: javascript html5 canvas

我正在绘制画布并根据值旋转它,如果我在页面上使用画布一次,它就会起作用。

如果我第二次将它添加到页面,只有最后一个被绘制,我无法在我的代码中找到错误,并且我没有得到js错误。

我认为问题出在下一个功能中:

function animate(){ 

function drawnumbers()
{context.save(); 
context.fillStyle = "#000000"; 
context.translate(73,0); 
context.font="10px Orbitron"; 
context.textAlign = "center"; 
context.rotate(((i*(180/min)))*Math.PI/180); 
context.fillText(data.values[i].amount,0,3); 
context.restore(); 
}; 
if (d < defer){ 
context.clearRect(0,0,400,400); 
d++; 

context.save(); 
var ang = ((((d-minn)*(180/angle)))*(Math.PI/180)); 
context.translate(38,39); 
context.scale(.8,.8); 
base_image = new Image(); 

base_image.src = 'http://oi44.tinypic.com/2hfkx8p.jpg'; 
context.translate(base_image.width/2, base_image.height/2); 
context.rotate(ang ); 
context.drawImage(base_image, -base_image.width/2, -base_image.height/2); 
context.restore(); 

context.save();
context.beginPath(); 
context.arc(100,100,64,1*Math.PI,2*Math.PI, false); 
context.lineWidth = .4; 
context.strokeStyle="#00A1DE"; 
context.globalAlpha = 0.7; 
context.stroke(); 
context.restore(); 

context.save(); 
context.translate(100,100); 
context.rotate(Math.PI/180); 
context.strokeStyle = "#00A1DE"; 
context.lineWidth = .7; 
for (var i=0;i < data.values.length; i++){ 
context.beginPath(); 
context.moveTo(62,0); 
context.lineTo(67,0); 
context.stroke(); 
context.globalAlpha = 0.7; 
drawnumbers(); 
context.rotate((182/(min))*(-Math.PI/180)); 
} 
context.restore(); 

context.fillStyle="white"; 
context.fillRect(38,101,123,75); 

context.save(); 
context.fillStyle = "#00a1de"; 
context.font = "22px Orbitron"; 
context.textAlign = "center"; 
context.fillText(defer, 100, 90); 
context.restore(); 

context.save(); 
context.fillStyle = "#000000"; 
context.font = "10px arial"; 
context.textAlign = "center"; 
context.fillText(eenheid, 100, 115); 
context.restore(); 

} 
else 
{ 
clearTimeout(t); 
}; 
t=setTimeout("animate()",30-d); 
}; 

检查示例以便更好地理解:

http://jsbin.com/ogEgURu/1/

我在一个函数中使用它但它仍然是同一个问题所以我认为我的代码出了问题。

任何人都可以看到我没有看到的问题吗?

1 个答案:

答案 0 :(得分:2)

你的代码过于复杂,特别是因为这种复杂性没有充分的理由 复制大的(> 200)行代码块以复制功能是容易出错的 重构代码后,您将能够轻松看到问题 只是一些提示:

  • 非常简单:美化代码。
  • 无冗余:如果代码位于此处两次或更多,请创建一个函数并进行分解。
  • 将代码分解为更小的部分。例如:drawText(context,text,x,y,font)(打印eenheid和defer),drawNumbers(context),drawRotatingImage(context,angle),...
  • 每次beginPath()时都使用closePath();
  • 在页面加载时加载一次图像,并等待它在动画之前加载。
  • 不要在循环中定义函数(drawumbers)。
  • 使用单个对象存储多个参数(context,angle,...)或 甚至切换到面向对象的风格。
  • 只有一个 animate()循环,如果需要,它将调用多个draw(...)函数。

毕竟,你的代码看起来会更简单,bug应该很快消失。

我做了这项工作(部分),在这个小提琴中: http://jsfiddle.net/gamealchemist/ztczK/1/(已编辑)

代码如下:

// parameters : settings for one gauge display
var parameters1 = {
    data: data,
    defer: '520',
    context: context,
    left: 38,
    top: 30,
    d: 0,
    angle: 0,
    scale: 0.8,
    //... whatever parameter here
};
var parameters2 = ... ;

将绘图分成许多函数,因此理解起来要简单得多:

// draws a gauge
function drawGauge(param) {
    preDraw(param);
    drawBaseImage(param);
    drawArc(param);
    drawTheNumbers(param);
    writeDefer(param);
    writeEenheid(param);
    postDraw(param);
}

// translate and scales context, and updates some values for the gauge
function preDraw(param) {
    var minn = param.data.values[param.data.values.length - 1].amount;
    var maxn = data.values[0].amount;
    var angle = maxn - minn;
    var d = param.d;
    param.ang = ((((d - minn) * (180 / angle))) * (Math.PI / 180));
    var ctx = param.context;
    ctx.save();
    ctx.translate(param.left, param.top);
    ctx.scale(param.scale, param.scale);
    context.fillStyle = "white";
    context.fillRect(0, 60, 123, 75);
}

// restore context
function postDraw(param) {
    var ctx = param.context;
    ctx.restore();
    param.d++;
}

function drawBaseImage(param) {
    var ctx = param.context;
    var ang = param.ang;
    ctx.save();
    ctx.translate(base_image.width / 2, base_image.height / 2);
    ctx.rotate(ang);
    ctx.drawImage(base_image, -base_image.width / 2, -base_image.height / 2);
    ctx.restore();
}

function drawArc(param) {
    var ctx = param.context;
    ctx.save();
    ctx.beginPath();
    ctx.arc(base_image.width / 2, base_image.height / 2, 64, 1 * Math.PI, 2 * Math.PI, false);
    ctx.lineWidth = .4;
    ctx.strokeStyle = "#00A1DE";
    ctx.globalAlpha = 10.7;
    ctx.stroke();
    ctx.restore();
}

function writeDefer(param) {
    var ctx = param.context;
    var defer = param.defer;
    ctx.save();
    ctx.fillStyle = "#00a1de";
    ctx.font = "22px Orbitron";
    ctx.textAlign = "center";
    ctx.fillText(defer, base_image.width / 2, base_image.height / 2);
    ctx.restore();
}

function writeEenheid(param) {
    var ctx = param.context;
    ctx.save();
    ctx.fillStyle = "#000000";
    ctx.font = "10px arial";
    ctx.textAlign = "center";
    ctx.fillText(eenheid, base_image.width / 2, base_image.height / 2 + 20);
    ctx.restore();
}

function drawTheNumbers(param) {
    var ctx = param.context;
    var dataValues = param.data.values;
    var count = dataValues.length;
    ctx.save();
    ctx.translate(base_image.width / 2, base_image.height / 2);
    ctx.rotate(Math.PI / 180);
    ctx.strokeStyle = "#00A1DE";
    ctx.lineWidth = .7;
    ctx.fillStyle = "#000000";
    ctx.font = "10px Orbitron";
    ctx.textAlign = "center";
    ctx.globalAlpha = 0.7;
    for (var i = 0; i < count; i++) {
        ctx.beginPath();
        ctx.moveTo(62, 0);
        ctx.lineTo(67, 0);
        ctx.stroke();
        ctx.closePath();
        ctx.fillText(dataValues[i].amount, 60, 3);
        ctx.rotate(-Math.PI / count);
    }
    context.restore();
}

然后动画变得非常简单,即使有几个仪表:

function animate() {
    context.clearRect(0, 0, canvasWidth, canvasHeight);
    drawGauge(parameters1);
    drawGauge(parameters2);
    setTimeout(animate, 15);
};
base_image.onload = animate();