Search code examples
p5.jsrectangles

p5.js draw a rectangle at cursor position on mouse click


I have a very simple 9x9 grid. I know how to handle the rectangles on this grid. What I want is when I click on one of the grid rectangles, this rectangle should now be marked with a fill or border around it.

I can draw a rectangle, with a blue fill at exact the correct rectangle on the grid.

But with the next click on the grid, the new rectangle is drawn but the old rectangle is still there and will stay there. And so on.

My question is now, how can I paint always exact on rectangle at the click position?

Is maybe a class the right way?

Creating every time a new rectangle and destroy the old one?

var nullx = 140;
var nully = 50;

var breite = 65;
var hoehe = 65;

var pressed = false;

function setup() {
  createCanvas(800, 1200);  
}

function draw() {
  //background(220);
  noFill();
  //strokeWeight(2);
  
  sudokulines(); 
  numberstorect();
  if(pressed == true){
    sqMark();      
  }
  
  if (mousePressed == true){
    console.log("click...")
    sqMark();
  }
}

function mousePressed(){
  pressed = true;
}

function sqMark(){  
  var tempX;
  var tempY;
  //console.log(tempX,tempY);
  tempX = (floor((mouseX - nullx) / breite) * breite) + nullx;
  tempY = (floor((mouseY - nully) / hoehe) * hoehe) + nully;
  console.log(tempX,tempY);
  if (tempX > 139 && tempY > 49 ){
    if (tempX < 661 && tempY < 571){
      strokeWeight(0.7);
      fill(0,0,255);
      rect(tempX+2,tempY+2,breite-4,hoehe-4);
      pressed = false;
    }    
  }
}

function sudokulines(){  
  //The vertical lines
  for (var i = 1; i <= 8; i++){
    if (i == 3 || i == 6){
      strokeWeight(3);
    }else{
      strokeWeight(1);
    }
    line(nullx + breite * i, nully, nullx + breite * i, nully+ 9*hoehe);
  }
  //The horizontal lines
  for (var i = 1; i <= 8; i++){
    if (i == 3 || i == 6){
        strokeWeight(3);
      }else{
        strokeWeight(1);
      }      
    //The big rectangle around
    line(nullx , nully + hoehe * i, nullx + 9*breite, nully + hoehe * i);    
  }

  strokeWeight(3);
  rect(nullx,nully,9*breite,9*hoehe);
}

function numberstorect(){
  textAlign(CENTER,CENTER);
  fill(0);
  textSize(breite/1.3);
  text(2,nullx + breite/2, nully + hoehe/2);
}

Solution

  • It's important to understand that p5.js draws in immediate mode, so each element, once drawn, is not removable unless intentionally drawn over or cleared. This simplest solution to your specific problem is to simply save to location to be highlighted when the user presses the mouse, and then always clear the canvas and redraw everything (including the selected square) in the draw function. Because there's no animation, you can optimize this by disabling looping in your setup function, and then explicitly calling redraw when something happens that effects the display (i.e. the mouse is pressed).

    var nullx = 140;
    var nully = 50;
    
    var breite = 65;
    var hoehe = 65;
    
    let selectedX = -1;
    let selectedY = -1;
    
    function setup() {
      createCanvas(800, 1200);
      // By default don't re draw every frame
      noLoop();
    }
    
    function draw() {
      background(255);
      noFill();
      //strokeWeight(2);
    
      sudokulines();
      numberstorect();
      sqMark();
    }
    
    function mousePressed() {
      // Set the selection
      selectedX = (floor((mouseX - nullx) / breite) * breite) + nullx;
      selectedY = (floor((mouseY - nully) / hoehe) * hoehe) + nully;
      // Only redraw when something changes.
      redraw();
    }
    
    function sqMark() {
      if (selectedX > 139 && selectedY > 49) {
        if (selectedX < 661 && selectedY < 571) {
          strokeWeight(0.7);
          fill(0, 0, 255);
          rect(selectedX + 2, selectedY + 2, breite - 4, hoehe - 4);
          pressed = false;
        }
      }
    }
    
    function sudokulines() {
      //The vertical lines
      for (var i = 1; i <= 8; i++) {
        if (i == 3 || i == 6) {
          strokeWeight(3);
        } else {
          strokeWeight(1);
        }
        line(nullx + breite * i, nully, nullx + breite * i, nully + 9 * hoehe);
      }
      //The horizontal lines
      for (var i = 1; i <= 8; i++) {
        if (i == 3 || i == 6) {
          strokeWeight(3);
        } else {
          strokeWeight(1);
        }
        //The big rectangle around
        line(nullx, nully + hoehe * i, nullx + 9 * breite, nully + hoehe * i);
      }
    
      strokeWeight(3);
      rect(nullx, nully, 9 * breite, 9 * hoehe);
    }
    
    function numberstorect() {
      textAlign(CENTER, CENTER);
      fill(0);
      textSize(breite / 1.3);
      text(2, nullx + breite / 2, nully + hoehe / 2);
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>