# 《每周一点canvas动画》——边界检测与摩擦力

ok！回归正题，本章的主要内容有：

• 环境边界检测

• 摩擦力的应用

1. 边界设置

2. 超出边界移除

3. 超出边界重新形成

4. 边界环绕

5. 边界反弹

### 1.设置边界

``    var left = 0,         top = 0,         right = canvas.width,         bottom = canvas.height;``

``    if(ball.x > right){         // do something     }else if(ball.x < left){         //do something     }      if(ball.y > bottom){         //do something     }else if(ball.y < top){         //do something     }``

### 2.超出边界移除

``       <canvas id="canvas" width="400" height="400" style="background:#000;">            your browser not support canvas        </canvas>        <p id="log"></p>         <script src="../js/utils.js"></script>         <script src="../js/ball.js"></script>         <script>             window.onload = function(){                 var canvas = document.getElementById("canvas"),                     context = canvas.getContext("2d"),                     log = document.getElementById("log");                  var balls = [],                     numBall = 10,                     canWid = canvas.width,                     canHei = canvas.height;                  //定义10个小球                 for(var i=0; i<numBall; i++){                     var size = Math.random()*20 + 5,   //颜色                         color = Math.random()*(0xffffff),   //大小                         ball = new Ball(size, color);                      ball.id = "ball_" + i;   //给每个小球一个id                     ball.radius = Math.random()*30+10;                     ball.x = Math.random()*canWid;                     ball.y = Math.random()*canHei;                     ball.vx = Math.random()*2 - 1;                     ball.vy = Math.random()*2 - 1;                      balls.push(ball); //push进数组                 }                  //定义draw函数                 function draw(ball, pos){                       //让小球加上它的速度值                       ball.x += ball.vx;                       ball.y += ball.vy;                        //判断是否超出边界，不论超出哪一边                       if(ball.x - ball.radius > canvas.width ||                          ball.radius+ball.x <0 ||                          ball.y - ball.radius > canvas.height ||                          ball.y+ball.radius < 0){                          //将超出边界的小球从数组中删除                           balls.splice(pos, 1);                           if(balls.length > 0){                               //将超出的小球的id值输出                               log.innerHTML += "移除" + ball.id + "<br/>";                           }else{                               log.innerHTML = "全部移除";                           }                       }                      ball.draw(context);                   }                  //动画循环                 (function drawFrame(){                     window.requestAnimationFrame(drawFrame, canvas);                     context.clearRect(0, 0, canvas.width, canvas.height);                      //定义初始变量 i 为小球的数量, 并且会随着小球的移除减小                     var i = balls.length;                     while(i--){                         draw(balls[i], i);                     }                 }());             }         </script>``

### 3.超出边界重新形成

``     function draw(ball, pos){                       ...                       if(边界超出判定){                           //超出了重置速度与坐标                           ball.x = canvas.width/2;                           ball.y = canvas.height;                           ball.vx = Math.random()*(2) - 1;                           ball.vy = Math.random()*(-2) - 1;                       }                    ...                   }      (function drawFrame(){                     window.requestAnimationFrame(drawFrame, canvas);                     context.clearRect(0, 0, canvas.width, canvas.height);                     balls.forEach(draw);                 }()); ``

### 3.边界环绕

``    <canvas id="canvas" width="500" height="500" style="background:#000;">            your browser not support canvas!        </canvas>        <script src="../js/utils.js"></script>        <script src="../js/spaceship.js"></script>        <script>            window.onload = function(){                var canvas = document.getElementById("canvas"),                    context = canvas.getContext("2d");                 var ship = new SpaceShip();                    ship.x = canvas.width/2;                    ship.y = canvas.height/2;                 var vr = 0,                    vx = 0,                    vy = 0,                    ax = 0,                    ay = 0,                    angle = 0,                    thrust = 0;                 window.addEventListener("keydown", function(event){                    switch (event.keyCode){                        case 37:                            vr = -3;                            break;                        case 39:                            vr = 3;                            break;                        case 38:                            ship.showFlame = true;                            thrust = 0.05;                            break;                        case 40:                            thrust -= 0.02;                            break;                          }                }, false);                window.addEventListener("keyup", function(event){                    vr = 0;                    thrust = 0;                    ship.showFlame = false;                }, false);                 (function drawFrame(){                    window.requestAnimationFrame(drawFrame, canvas);                    context.clearRect(0, 0, canvas.width, canvas.height);                     angle += vr * Math.PI/180                    ship.rotation = angle;                    ax = Math.cos(angle)*thrust;                    ay = Math.sin(angle)*thrust;                     vx += ax;                    vy += ay;                     ship.x += vx;                    ship.y += vy                                        //核心部分                    if(ship.x - ship.width/2 > canvas.width){                        ship.x = 0;                    }                    if(ship.x < 0){                        ship.x = canvas.width;                    }                    if(ship.y - ship.height/2> canvas.height){                        ship.y = 0;                    }                    if(ship.y <0){                        ship.y = canvas.height;                    }                     ship.draw(context);                }())            }        </script>``

### 4.边界反弹

ok！本章的重头戏来了，标题的意思已经很明白了，我们要让物体触碰到边界的时候反弹回来。就像真实的世界中一样，球体撞到墙上反弹回来。有了前面的铺垫，要实现这个效果那还不是分分钟的事情！一样的套路,先上效果图：

``       <canvas id="canvas" width="400" height="300" style="background:#000;">            your browser not support canvas!        </canvas>        <script src="../js/utils.js"></script>        <script src="../js/ball.js"></script>        <script>          window.onload = function(){              var canvas = document.getElementById("canvas"),                  context = canvas.getContext("2d");               var vx = Math.random()*10 - 5;              var vy = Math.random()*10 - 5;               var ball = new Ball(20, "#ff0000");                  ball.x = canvas.width/2;                  ball.y = canvas.height/2;                              //动画循环              (function drawFrame(){                  window.requestAnimationFrame(drawFrame, canvas);                  context.clearRect(0, 0, canvas.width, canvas.height);                   ball.x += vx;                  ball.y += vy;                                   //核心部分                  if(ball.x + ball.radius > canvas.width){                      ball.x = canvas.width - ball.radius;                      vx *= -1;                  }else if(ball.x - ball.radius < 0){                      ball.x = ball.radius;                      vx *= -1;                  }                  if(ball.y + ball.radius > canvas.height){                      ball.y = canvas.height - ball.radius;                      vy *= -1;                  }else if(ball.y - ball.radius < 0){                      ball.y = ball.radius;                      vy *= -1;                  }                   ball.draw(context);              }())          }``

``   var bounce = -1;     if(ball.x + ball.radius > canvas.width){            ball.x = canvas.width - ball.radius;            vx *= bounce;     }else if(ball.x - ball.radius < 0){            ball.x = ball.radius;            vx *= bounce;     }     if(ball.y + ball.radius > canvas.height){           ball.y = canvas.height - ball.radius;           vy *= bounce;     }else if(ball.y - ball.radius < 0){           ball.y = ball.radius;           vy *= bounce;     }    ``