Trying to get responsive window and shapes using p5.js - javascript

I'm making my way through JavaScript tutorials (using p5.js) and was interested in coding a responsive screen with four shapes that scale down and stick next to each other while doing so.
Is defining a separate variable for y enough, or would it be better to redefine all the shapes by a new set of x and y variables? Window height/width seems like it should be the correct code to use.
My code:
function setup() {
createCanvas(window.innerWidth, window.innerHeight);
}
function draw() {
background(200);
noStroke();
var labelw = window.innerWidth/8;
var labelh = labelw/4;
var sectionw = window.innerWidth;
var sectionh = window.innerHeight;
// Red
if(window.innerWidth/2 < window.innerHeight){
fill(200, 50, 50);
rect(0, 0, sectionw/2, sectionw/4)
}
// Blue
if(window.innerWidth/2 < window.innerHeight){
fill(50, 50, 200);
rect(sectionw/2, 0, sectionw/2, sectionw/4)
}
// Green
if(window.innerWidth/2 < window.innerHeight){
fill(130, 230, 130);
rect(0, sectionh/2, sectionw/2, sectionw/4)
}
// Purple
if(window.innerWidth/2 < window.innerHeight){
fill(190, 100, 230);
rect(sectionw/2, sectionh/2, sectionw/2, sectionw/4)
}
// label1
fill(50)
rect(0, 0, labelw, labelh)
fill(255);
textSize(labelw/10);
text("Test Label\nTestIdeo, 19xx-20xx",0, 0, 200, 200);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.16/p5.js"></script>
<html>
<head></head>
<body></body>
</html>

You need to do two things:
First, you need to detect when the screen is resized, and resize the canvas when that happens. The windowResized() and resizeCanvas() functions come in handy for that. See the reference for more info.
Second, you just need to use the width and height variables to draw your shapes. The width and height variables are automatically updated when you resize the canvas.
Putting it all together, it would look like this:
function setup() {
createCanvas(windowWidth, windowHeight);
}
function draw() {
fill(255, 0, 0);
rect(0, 0, width/2, height/2);
fill(0, 255, 0);
rect(width/2, 0, width/2, height/2);
fill(0, 0, 255);
rect(0, height/2, width/2, height/2);
fill(255, 255, 0);
rect(width/2, height/2, width/2, height/2);
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}

Related

Making smaller version of canvas an objects in p5.js

So I am trying to make a exact smaller scale version of my canvas and sprites in p5.js and fit it in a box. Is there a function or way I can do this? The background, colors, and images of the sprites should be the same.
I don't know how p5.play works, but I'm guessing that the copy() command (reference) will do what you're looking for. To put the minimap in the bottom corner, you might do something like this:
function draw() {
//whatever is currently in your draw loop...
let minimapWidth = 50;
let minimapHeight = 50;
copy(0, 0, width, height,
width-minimapWidth,
height-minimapHeight,
minimapWidth, minimapHeight
);
}
There are two ways to do this, one way is to draw everything to a p5.Graphics buffer and the draw that buffer to your main canvas twice with different destination sizes. The other way is to do the main part of your drawing directly to your canvas, and then use the pixels array to create a p5.Image from the content of your canvas and then draw that to the canvas with the image function.
Example 1. p5.Graphics
let graphics;
function setup() {
createCanvas(windowWidth * 0.9, windowHeight * 0.9);
graphics = createGraphics(width, height);
graphics.background(100);
}
function draw() {
graphics.ellipse(mouseX, mouseY, 50, 50);
image(graphics, 0, 0, width, height, 0, 0, graphics.width, graphics.height);
// Draw picture in picture
let aspect = width / height;
image(graphics, 10, 10, 100, 100 / aspect, 0, 0, graphics.width, graphics.height);
push();
noFill();
strokeWeight(3);
rect(10, 10, 100, 100 / aspect);
pop();
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
</body>
</html>
Example 2. pixels & image
Note: this option has the disadvantage of being more complicated, waaay slower, and it doesn't support persistently drawn content as well as the p5.Graphics option because it displays itself on subsequent frames.
let img;
let density;
function setup() {
createCanvas(round(windowWidth * 0.9), round(windowHeight * 0.9));
density = pixelDensity();
img = createImage(width, height);
img.loadPixels();
background(100);
}
function draw() {
ellipse(mouseX, mouseY, 30, 30);
loadPixels();
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
let srcPixel = y * 4 * width * density ** 2 + x * 4 * density;
let dstPixel = y * 4 * img.width + x * 4;
for (let channel = 0; channel < 4; channel++) {
img.pixels[dstPixel + channel] = pixels[srcPixel + channel];
}
}
}
img.updatePixels();
// Draw picture in picture
let aspect = width / height;
image(img, 10, 10, 100, 100 / aspect, 0, 0, img.width, img.height);
push();
noFill();
strokeWeight(3);
rect(10, 10, 100, 100 / aspect);
pop();
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
</head>
<body>
</body>
</html>

Rotate rectangle around center on mouse drag

I want to make a rectangle rotate around its center as in this code. The problem is that the rectangle rotates on mouse drag on any area.
I want the rectangle to rotate on its position when the mouse drags it only not any mouse drag rotates it.
I am using the p5.js library.
If there any code that rotates rectangle around its center on the mouse drag that please share it with me.
Link of code: https://editor.p5js.org/jwglazebrook/sketches/p2pnhPSZE
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;
}
Code of 2 circle
let angle = 0.6;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(204, 226, 225); // Light blue color
fill(204, 226, 225); // Blue color
push();
translate(150, 150);
rotate(angle);
circle(-50,0,100);
circle(50,0,100);
pop();
line(100, 100, 200, 200);
}
function mouseDragged() {
m_angle = atan2(mouseY - 150, mouseX - 150);
angle = m_angle;
}

