Search code examples
javascriptrotationprocessingangle

Use mouse to rotate a rectangle


I have the rectangle pointing at the mouse. What I want: when I lift the mouse and click and drag that the rectangle rotates further.

Or that I can click on any corner to rotate the rectangle. Just like you would with your finger and a sheet of paper.

let angle = 0;

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(220);

  push();
  translate(150, 150);
  rotate(angle);

  stroke(0);
  strokeWeight(2);
  rect(-100, -75, 200, 150);

  stroke(255, 0, 0);
  strokeWeight(5);
  line(-100, -75, 100, -75);

  stroke(0, 255, 0);
  point(0, 0);

  pop();
}

function mouseDragged() {
  m_angle = atan2(mouseY - 150, mouseX - 150);
  angle = /* MAGIC FORMULA HERE */ m_angle;
}

https://editor.p5js.org/jwglazebrook/sketches/p2pnhPSZE


Solution

  • The Problem:

    The issue with your code is that you need to store the offset from the initial mouse click to the new dragged point.

    The Solution:

    To fix the jerky behavior we just have to store the previous mouse angle and box angle and compare the difference with the dragged mouse angle.

    The Code:

    let angle = 0;
    
    function setup() {
      angleMode(DEGREES);
      createCanvas(400, 400);
    }
    
    function draw() {
      background(220);
    
      push();
      translate(150, 150);
      rotate(angle);
    
      stroke(0);
      strokeWeight(2);
      rect(-100, -75, 200, 150);
    
      stroke(255, 0, 0);
      strokeWeight(5);
      line(-100, -75, 100, -75);
    
      stroke(0, 255, 0);
      point(0, 0);
    
      pop();
    }
    
    let c_angle = 0;
    let q_angle = 0;
    
    function mousePressed() {
      c_angle = atan2(mouseY - 150, mouseX - 150); //The initial mouse rotation
      q_angle = angle; //Initial box rotation
    }
    
    function mouseDragged() {
      m_angle = atan2(mouseY - 150, mouseX - 150);
    
      let dangle = m_angle - c_angle; //How much the box needs to be rotated
      if (dangle>=360) dangle-=360; //clamping
      if (dangle<0) dangle+=360; //clamping
      angle =  q_angle + dangle; //Apply the rotation
      if (angle>=360) angle -= 360; //clamping
    }