【问题标题】:Canvas Animation Not Rendering画布动画不渲染
【发布时间】:2012-08-15 07:43:42
【问题描述】:

我是 canvas 标签的新手,正在玩一些动画。基本上,我正在尝试设置一个由多个图像组成的“地面”部分(类似于像马里奥兄弟这样的 8 位横向卷轴游戏)。地面将由多个图像组成,我构建了一个构造函数来加载这些图像并将它们平铺在底部。

function Ground(context,ImageName,ImgX,ImgY,ImgW,ImgH){
    this.width=ImgW;
    this.height=ImgH;
    this.x=ImgX;
    this.y=ImgY;
    img=new Image();
        img.onload=function(){context.drawImage(img,ImgX,ImgY,ImgW,ImgH);};
    img.src='images/'+ImageName;};

这似乎工作得很好。然后我设置了动画的其余部分,包括 Key Left/Right 事件的基本设置,如下所示:

window.onload=function(){
    var canvas=document.getElementById('canvas'),
    context=canvas.getContext('2d'),
        Grounds=[],
        ImgX=-150; // INITIAL STARTING X FOR FIRST GROUND TILE

    // INSERT GROUND ELEMENTS
    for(var i=0,l=8; i<l; i++){
             var ImgX+=150;
             Grounds[i]=new Ground(context,"ground.png",ImgX,650,150,150);
        };

    // ASSIGN LEFT/RIGHT KEYS
    window.addEventListener('keyup',function(event){
              switch(event.keyCode){
                case 37:
                for(var i=0,l=Grounds.length; i<l; i++){
                         Grounds[i].x+=10;
                    };  
                 break;
            case 39:break;
              };
         });

    // ANIMATION LOOP
    (function drawFrame(){
    window.mozRequestAnimationFrame(drawFrame,canvas);
        context.clearRect(0, 0, canvas.width, canvas.height);

    }());
};

我确切地知道我的问题是什么,但不知道如何解决它。动画循环每帧都清除画布,但在用户按下左箭头键时不会重绘更新的位置(如果有)。

我在这里遗漏了重绘部分,我不确定如何处理这个问题,或者我是否完全错误地处理了这个问题。非常感谢任何帮助!谢谢!

【问题讨论】:

    标签: html loops canvas render


    【解决方案1】:

    你不能只添加一个draw方法吗?你通常是这样的: 初始化 -> 更新 -> 清除,重绘 -> 更新 -> 清除,重绘 -> ...

    // ANIMATION LOOP
    (function drawFrame(){
    window.mozRequestAnimationFrame(drawFrame,canvas);
        context.clearRect(0, 0, canvas.width, canvas.height);
        contect.drawImage(...);
    
    }());
    

    【讨论】:

      【解决方案2】:

      首先,您增加了地砖的属性x,但该属性甚至没有在您的代码中的任何地方使用。修改您的代码,使这些图像对象的onload 事件根据它们自己的x 属性绘制图像,因此对它的更改实际上会影响绘制的内容。还将图像对象添加为 Ground 对象的属性,以便您以后可以从外部访问它。

      您的方法确实不太好,但是如果您想在不回到 0 的情况下这样做,请按以下方式操作:

      function Ground(context,ImageName,ImgX,ImgY,ImgW,ImgH){
          this.width=ImgW;
          this.height=ImgH;
          this.x=ImgX;
          this.y=ImgY;
          var self = this; // Add local reference to this Ground instance 
          this.img=new Image(); // img is now a property too
              this.img.onload=function(){context.drawImage(this, self.x, self.y,self.width,self.height);};
          this.img.src='images/'+ImageName;};
      

      好的,现在您可以更改地砖的属性x 并再次调用它的绘制函数(即 onload 事件)。

      Grounds[i].x+=10;
      Grounds[i].img.dispatchEvent(new Event("load"));
      

      请注意,您确实应该先更新所有值,然后再分别进行所有绘制调用。

      【讨论】: