代码之家  ›  专栏  ›  技术社区  ›  Martijn van der Bruggen

画布:并非反弹球对象数组中的所有对象都显示出来

  •  1
  • Martijn van der Bruggen  · 技术社区  · 7 年前

    我使用laravel 5.5、vuejs和vue路由器创建了一个spa/rest/crud应用程序。现在,我想到了在登录页上使用一个组件,并用画布来增加它的趣味。(最初是p5.js,但我现在放弃了。)到现在为止,一直都还不错。我让Vue组件通过Vue路由器工作,并在头版制作了一个带有自定义指令的组件,该指令将模板中的canvas元素及其数据(以ball对象的形式)馈送给canvas元素

    现在,由于我不得不切换到我并不熟悉的画布,我遇到了一个问题。作为测试,我将4个球放入一个阵列中。但只有1个在显示。现在,当我禁用clearRect函数时。它们确实以一种混乱的方式出现。显然,我不得不使用beginPath()来防止球“拖拽”。但当我这样做的时候,只有一个出现了。也许我忽略了一件简单的事情。我将在下面发布我认为导致问题的部分:

    <script>            
    export default {
        data: function(){
            return {
    
            }
        },
        directives: {
          bindCanvas: {
    
            inserted: function (el) {
                var ctx = el.getContext("2d");
                var Ball = function(x,y,r){
                    this.position = {};
                    this.position.x = x;
                    this.position.y = y;
                    //i could not use vectors so i came up with this solution
                    this.velocity = {x:0,y:0};
                    this.acceleration = {x:0,y:0};                  
                    this.radius = r;
                };
                Ball.prototype.addForce = function(x,y){
    
                    this.acceleration.x += x/1000;
                    this.acceleration.y += y/1000;
    
                };
                Ball.prototype.move = function(){                   
    
                    this.position.x += this.velocity.x;
                    this.position.y += this.velocity.y;
                    this.velocity.x += this.acceleration.x;
                    this.velocity.y += this.acceleration.y;
    
                    //reset acceleration to 0
                    this.acceleration.x *= 0;
                    this.acceleration.y *= 0;
                };
                Ball.prototype.display = function(){
                    //here is the problem somewhere i think.
                    ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
                    ctx.beginPath();
                    ctx.fillStyle = 'rgb(255,0,0)';
                    ctx.arc(this.position.x,this.position.y,this.radius,0, Math.PI*2);
                    ctx.fill();
                };
    
                Ball.prototype.checkBorders = function(){
                    if(this.position.x > ctx.canvas.width-(this.radius/2)){
                        this.velocity.x = this.velocity.x *-1;
                    } else if (this.position.x < 0){
                        this.velocity.x *= -1;
                    }
                    if (this.position.y > ctx.canvas.height-(this.radius/2)){
                        this.velocity.y *= -1;
                    } else if(this.position.y < 0){
                        this.velocity.y *= -1;
                    }
                };
    
                Ball.prototype.checkMaxSpeed = function(){
                    if(this.velocity.x > 0.5){
                        this.velocity.x = 0.5;
                    }
                    if(this.velocity.x < -0.5){
                        this.velocity.x = -0.5;
                    }
                    if(this.velocity.y > 0.5){
                        this.velocity.y = 0.5;
                    }
                    if(this.velocity.y < -0.5){
                        this.velocity.y = -0.5;
                    }
                };
    
                var arrayOfBalls = [];
    
                for(var i=0;i<=3;i++){
                    arrayOfBalls.push(new Ball(Math.random()*100,Math.random()*100,Math.random()*100));
                }
    
    
                var animate = function(){
    
    
                    for(var j = arrayOfBalls.length-1; j>= 0; j--){
                    arrayOfBalls[j].checkBorders();
                    arrayOfBalls[j].checkMaxSpeed();
                    arrayOfBalls[j].addForce(Math.random(),Math.random());
                    arrayOfBalls[j].addForce(0,0.00098);
    
                    arrayOfBalls[j].display();
                    arrayOfBalls[j].move();
                    }
                    window.requestAnimationFrame(animate);
    
                };
                animate();
            }
          }
        },
    
    
    }
    

    1 回复  |  直到 7 年前
        1
  •  0
  •   dougtesting.net    7 年前

    正如我在评论中提到的,问题是每个球的display()函数中的clearRect()调用。通常情况下,画布只需在动画的每个帧/循环中清除一次,以便将clearRect放置在动画函数的顶部,如图所示。。。

    var animate = function(){
    
        // Clear the canvas just once each animation frame here
        ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
    
        for(var j = arrayOfBalls.length-1; j>= 0; j--) {
            arrayOfBalls[j].checkBorders();
            arrayOfBalls[j].checkMaxSpeed();
            arrayOfBalls[j].addForce(Math.random(),Math.random());
            arrayOfBalls[j].addForce(0,0.00098);
    
            arrayOfBalls[j].display();
            arrayOfBalls[j].move();
        }
        window.requestAnimationFrame(animate);
    };