Reputation: 79
When I load the window from a narrow size and make it wider, the added canvas space is white.
Canvas resize from narrow to wide:
When I load from a larger window to a smaller size, the canvas stays in the larger size, while HTML and CSS elements respond. In the second picture, the circles are supposed to cut off at the same point at the black rectangle.
I think this is happening because the circles are randomly generated and the layout of them is different whenever the page loads/reloads. Basically, I have to "refresh" the window for the new resized canvas to work. BTW, I tried WindowResized() already.*
var font;
var colors;
var bolder;
var canvas;
setup = () => {
frameRate(2.5);
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '-1');
colors = [color(255, 0, 0), color(1, 130, 83), color(0, 0, 255), color(255, 255, 0), color(102, 0, 102), color(255, 107, 31)];
for (var c = 0; c < 1000; c++) {
var circle = {
x: random(width),
y: random(height),
r: random(90, 15)
};
var overlap = false;
var protection = 0;
for (var j = 0; j < circles.length; j++) {
var other = circles[j];
var d = dist(circle.x, circle.y, other.x, other.y);
if (d < circle.r + other.r) {
overlap = true;
}
}
if (!overlap) {
circles.push(circle);
}
protection++;
if (protection > 10000) {
break;
}
}
for (var i = 0; i < circles.length; i++) {
fill(255, 255, 255);
strokeWeight(4);
ellipse(circles[i].x, circles[i].y, circles[i].r * 2, circles[i].r * 2);
}
}
draw = () => {
for (var i = 0; i < circles.length; i++) {
if (mouseX > circles[i].x - circles[i].r && mouseX < circles[i].x + circles[i].r && mouseY > circles[i].y - circles[i].r && mouseY < circles[i].y + circles[i].r)
{
stroke(0, 0, 0);
fill(random(colors));
strokeWeight(4);
noStroke;
ellipse(circles[i].x, circles[i].y, circles[i].r * 2, circles[i].r * 2);
}
}
}
Upvotes: 1
Views: 996
Reputation: 51837
You are on the right track using windowResized() and resizeCanvas()
,
however you missed an important detail regarding scope:
windowResized()
function in your code, local only to setup()
windowResized()
as a sibling of setup()
/draw()
, overriding p5.js's default: same as the resizeCanvas example linked aboveThe second overlooked detail has to do with drawing:
draw()
you are not clearing the canvas (using background()
or something similar) which means you expect the circles drawn in setup()
to remain drawnresizeCanvas()
might clear the canvas as wellsetup()
in a function you can simple re-call again in windowResized()
The thirdpart, you guessed it, attention to details in code:
circles
at the top, nowever you've never initialized it to an empty array: this would cause an undefined
error trying to circles.push
()
when calling a function like noStroke()
function
you can, but it would make it easier to read/scan the code when it's uniform. (In the end you'll spend more time reading the code than writing it: make it easy for your future self to easily predict what your past self coded :) )Here's a modified version of your sketch with the points above addressed:
var font;
var colors;
var bolder;
var canvas;
var circles;
setup = () => {
frameRate(2.5);
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '-1');
colors = [color(255, 0, 0), color(1, 130, 83), color(0, 0, 255), color(255, 255, 0), color(102, 0, 102), color(255, 107, 31)];
setupCircles();
}
// group circle drawing functionality in a re-usable
setupCircles = () => {
circles = [];
for (var c = 0; c < 1000; c++) {
var circle = {
x: random(width),
y: random(height),
r: random(90, 15)
};
var overlap = false;
var protection = 0;
for (var j = 0; j < circles.length; j++) {
var other = circles[j];
var d = dist(circle.x, circle.y, other.x, other.y);
if (d < circle.r + other.r) {
overlap = true;
}
}
if (!overlap) {
circles.push(circle);
}
protection++;
if (protection > 10000) {
break;
}
}
for (var i = 0; i < circles.length; i++) {
fill(255, 255, 255);
strokeWeight(4);
ellipse(circles[i].x, circles[i].y, circles[i].r * 2, circles[i].r * 2);
}
noStroke();
}
windowResized = () => {
console.log('window resized');
resizeCanvas(windowWidth, windowHeight, true);
setupCircles();
}
draw = () => {
for (var i = 0; i < circles.length; i++) {
if (mouseX > circles[i].x - circles[i].r && mouseX < circles[i].x + circles[i].r && mouseY > circles[i].y - circles[i].r && mouseY < circles[i].y + circles[i].r)
{
stroke(0, 0, 0);
fill(random(colors));
strokeWeight(4);
ellipse(circles[i].x, circles[i].y, circles[i].r * 2, circles[i].r * 2);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
Closing remarks:
I've noticed you used noStroke()
and frameRate(2.5)
which leads me to believe you are visual thinker paying attention to visual details. If the intention is to avoid jagged circle edges from overdrawing and not using as much CPU/power on mobile devices you might
want to check out createGraphics()
: it's really cool. In terms of avoiding continously rendering in draw()
if you simply want to fill circles when they're hovered you can use mouseMoved()
You could use a global graphics object at the top that gets populated with circles in setup() then simply fill circles when the mouse is moved.
Additionally you could further encapsulate:
for (var i = 0; i < circles.length; i++) {
if (mouseX > circles[i].x - circles[i].r && mouseX < circles[i].x + circles[i].r && mouseY > circles[i].y - circles[i].r && mouseY < circles[i].y + circles[i].r)
{
stroke(0, 0, 0);
fill(random(colors));
strokeWeight(4);
ellipse(circles[i].x, circles[i].y, circles[i].r * 2, circles[i].r * 2);
}
}
to something like
isInsideCircle = (circle, x, y) => {
return (x > circle.x - circle.r && x < circle.x + circle.r ) && (y > circle.y - circle.r && y < circle.y + circle.r);
}
getCircleAt = (circles, x, y) => {
let numCircles = circles.length;
for (let i = 0; i < numCircles; i++){
if(isInsideCircle(circles[i], x, y){
return circles[i];
}
}
}
mouseMoved = () => {
circle = getCircleAt(circles, mouseX, mouseY);
if(circle){
fill(random(colors));
ellipse(circle.x, circle.y, circle.r * 2, circle.r * 2);
}
}
Note this is an untested snippet, but hopefully it illustrated some of the ideas mentioned.
Upvotes: 2