How to draw line slowly from a point to another point in P5?

I am using p5.js to draw a simple line.
function setup() {
//createCanvas(windowWidth, windowHeight);
createCanvas(400, 200);
}
function draw() {
background(255, 255, 255);
fill(255, 0, 0);
stroke(255, 0, 0);
strokeWeight(1);
line(0, 0, 250, 100);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
But the line drawn suddenly at once.
How can I draw the line slowly / gradually? (i.e in 300 milliseconds).
That it looks like animating from point(0,0) to point(250,100).
I had a quick look at p5 and it looks like it calls the draw method at intervals. If you want movement to happen you just need to program it.
I've put together a quick example below. I think it's drawing a lot slower than you want but I'm not sure how often p5 calls draw.
var position = 0,
end = 300;
function setup() {
//createCanvas(windowWidth, windowHeight);
createCanvas(400, 200);
}
function draw() {
background(255, 255, 255);
fill(255, 0, 0);
stroke(255, 0, 0);
strokeWeight(1);
var xEnd = 250,
yEnd = 100;
// Got to the end yet?
if (position < end) {
// Work out positions.
xEnd = (xEnd / end) * position;
yEnd = (yEnd / end) * position;
}
line(0, 0, xEnd, yEnd);
// Increment position.
position++;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
FrameRate can be used to adjust the speed of a drawing. This sketch draws a diagonal line that begins slowly at point 0,0 and then speeds up until it reaches point 250, 100.
var x = 0;
function setup() {
createCanvas(400, 200);
frameRate(10);
}
function draw() {
background(255, 255, 255);
fill(255, 0, 0);
stroke(255, 0, 0);
strokeWeight(1);
// y = mx + b
line(0, 0, x, 100/250*x);
x++;
if (x > 50){
frameRate(30);
}
if (x > 250){
noLoop();
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.min.js"></script>

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
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
}

Skew transformation HTML5 canvas

I'm trying to implement skew transformation using the "x" axis with HTML5 canvas, but my code fails... Here is my JavaScript:
function init() {
var canvas = document.getElementById('skewTest'),
context = canvas.getContext('2d'),
angle = Math.PI / 4;
img = document.createElement('img');
img.src = 'img.gif';
img.onload = function () {
context.setTransform(1, Math.tan(angle), 1, 1, 0, 0);
context.clearRect(0, 0, 200, 200);
context.drawImage(img, 0, 0, 100, 100);
}
}
I'll be very glad if I see working example in JsFiddle.
Thank you in advance!
The correct matrix of skewing in only one direction is
context.setTransform(1, Math.tan(angle), 0, 1, 0, 0);
// ^
With the number at ^ being 1, you are skewing the image in the y-direction by 45° as well.
Sample: http://jsbin.com/etecay/edit#html,live
Canvas can't support direct transform; instead use the below code:
ctx.lineWidth = 100;
ctx.strokeStyle = "rgba(255, 255, 255, 0.5)";
ctx.strokeRect(0, 0, 640, 480);
ctx.lineWidth = 4;
ctx.strokeStyle = "#5E81AB";
ctx.strokeRect(50, 50, 540, 380);

Categories

Resources