2014-05-13 24 views
0

首先,请原谅我绝对缺乏JavaScript知识。我正在寻找解决此问题的最佳方法,但3天后我认为这可能是错误的。处理矩形实例以在画布上单独绘制的最佳方法

我需要编写一些代码在画布中的不同行中绘制移动的矩形。将来我需要检测两个矩形在同一个X坐标中的位置,因此重要的是跟踪X值。来自Java的我认为最好的办法是创建一些矩形“对象”,每个实例都有一个绘制方法。

是什么导致我的麻烦是我想用setInterval()调用draw函数,但是看起来每次调用函数draw时,值都不一样。

这是我的Rectangle类的定义:

function Rectangle(x,y,width,height) { 
     var x=x; 
     var y= y; 
     var width= width; 
     var height= height; 

     this.getX = function(){ 
      return x; 
     } 
     this.setX = function (value) { 
      x = value; 
     } 

     this.getY = function(){ 
     return y; 
     } 

     this.setY = function (value) { 
     y = value; 
     } 

     this.getWidth = function(){ 
     return width; 
     } 

     this.setWidth = function (value) { 
     width = value; 
     } 

     this.getHeight = function(){ 
      return height; 
     } 

     this.setHeight = function (value) { 
      height = value; 
     } 

     this.draw = function(){ 

    if(this.getX() <=canvas.width){ 
     clearContext(this.getX() - 30,this.getY(),this.getWidth(),this.getHeight());  
     var temp= this.getX()+1; 
     this.setX(temp); 
     ctx.fillRect(temp,this.getY(),this.getWidth(),this.getHeight()); 
    }else{ 
      clearInterval(this.draw(),speed); 
    } 

} 
} 

然后,我有一个功能formSubmit,我创建矩形实例时按下按钮,并调用分别是功能与setInterval()得出:

function formSubmit(){ 
    number=parseInt(document.getElementById("nummerT").value); 
    rate=parseInt(document.getElementById("rate").value); 
    speed=parseInt(document.getElementById("speed").value); 
    confirm(speed); 
    myRectangle= new Rectangle(0,0,30,30); 
    myRectangle2 = new Rectangle(0,60,30,30); 
    setInterval(myRectangle.draw(),speed); 
} 

回答

0

我没有这么多添加到其他的答案(+1到两个),但只是一份关于这一部分:

