[canvas]小球边界反弹

345 阅读1分钟

QQ录屏20220830183630_.gif

先绘制一个小球

小球的大小,颜色等定义

ball.js

class Ball {
  constructor(props) {
    this.x = 0;
    this.y = 0;
    this.r = 20;
    //设置小球的横向速度和纵向速度
    this.vx = 0;
    this.vy = 0;
    //横向缩放倍数
    this.scaleX = 1;
    //纵向缩放倍数
    this.scaleY = 1;
    this.strokeStyle = 'rgba(1,0,0,0)';
    this.fillStyle = 'rgba(57,119,224)'
    this.alpha = 1
    Object.assign(this, props);
    return this;
  }
  render(ctx) {
    let { x, y, r, scaleX, scaleY, fillStyle, strokeStyle, alpha } = this;
    ctx.save();
    ctx.translate(x, y);
    ctx.scale(scaleX, scaleY);
    ctx.strokeStyle = strokeStyle;
    ctx.fillStyle = fillStyle;
    ctx.globalAlpha = alpha;
    ctx.beginPath()
    ctx.arc(0, 0, r, 0, 2 * Math.PI);
    ctx.fill();
    ctx.stroke();
    ctx.restore();
    return this
  }
}
​

工具类

utils.js

let C = {};
//获取鼠标在元素上的坐标
C.getOffset = function(ele){
  let mouse = {x: 0,y: 0};
  ele.addEventListener('mousemove',function(e){
  let {x,y} = C.eventWrapper(e);
  mouse.x = x;
  mouse.y = y;
  })
  return mouse;
};
//坐标系转换
C.eventWrapper = function (ev){
  let {pageX,pageY,target} = ev;
  let {left,top} = target.getBoundingClientRect();
  return {x: pageX - left,y:pageY - top};
  };
 //角度转弧度
 C.toRad = function (angle){
   return angle * Math.PI / 180;
 };
 //弧度转角度
 C.toAngle = function(rad){
 return rad * 180 / Math.PI
 };
​
 //封装一下生成随机数
 //两个参数,第一个是数组,第二个是是否是整数
​
 C.rp = function(arr,int){
   const max = Math.max(...arr);//调用:C.rp([10,20],true);有true传的就是随机的整数,没有传的就是随机的小数
   const min = Math.min(...arr);
   //...将数组展开
   const num = Math.random()*(max-min)+min;
   return int ? Math.round(num):num;
 };
​
 //生成随机数颜色
 C.createColor = function(){
   return `rgb(${C.rp([55,255],true)},${C.rp([55,255],true)},${C.rp([55,255],true)})`;
 }
​

越界处理

小球碰到边界会反弹

image-20220830191124673

源码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  body,html {
    margin:0;
    height:100%;
  }
  #canvas{
    box-shadow: 4px 4px 12px rgba(0, 0, 0, 0.5);
    position: absolute;
    top: 10%;
    left: 5%;
  }
</style>
<body>
<canvas id="canvas"></canvas>
<script src="/js/ball.js"></script>
<script src="/js/utils.js"></script>
<script>
  const canvas = document.getElementById('canvas')
  const ctx=canvas.getContext('2d');
​
  let W = canvas.width = 800;
  let H = canvas.height = 600;
  let balls=[];
  for(let i=0;i<10;i++){
    balls.push(new Ball({
      r:C.rp([30,70]),
      vx:C.rp([-5,5]),
      vy:C.rp([-6,7])
    }))
  }
  function ballMove(ball){
    ball.x+=ball.vx;
    ball.y+=ball.vy;
​
    //越接处理
    if(ball.x-ball.r<=0){
      ball.x=ball.r;
      ball.vx*=-1;
    }
    if(ball.x+ball.r>=W){
      ball.x=W-ball.r;
      ball.vx*=-1
    }
    if(ball.y-ball.r<=0){
      ball.y=ball.r;
      ball.vy*=-1;
    }
    if(ball.y+ball.r>=H){
      ball.y=H-ball.r;
      ball.vy*=-1
    }
​
    ball.render(ctx)
  }
​
​
  (function move(){
    window.requestAnimationFrame(move);
    ctx.clearRect(0,0,W,H);
    balls.forEach(ballMove)
  })()
​
 </script>
</body>
</html>

\