Call function draw on mouse click - p5.js

Is it possible to call the function draw(){} in a p5 js sketch when clicking on the canvas?
I would like everything under the draw function to be called when clicking anywhere on the canvas, and not before.
function setup() {
createCanvas(500, 500);
frameRate(65);
background('#ff0a0a');
textSize(60);
text("ART", 370, 250);
};
function draw() {
noFill();
var red = random(100);
var green = random(200);
var blue =random(230);
var h = random(height);
stroke(red,green,blue);
strokeWeight(8);
rect(frameCount,h,300,20+(frameCount));
ellipse(frameCount,h ,300,20+(frameCount));
triangle(frameCount,h ,300,20+(frameCount));
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/p5.js"></script>

This works fine for me:
function setup() {
createCanvas(500, 500);
frameRate(65);
background('#ff0a0a');
textSize(60);
text("ART", 370, 250);
};
function mousePressed() {
noFill();
var red = random(100);
var green = random(200);
var blue =random(230);
var h = random(height);
stroke(red,green,blue);
strokeWeight(8);
rect(frameCount,h,300,20+(frameCount));
ellipse(frameCount,h ,300,20+(frameCount));
triangle(frameCount,h ,300,20+(frameCount));
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/p5.js"></script>

Just to mention another way and to address your question in Kevin's answer above, you can do something like this to draw continuously when the mouse is clicked once and stop when it is clicked again. This would work like a toggle switch for drawing :-
var drawThings;
function setup() {
createCanvas(500, 500);
frameRate(65);
background('#ff0a0a');
textSize(60);
text("ART", 370, 250);
}
function draw() {
if (drawThings) {
noFill();
var red = random(100);
var green = random(200);
var blue = random(230);
var h = random(height);
stroke(red, green, blue);
strokeWeight(8);
rect(frameCount, h, 300, 20 + (frameCount));
ellipse(frameCount, h, 300, 20 + (frameCount));
triangle(frameCount, h, 300, 20 + (frameCount));
}
}
function mouseClicked() {
drawThings = !drawThings;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/p5.js"></script>

Related

How to show permanent afterimage effect in P5.js?

I'm making a new painting app for an assignment.
What I want for result is that if a user pressed mouse buttons, then white cream is put on the background images and shapes as permanent afterimage effect, following the movement of the mouse.
However when I pressed the mouse buttons, the background images came out as I intended, but the ones with the white cream didn’t work at all.
My current code is:
function setup() {
createCanvas(600,600);
frameRate(100);
}
function draw() {
background(80,30,0);
var size1 = 500;
fill(255);
noStroke();
ellipse(300, 300, size1, size1);
var size2 = 450;
fill(255,217,102);
noStroke();
ellipse(300, 300, size2, size2);
if (mouseIsPressed) {
fill(255,255,255);
noStroke();
triangle(mouseX,mouseY-28,mouseX-24,mouseY+16,mouseX+24,mouseY+16);
fill(255,255,255);
stroke(121,67,21);
strokeWeight(0.1);
triangle(mouseX-24,mouseY-16,mouseX+24,mouseY-16,mouseX,mouseY+28);
}
}
I don’t know what the problem is, and how to solve it.
Could you help me out?
Thank you.
P5.js link of this app is here : https://editor.p5js.org/jwyoon100/full/Kd4JRk87f
You need to move all the background images code into the setup() function, like this:
function setup() {
createCanvas(600,600);
frameRate(100);
background(80,30,0);
var size1 = 500;
fill(255);
noStroke();
ellipse(300, 300, size1, size1);
var size2 = 450;
fill(255,217,102);
noStroke();
ellipse(300, 300, size2, size2);
}
function draw() {
if (mouseIsPressed) {
fill(255,255,255);
noStroke();
triangle(mouseX,mouseY-28,mouseX-24,mouseY+16,mouseX+24,mouseY+16);
fill(255,255,255);
stroke(121,67,21);
strokeWeight(0.1);
triangle(mouseX-24,mouseY-16,mouseX+24,mouseY-16,mouseX,mouseY+28);
}
}

Hide and show background image when keyboard pressed, preserving overlay elements

I would like to paint ellipses over an image when clicking the mouse, and when I press the keyboard, hide and show the underneath image alternatively, without cleaning the ellipses.
I'm using createGraphics() to store the image data, and remove() so when the keyboard is pressed I spect the image disappear but it doesn't work
Here is a sketch of what I trying to do:
let isMouseBeeingPressed = false;
let img;
let isShow = true
let bufferImg;
function preload() {
img = loadImage(
"https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
);
}
function setup() {
createCanvas(500, 500);
background(255);
loadImageBuffer();
}
function loadImageBuffer() {
bufferImg = createGraphics(400, 400);
bufferImg.image(img, 0, 0);
image(bufferImg, 0, 0);
}
function draw() {
if(isMouseBeeingPressed) {
stroke(0, 0, 0, 50);
fill(255);
ellipse(mouseX, mouseY, 20);
}
}
function keyPressed() {
if(isShow) {
bufferImg.remove();
} else {
image(bufferImg, 0, 0);
}
console.log('isShow:', isShow);
return isShow = !isShow;
}
function mousePressed() {
isMouseBeeingPressed = true;
}
function mouseReleased() {
isMouseBeeingPressed = false;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Any idea of how to achieve this?
The best approach is probably to draw the ellipses to a separate buffer (p5.Graphics), and then draw that on top of the image or blank background as needed. An alternative approach would be to record the position of each ellipse in an array so that they can be redrawn. However, the latter approach will use more memory and switching the image on and off will have a noticeable delay after many ellipses have been drawn.
Approach #1 (render via p5.Graphics)
let img;
let graphics;
let isShow = true;
function preload() {
img = loadImage(
"https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
);
}
function setup() {
createCanvas(500, 500);
background(255);
image(img, 0, 0);
graphics = createGraphics(width, height);
}
function draw() {
if (mouseIsPressed) {
graphics.stroke(0, 0, 0, 50);
graphics.fill(255);
graphics.ellipse(mouseX, mouseY, 20);
background(255);
if (isShow) {
image(img, 0, 0);
}
image(graphics, 0, 0);
}
}
function keyPressed(e) {
isShow = !isShow;
background(255);
if (isShow) {
image(img, 0, 0);
}
image(graphics, 0, 0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Update: one thing to note about this approach is that whenever the mouse is pressed, the entire scene must be redrawn (white background, image if applicable, and foreground). The reason for this is antialiasing and transparency. When you draw an ellipse on the graphics buffer the edges will have some partially transparent pixels due to antialiasing. If you repeatedly draw the buffer as an overlay without redrawing what is behind it then the partially transparent pixels will become less and less transparent until they are sold black. This will cause your ellipses to have a slightly thicker and more pixelated outer edge.
Approach #2 (Array of ellipse positions)
let img;
let isShow = true
let positions = [];
function preload() {
img = loadImage(
"https://images.pexels.com/photos/20787/pexels-photo.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500"
);
}
function setup() {
createCanvas(500, 500);
background(255);
image(img, 0, 0);
}
function draw() {
if (mouseIsPressed) {
stroke(0, 0, 0, 50);
fill(255);
ellipse(mouseX, mouseY, 20);
positions.push([mouseX, mouseY]);
}
}
function keyPressed() {
isShow = !isShow;
background(255);
if (isShow) {
image(img, 0, 0);
}
stroke(0, 0, 0, 50);
fill(255);
for (const [x, y] of positions) {
ellipse(x, y, 20);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>

How do I create a line that recedes as you draw more in p5.js?

Currently working on a site that features some line drawing while hovering. How can I make the line recede naturally as you draw more? Right now I've figured out how to draw a continual line.
var canvas;
var button;
function windowResized() {
console.log('resized');
resizeCanvas(windowWidth, windowHeight);
}
function setup () {
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0,0);
canvas.style('z-index', '-1')
background(175);
// button = createButton("Start Your Walk");
}
function draw () {
strokeWeight(4);
console.log('button')
line(pmouseX, pmouseY, mouseX, mouseY)
}
You may store the values of your mouse position in an array and then draw the points of the array in order. When the array is updated, if it is full, you will have to erase the last point of the array, move all the points one position backwards and add the new point. The following would be an example code. I recomend you to consult this page for documentation and also the p5 reference.
var mousePositions = [];
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
v = createVector(mouseX, mouseY);
mousePositions.push(v);
noFill();
beginShape();
for(var i = 0; i < mousePositions.length; i++){
vertex(mousePositions[i].x, mousePositions[i].y);
}
endShape();
if(mousePositions.length > 25){
mousePositions.shift();
}
}

p5 resize window without clearing the background

The following code makes use of the p5dom add-on to position the canvas in the centre of the window. To dynamically resize the canvas I'm using the windowResized() function. I want to keep the background function in setup. How do I prevent the background colour from clearing when I resize the window? Many thanks.
var cnv;
function centerCanvas() {
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
}
function setup() {
cnv = createCanvas(windowWidth,windowHeight);
centerCanvas();
background(255, 0, 200);
}
function draw(){
}
function windowResized() {
centerCanvas();
resizeCanvas(windowWidth,windowHeight)
}
One thing you might do is draw everything to a buffer instead of directly to the screen. The createGraphics() function is your friend here. From the P5.js reference:
var pg;
function setup() {
createCanvas(100, 100);
pg = createGraphics(100, 100);
}
function draw() {
background(200);
pg.background(100);
pg.noStroke();
pg.ellipse(pg.width/2, pg.height/2, 50, 50);
image(pg, 50, 50);
image(pg, 0, 0, 50, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script>
You would want to draw everything to a buffer, and then when the screen is resized, redraw that buffer.
Simply by adding the background function to the draw one too.
Try this:
var cnv;
function centerCanvas() {
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
}
function setup() {
cnv = createCanvas(windowWidth,windowHeight);
centerCanvas();
background(255, 0, 200);
}
function draw(){
//HERE:
background(255, 0, 200);
}
function windowResized() {
//(you can add it here too...)
centerCanvas();
resizeCanvas(windowWidth,windowHeight);
}
I would simply set the background in the windowResized function.
function windowResized() {
centerCanvas();
resizeCanvas(windowWidth,windowHeight)
background(255, 0, 200);
}
For an alternative method, you could use CSS to edit the dimensions using something similar to the following:
<style>
canvas {
width: 100%;
height: 100%;
}
</style>

Draw line from one dot to another using mouse event

How can I use HTML5 canvas to simply connect two dots with one line using mouse? where I would click on the first dot and drag the mouse creating a line until it connects to the second dot.
I have been using x/y offset to follow the mouse but drawing a line is where I need help in.
Data array is the two dots
$scope.data = [
[192,27]
,[183,55]
];
function drawDot(event) {
if(dragging){
context.lineTo(event.offsetX, event.offsetY);
context.stroke();
context.beginPath();
context.arc(event.offsetX, event.offsetY,5, 0, Math.PI*2);
context.fill();
context.beginPath();
context.moveTo(event.offsetX, event.offsetY);
}
}
function engage(){
dragging = true;
drawDot(event);
}
function disengage(){
dragging = false;
context.beginPath();
}
function init(){
canvas.addEventListener("mousedown",engage);
canvas.addEventListener("mouseup",disengage);
canvas.addEventListener("mousemove",drawDot,false);
}
I am seeing a few things wrong here. Look at my example. I believe that is what you are looking for.
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d")
var startX = 0;
var startY = 0;
function drawDot(event) {
if(dragging){
context.clearRect(0,0,canvas.width, canvas.height)
context.beginPath();
context.moveTo(startX, startY);
context.lineTo(event.offsetX, event.offsetY);
context.arc(event.offsetX, event.offsetY,5, 0, Math.PI*2);
context.stroke();
context.closePath();
}
}
function engage(event){
dragging = true;
startX = event.offsetX;
startY = event.offsetY;
}
function disengage(){
dragging = false;
}
canvas.addEventListener("mousedown",engage);
canvas.addEventListener("mouseup",disengage);
canvas.addEventListener("mousemove",drawDot,false);
<canvas id="canvas" style="margin: 10px; background: blue"></canvas>

Resources