function Rectangle(x,y,width,height) { 
     var x=x; 
     var y= y; 
     var width= width; 
     var height= height; 
     ... 

当你做Rectangle(x, y, ...)编译器/解析器会怎么做这件事情(或者更确切地说,相当于):

var x = arguments[0]; // x declared internally, no need to manually declare it 
var y = arguments[1]; // y declared too, etc. 
... 

,所以你不需要在函数签名声明变量,因为他们已经宣布 - 或者刚刚离开签名不带任何参数的d手动分配(稍微慢一点但完全合法)。

function Rectangle() { 
     var x = arguments[0]; // legal but not recommended (in most cases) 
     var y = arguments[1]; 
     ... 

所以,结论 - 在这种情况下,推荐的做法是:

function Rectangle(x,y,width,height) { 
    // no x,y, width and height decl. here - they're declared by signature 
    this.getX = function(){ 
     return x; 
    } 
    ... 

第二期:setInterval需要一个参考的功能。因为现在该函数将被调用,因为将括号放在最后,而该函数的结果将作为参考递交。

你可以把它想:

setInterval(myRectangle.draw, speed); // only a reference, no parenthesis 

但为了使它取消你需要存储的计时器ID:

var timerID; // global scope 

... 
timerID = setInterval(myRectangle.draw, speed); 

然后使用该请求后取消它:

clearInterval(timerID); 

我也会推荐使用​​,因为这是针对动画和m监控器同步。

setInterval相反,您需要在动画循环中的每帧中调用它。您可以使用标记/条件而不是当您要结束动画时再次调用它。

你也有一个clearContext在那里的方法 - 我假设你有代码中的其他地方定义,如果没有,检查出context.clearRect()

1

问题是setInterval(myRectangle.draw(),speed);没有做到你认为的那样。您正在调用draw一次,然后间隔正在调用draw的结果。你需要这样的东西:

interval = setInterval(function() { 
    myRectangle.draw(); 
}, speed); 

你会注意到,我的setInterval的返回值设置为变量,因为这将是你以后清除的时间间隔。您只需拨打

clearInterval(interval); 

如果这就是要解决所有的问题,我不知道,但应该至少你得到的东西,会给你一些更多的信息。

1

演示:http://jsfiddle.net/m1erickson/SdPPa/

enter image description here

你创建矩形对象来定义什么是在画布上绘制的确是通用标准的本能。

与Java不同,JavaScript没有真正的类,但是您可以像在问题中那样创建伪类。

在它的最简单的一个矩形“类”需要这些属性:

  • X,Y
  • 宽度,高度

如果要动画您可以添加在画布上的矩形:

  • velocityX,directionY
  • velocityY,方向

这些新特性允许你移动矩形这样的:

this.x += this.directionX * this.velocityX; 

this.y += this.directionY * this.velocityY; 

提示:的Html5现拥有一支优秀的动画处理:requestAnimationFrame。您可能想要使用它来代替setInterval或setTimeout,因为它通过将自身与浏览器的刷新周期进行集成来提供更好的性能。

提示: JavaScript是一种原型语言,因此您可以使用方法扩展您的“类”。将方法添加到“类”的最好方法是将它们添加到类原型中。这样一来,方法被创建一次并被类的所有实例共享,而不是在每个实例上重新创建每个方法。

于是一种方法,使一个矩形实例本身画到画布上可能是这样的:

// draw this rect on the canvas 
Rectangle.prototype.render=function(){ 
    ctx.fillStyle=this.color; 
    ctx.fillRect(this.x,this.y,this.width,this.height); 
    return(this); 
} 

提示:如果你总是返回(本) JavaScript的“类”方法可以链接。链接的好用可能是调用实例上的move方法,然后链接render方法。

rectangle1.move().render(); 

有很多关于JavaScript的“类”学习。

这里注释的代码开始于:

祝您的项目顺利!

<!doctype html> 
<html> 
<head> 
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> 
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> 
<style> 
    body{ background-color: ivory; } 
    canvas{border:1px solid red;} 
</style> 
<script> 
$(function(){ 

    // canvas related variables 
    var canvas=document.getElementById("canvas"); 
    var ctx=canvas.getContext("2d"); 

    // an array to hold all rectangle objects 
    var rectangles=[]; 

    // a rectangle pseudo-class (javascript does not have actual classes) 
    function Rectangle(stdProperties) { 

     addProperties(this,stdProperties); 

     this.color=randomColor(); 


    }; 
    // 
    // Add methods that apply to all instance rectangles 
    // to Rectangle.prototype so those methods are 
    // created once for all instances instead of 
    // repeatedly for every instance. 
    // 

    // set x,y,width,height of this rectangle 
    Rectangle.prototype.init=function(x,y,width,height){ 
     this.x=x; 
     this.y=y; 
     this.width=width; 
     this.height=height; 
     return(this); 
    }; 

    // move this rectangle by its preset delta-x and delta-y 
    Rectangle.prototype.move=function(){ 
     var maxRight=canvas.width-this.width; 
     var maxBottom=canvas.height-this.height; 
     this.x+=this.directionX*this.velocityX; 
     if(this.x<0){ this.x=0; this.directionX*=-1} 
     if(this.x>maxRight){ this.x=maxRight; this.directionX*=-1} 
     this.y+=this.directionY*this.velocityY; 
     if(this.y<0){ this.y=0; this.directionY*=-1} 
     if(this.y>maxBottom){ this.y=maxBottom; this.directionY*=-1} 
     return(this); 
    }; 

    // draw this rect on the canvas 
    Rectangle.prototype.render=function(){ 
     ctx.fillStyle=this.color; 
     ctx.fillRect(this.x,this.y,this.width,this.height); 
     return(this); 
    } 

    // create a new rectangle object from the Rectangle "class" 
    function newRect(x,y,width,height){ 

     // define default properties for Rectangle 
     var DefaultRectangleProperties={ 
      x:0,y:0,width:10,height:10, 
      velocityX:1,velocityY:1,directionX:1,directionY:1, 
      color:"black", 
     } 

     // new-up a Rectangle 
     var rect = new Rectangle(DefaultRectangleProperties); 

     // set the x,y,width,height & draw it on the canvas 
     rect.init(x,y,width,height).render(); 

     // return(this) to allow chaining 
     return(rect); 
    } 

    // TESTING 

    // create 5 rectangles with some randomness 
    for(var i=0;i<5;i++){ 
     var rect=newRect(Math.random()*200,Math.random()*200,40,50); 
     rect.velocityX=Math.random()*2; 
     rect.velocityY=Math.random()*3; 
     rectangles.push(rect); 
    } 

    // animate the rectangles using requestAnimationFrame 
    animate(); 


    // the animation loop 
    function animate(t){ 

     // request another animation frame 
     requestAnimationFrame(animate); 

     // clear the canvas 
     // move all the rectangles by their preset distance 
     // redraw all the rectangles 
     ctx.clearRect(0,0,canvas.width,canvas.height); 
     for(var i=0;i<rectangles.length;i++){ 
      rectangles[i].move().render(); 
     } 

    } 


    /////////////////////////////////// 
    // Utilities 
    /////////////////////////////////// 


    // create getters/setters on the specified object 
    // using the supplied properties object 
    // 
    function addProperties(object,properties){ 
     for (var i in properties) { 
      (function(i) { 
       Object.defineProperty(object, i, { 
        get: function(){ return properties[i]; }, 
        set: function(val){ properties[i] = val; } 
       }) 
      })(i); 
     }   
    } 

    // generate a random color 
    function randomColor(){ 
     return('#'+Math.floor(Math.random()*16777215).toString(16)); 
    } 


}); // end $(function(){}); 
</script> 
</head> 
<body> 
    <canvas id="canvas" width=300 height=300></canvas> 
</body> 
</html>