Search code examples
javascriptcanvasprocessingdrawingp5.js

Rotating and drawing on a p5.js canvas


I am trying to draw on a rotating p5.js canvas, where the canvas element is being rotated via its transform CSS attribute. The user should be able to draw points on the canvas with the cursor, even while the canvas element is actively rotating.

The below code is what I have tried so far. However, it is currently not working, because the points are not correctly showing up where the mouse is hovering over the rotating canvas. I'm currently testing this out on the p5.js editor.

let canvas

function setup() {
  canvas = createCanvas(400, 400)
  background('#fb88f3')
  strokeWeight(10)
}

function draw() {
  canvas.style(`transform: rotate(${frameCount}deg)`)

  translate(200, 200)
  rotate(-radians(frameCount))
  
  point(mouseX-200, mouseY-200)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>

I've found this related StackOverflow post where they drew on a rotating canvas as a p5.Graphics element. However, for my purposes, I'd like to rotate the actual element instead, as part of a simple p5.js painting application I am working on.

I've been stuck on this for a while and would appreciate any help! Thanks in advance!


Solution

  • This seems to be a bug in p5.js.

    The mouse coordinate seems to depend on the size of the bounding box of the canvas. The bounding box depends on the rotation. Therefor you need to scale the offset for the calculation of the center of the canvas.
    Unfortunately, that's not all. All of this does not depend on the current angle, but on the angle that was set when the mouse was last moved. Hence the scale needs to be computed in the mouseMoved callback:

    let scale;
    
    function mouseMoved() {
      let angle_rad = radians(frameCount)
      scale = abs(sin(angle_rad)) + abs(cos(angle_rad))
    }
    
    let center_offset = 200 * scale;
    point(mouseX-center_offset, mouseY-center_offset)
    

    let canvas, scale
    
    function setup() {
      canvas = createCanvas(400, 400)
      background('#fb88f3')
      strokeWeight(10)
    }
    
    function draw() {
      
      let angle = frameCount;
      let angle_rad = radians(angle)
      let center_offset = 200 * scale
      
      canvas.style(`transform: rotate(${angle}deg)`)
    
      translate(200, 200)
      rotate(-angle_rad)
      
      point(mouseX-center_offset, mouseY-center_offset)
    }
    
    function mouseMoved() {
      let angle_rad = radians(frameCount)
      scale = abs(sin(angle_rad)) + abs(cos(angle_rad))
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>