Search code examples
javascriptprocessingdrawingp5.js

Arrow Line Brush in P5.js


I am currently making a brush in p5.js

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

function draw() {
 
  if(mouseIsPressed){
    
        stroke(255);
    fill(0);

   
    strokeWeight(30);
    triangle(mouseX, mouseY, pmouseX, pmouseY);
    stroke(0);
    strokeWeight(25);
    triangle(mouseX, mouseY, pmouseX, pmouseY);

  }
}
<!DOCTYPE html><html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/addons/p5.dom.min.js"></script> <link rel="stylesheet" type="text/css" href="style.css"> <meta charset="utf-8" /> </head><body> <script src="sketch.js"></script> </body>  </html>

This is how it currently looks like enter image description here

However, I would like to add a triangle at the end like this enter image description here

Would that be possible? Any suggestions are welcome!

Thank you :)


Solution

  • In order to draw your arrow head you will need to draw the desired triangle when the mouse is released. P5.js will call various input event functions when the user performs input actions and one such function is mouseReleased(). Here is an example of drawing arrow heads in the mouseReleased function.

    function setup() {
      createCanvas(400, 400);
      background(255)
    }
    
    function draw() {
      if (mouseIsPressed) {
        stroke(255);
        fill(0);
    
        // These calls to triangle were unusual, and seemed to be mostly working by accident
        //strokeWeight(30);
        //triangle(mouseX, mouseY, pmouseX, pmouseY);
        stroke(0);
        strokeWeight(25);
        //triangle(mouseX, mouseY, pmouseX, pmouseY);
        line(mouseX, mouseY, pmouseX, pmouseY);
      }
    }
    
    function mouseReleased() {
      // When the user releases the mouse button, draw an arrow head
      
      // Save the stroke/fill/translate/rotate state
      push();
      
      noStroke();
      fill(0);
      // Find the angle of the direction the mouse has been recently
      // moving in
      let angle = atan2(mouseY - pmouseY, mouseX - pmouseX);
      // Translate to the current mouse position
      translate(mouseX, mouseY);
      // Rotate so that the positive x direction is in the direction
      // the mouse was moving.
      rotate(angle);
      
      // Draw a triangle pointing in the positive x direction.
      triangle(
        0, -25,
        50, 0,
        0, 25
      );
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="utf-8" />
      <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.min.js"></script>
    </head>
    
    <body>
    </body>
    
    </html>

    Note: the behavior of this implementation is only as good as the behavior of pmouseX and pmouseY. Because of the way these properties work the direction of the arrow will be affected by small movements just before the mouse is released as well as suboptimal behavior when the mouse is stationary. To get better results you could come up with your own methodology to track mouse direction in the mouseMoved() function.