【问题标题】:unexpected behavior during a rotation animation on canvas画布上旋转动画期间的意外行为
【发布时间】:2017-01-27 23:56:12
【问题描述】:

我一直在研究一些关于动画的研究,并且在一些 jquery 的帮助下,我创建了一个动画,当用户通过 mousemove jquery 事件移动的方块与屏幕上的另一个方块发生碰撞时(被击中的 square2) 将移动一定的长度,如果命中框在其边缘附近被击中,则对象预计会旋转。我遇到的问题是,当对象旋转时,它会产生正方形轮廓的伪残像。起初我认为我可以通过使用 clearRect() 方法来删​​除 afterImage 以包含 square2 周围的更大区域,但这样做不仅使我的问题无法解决,而且还会使我的第一个正方形的一部分不可见,这是不希望的。如果有人能帮我弄清楚我在这段代码中哪里出错了,我会很感激的。

    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();

【问题讨论】:

    标签: javascript animation canvas


    【解决方案1】:

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

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

    您正在这里绘制第二个形状。注释这行,伪图像应该消失了。

    【讨论】:

    • hmm 现在这很有趣,回顾一下代码确实有道理,因为我无论如何都在 drawImagerot 函数中绘制了正方形。非常感谢!
    猜你喜欢
    • 2014-02-02
    • 2017-08-06
    • 2013-04-06
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 1970-01-01
    • 2014-02-01
    相关资源
    最近更新 更多