画布上旋转动画期间的意外行为

时间:2016-09-20 07:00:20

标签: javascript animation canvas

我一直在用动画进行一些研究,在一些jquery的帮助下,我创建了一个动画,当用户鼠标移动到鼠标移动jquery事件的方块与另一个方块碰撞时被击中的屏幕(square2)将移动一定长度,如果击中它的边缘附近击中了比预期旋转的对象。我遇到的问题是,当对象旋转时,它会创建正方形轮廓的伪余像。起初我以为我可以通过使用clearRect()方法来移除afterImage,以包含square2周围的更大区域,但这样做不仅使我的问题得不到解决,而且还使我的第一个方块的一部分不可见,这是不希望的。如果有人能解释我在这段代码中出错的地方,肯定会很感激它。[/ p>

    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    canvas.width = 1000;
    canvas.height = 400;
    var width = canvas.width;
    var height = canvas.height;
    var particles = [];

    var mouseSize = 50;
    var isColliding = false;
    var mouseX;
    var mouseY;
    var animationForward = false;

    function particle() {
      var particle = {
        originX: width / 2,
        originY: height / 2,
        x: width / 2,
        y: height / 2,
        size: 30,
        centerPointX: this.x + this.size / 2,
        centerPointY: this.y + this.size / 2,
        decay: .98,
        vx: 0,
        vy: 0,
        rotate: 0,
        vr: 0,

        draw: function() {
          ctx.fillStyle = "white";
          ctx.fillRect(this.x, this.y, this.size, this.size)

          //           rotation logic
// method found at http://stackoverflow.com/questions/2677671/how-do-i-rotate-a-single-object-on-an-html-5-canvas
          function drawImageRot(x, y, width, height, deg) {
            ctx.clearRect(x, y, width, height);
            //Convert degrees to radian 
            var rad = deg * Math.PI / 180;
            //Set the origin to the center of the image
            ctx.translate(x + width / 2, y + height / 2);
            //Rotate the canvas around the origin
            ctx.rotate(rad);
            //draw the image    
            ctx.fillRect(width / 2 * (-1), height / 2 * (-1), width, height);
            //reset the canvas  
            ctx.rotate(rad * (-1));
            ctx.translate((x + width / 2) * (-1), (y + height / 2) * (-1));
          }

          //check for collision
          if (mouseX < particles[0].x + particles[0].size &&
            mouseX + mouseSize > particles[0].x &&
            mouseY < particles[0].y + particles[0].size &&
            mouseSize + mouseY > particles[0].y) {
            isColliding = true;
          } else {
            isColliding = false;
          }

          //controlling  velocity dependending on location of collision.
          if (isColliding) {
            //x axis
            animationForward = true;

            // checking below to see if mouseRect is hitting near the center of particleRect. 
            // if it hits near center the vy or vx will not be as high depending on direction and if it               //does not than we will make square rotate
            if (mouseX < this.x) {
              this.vr = 3 + Math.random() * 10
              if (mouseX + mouseSize / 2 > this.x) {
                this.vx = 0 + Math.random() * 2;
              } else {
                this.vx = 3 + Math.random() * 3;

              }
            } else {
              this.vr = -3 - Math.random() * 10
              if (mouseX + mouseSize / 2 < this.x + this.size) {
                this.vx = 0 - Math.random() * 2;
              } else {
                this.vx = -3 - Math.random() * 3;
              }
            }

            //y axis checking

            if (mouseY < this.y) {
              if (mouseY + mouseSize / 2 > this.y) {
                this.vy = 0 + Math.random() * 2;
              } else {
                this.vy = 3 + Math.random() * 3;
              }
            } else {
              if (mouseY + mouseSize / 2 < this.y + this.size) {
                this.vy = 0 - Math.random() * 2;
              } else {
                this.vy = -3 - Math.random() * 3;
              }
            }

          }

          //decay all motions each frame while animation is forward
          if (animationForward) {
            this.vx *= this.decay;
            this.vy *= this.decay;
            this.vr *= this.decay;
          }

          //when animation is done, set all velocities to 0
          if (this.x != this.originX && Math.abs(this.vx) < .1 && this.y != this.originY && Math.abs(this.vy) < .1) {
            animationForward = false;
            this.vx = 0;
            this.vy = 0;
            this.vr = 0
          }

          //x check to see if animation over. if it is slowly put square back to original location
          if (this.x != this.originX && !animationForward) {
            if (this.x > this.originX) {
              this.vx = -1;
            }
            if (this.x < this.originX) {
              this.vx = 1;
            }

            if (this.x > this.originX && this.x - this.originX < 1) {
              this.vx = 0;
              this.x = this.originX;
            }
            if (this.x < this.originX && this.originX - this.x < 1) {
              this.vx = 0;
              this.x = this.originX;
            }
          }
          //           end x collison

          //           y check to see if animation over

          if (this.y != this.originX && !animationForward) {
            if (this.y > this.originY) {
              this.vy = -1;
            }
            if (this.y < this.originY) {
              this.vy = 1;
            }

            if (this.y > this.originY && this.y - this.originY < 1) {
              this.vy = 0;
              this.y = this.originY;
            }
            if (this.y < this.originY && this.originY - this.y < 1) {
              this.vy = 0;
              this.y = this.originY;
            }
          }
          //           end y collison

          //check rotation

          if (this.rotate != 0 && !animationForward) {
            this.rotate = Math.round(this.rotate);

            if (this.rotate < 0) {
              if (this.rotate < -300) {
                this.rotate += 10
              } else if (this.rotate < -200) {
                this.rotate += 7
              } else if (this.rotate < -125) {
                this.rotate += 5
              } else if (this.rotate < -50) {
                this.rotate += 3
              } else {
                this.rotate++;
              }
            } else {
              if (this.rotate > 300) {
                this.rotate -= 10;
              } else if (this.rotate > 200) {
                this.rotate -= 7
              } else if (this.rotate > 125) {
                this.rotate -= 5
              } else if (this.rotate > 50) {
                this.rotate -= 3
              } else {
                this.rotate--;
              }
            }

          }

          // move the rect based off of previous set conditions and make square rotate if edges hit

          this.x += this.vx;
          this.y += this.vy;
          this.rotate += this.vr;
          drawImageRot(this.x, this.y, this.size, this.size, this.rotate);

          //           boundary control

          if (this.x + this.size > width || this.x < 0) {
            this.vx = -this.vx * 2
          }
          if (this.y + this.size > height || this.y < 0) {
            this.vy = -this.vy * 2
          }

        }
      }
      return particle;
    }

    function createParticles() {
      particles.push(particle())

      //wouldnt be too hard to put more particles. would have to go back and change the isColliding and animationForward global variable and make each object have their own to check. also would have to go back and implement for loops wherever i mention an element in my array
    }

    createParticles();

    function draw() {
      console.log(particles[0].rotate);
      ctx.clearRect(0, 0, width, height);

      ctx.fillStyle = 'white';
      ctx.fillRect(mouseX, mouseY, mouseSize, mouseSize);

      particles[0].draw();

      requestAnimationFrame(draw);
    }

    $("#canvas").mousemove(function(event) {
      mouseX = event.pageX;
      mouseY = event.pageY;
    })

    window.onload = draw();

1 个答案:

答案 0 :(得分:0)

我认为你的问题就在这里:

   draw: function() {
      ctx.fillStyle = "white";
      ctx.fillRect(this.x, this.y, this.size, this.size)
      ....

你在这里画第二个形状。注释这一行和伪图像应该不见了。