I want to achieve something like an infinite drag like the one in Konva js Can anyone help me with this. I try varius things but non of them were ok. Im new in p5js and javascript. Please for any hints. Only this element prevents me from completing the entire project.
var grid;
var current_img;
var BgCat1 = [];
var layerOne;
let show_grid = false;
There may be a more elegant solution, but here I draw an extra cell on each side of the grid to handle the wraparound, so a 12x12 grid with 10x10 visible. See it run here: https://editor.p5js.org/rednoyz/full/uJCADfZXv
let dim = 10, sz;
let xoff = 0, yoff = 0;
function setup() {
createCanvas(400, 400);
sz = width/ dim;
}
function mouseDragged() {
xoff += mouseX - pmouseX;
yoff += mouseY - pmouseY;
}
function draw() {
background(255);
for (let i = 0; i < dim+2; i++) {
for (let j = 0; j < dim+2; j++) {
let x = ((xoff + j * sz) % (width+sz)) - sz;
if (x < -sz) x += width+sz;
let y = ((yoff + i * sz) % (height+sz)) - sz;
if (y < -sz) y += height+sz;
rect(x, y, sz, sz);
text(i * 10 + j, x + sz/2, y + sz/2);
}
}
}
Related
I have created a circle with subdivisions (function CircleSubDivs) in p5.js and now want to generate a grid filled with those. Ideally the ellipse would also be disproportionate if the width and height of a tile is not the same, or if the amount of tiles were to be controlled by the mouse position the ellipse would move flexibly.
This was my inspiration
This is my code so far:
// let colors = [
// "#F48668 ",
// "#5D2E8C",
// "#F7F7F7"
// ];
function CircleSubDivs(x, y, size) {
let amount = 13;
let r = 360 / amount;
for (let j = 0; j < 10; j++) {
for (let i = 0; i < amount; i++) {
fill(random(255));
let s = map(j, 0, 8, width, 100);
arc(width / 2, height / 2, s, s, radians(r * i), radians(r * (i + 1)));
}
}
}
function setup() {
createCanvas(500, 500);
frameRate(1);
}
function draw() {
background("#0F0F0F");
noStroke();
let tilesX = 3;
let tilesY = 2;
let tileW = width / tilesX;
let tileH = height / tilesY;
for (let x = 0; x < tilesX; x++) {
for (let y = 0; y < tilesY; y++) {
CircleSubDivs(x * tileW, y * tileH, tileW, tileH);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
As you can see I have created a grid and tried to store my function for the ellipse with divisions in there, but it just shows me one single ellipse when I run it. I would really appreciate some help :)
Your parameters to your function are unused, so the function does the same thing every time.
You might try something like:
function drawSubdividedCircle(x, y, size, segments=13, layers=10) {
const r = 360 / segments;
for (let i = 0; i < segments; i++) {
for (let j = 0; j < layers; j++) {
fill(random(255));
const s = map(j, 0, layers, size, 0);
arc(
x + size / 2,
y + size / 2,
s,
s,
radians(r * i),
radians(r * (i + 1))
);
}
}
}
function setup() {
createCanvas(500, 500);
frameRate(1);
}
function draw() {
background("#0F0F0F");
noStroke();
const tilesX = 3;
const tilesY = 2;
const tileSize = width / tilesX;
for (let x = 0; x < tilesX; x++) {
for (let y = 0; y < tilesY; y++) {
drawSubdividedCircle(x * tileSize, y * tileSize, tileSize);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
I am trying to create a hexagon made out of hexagon cells in p5.js.
I would like the algorithm to receive the following as input:
number of hexagon cells in the first row
total hexagon cells to draw
This is the code I have so far but it is not drawing the shape the way I want to.
// declare fixed variables
let diam = 30;
let total_hex = 30;
let diagonal = 7;
let first_row = 4;
let side = first_row;
// declare dependent variables
let radius = diam / 2;
let upper_half = side - 1;
let rows = upper_half + side;
function setup() {
createCanvas(700, 700);
}
// draw
function draw() {
background("#ffae5");
noFill();
strokeWeight(2);
stroke("#ffb703");
// start counters
// row_counter = rows;
counter = 0;
row_cells = first_row;
push();
translate(200, 200);
for (let j = 0; j < rows; j++) {
for (let i = 0; i < row_cells; i++) {
push();
translate(-j * (radius + radius / 2 + radius / 4), 0);
if (diagonal > i) {
console.log(diagonal, i);
push();
translate(i * 2 * diam - (i * radius) / 2, 3 * j * (diam / 2));
polygon(0, 0, diam, 6);
pop();
}
pop();
}
if (rows < j) {
row_cells -= 1;
}
if (rows > j) {
row_cells += 1;
}
}
pop();
}
function polygon(x, y, radius, npoints) {
let angle = TWO_PI / npoints;
beginShape();
for (let a = 0; a < TWO_PI; a += angle) {
let sx = x + sin(a) * radius;
let sy = y + cos(a) * radius;
vertex(sx, sy);
}
endShape(CLOSE);
}
Specifically, the hexagons from the bottom half of the shape appear to be shifted by some parameter I still can't figure out. Here's the link to the p5.js online editor.
What am I missing here? Thanks!
I logged i, j at each cell to determine the position.
Now if you look at the cells you want to remove, you will see that these cells are: i < 3 && j > 3 && j - i > 3.
So if you simply want to remove these cells, you could change your if (diagonal > i) to if (diagonal > i && !(i < 3 && j > 3 && j - i > 3))) or parametrize that 3 to be a dependent variable to Math.floor(diagonal/2) to make something like:
//declare fixed variables
let diagonal = 7;
...
//declare dependent variables
const bottomLeftThreshold = Math.floor(diagonal/2);
...
const bottomLeft = i < bottomLeftThreshold && j > bottomLeftThreshold && j - i > bottomLeftThreshold
if (diagonal > i && !(bottomLeft))
...
Now the code is much more readable and modularized.
I did some tweaks to #cSharp's code snippet (see first answer) here and there, and ended up making the code flexible enough so it can adapt to any number of hexagons and sizes.
Below are the "fixed" and "dependent" variables I declared to draw the hexagon as well as the draw() function. I had to do some auxiliary calculations to get the diagonal and side sizes here.
// declare data variables
let year_1920 = 21;
let year_2019 = 73;
// declare fixed variables
let diam = 30;
let total_hex = year_2019;
let diagonal = 11;
let first_row = 6;
let side = first_row;
// declare dependent variables
let radius = diam / 2;
let upper_half = side - 1;
let rows = upper_half + side;
function draw() {
background("#ffae5");
noFill();
strokeWeight(1.2);
stroke("#ffb703");
// start counters
yellow = 0;
counter = 0;
row_cells = first_row;
push();
translate(200, 100);
for (let j = 0; j < rows; j++) {
for (let i = 0; i < row_cells; i++) {
if (yellow >= year_1920) {
stroke(255);
fill("#ffb703");
}
yellow++;
if (counter >= total_hex) {
noStroke();
noFill();
}
push();
translate(-j * (radius + radius / 2 + radius / 4), 0);
if (
diagonal > i &&
!(i < upper_half && j > upper_half && j - i > upper_half)
) {
push();
translate(i * 2 * diam - (i * radius) / 2, 3 * j * (diam / 2));
polygon(0, 0, diam, 6);
pop();
counter++;
}
pop();
}
if (rows > j) {
row_cells++;
}
}
pop();
}
I've created a noise function that pairs with a circle function to create a random noise circle thing that looks pretty cool. My problem is the curveVertex function in P5.js works correctly except for the connection of the first and last vertex. My code is:
let start = Array(50).fill(0); // dont change
let amount = 1; // amount of shapes
let gap = 30; // between shapes
let amplify = 50; // 0 -->
let colorSpeed = 1; // 1 - 9
let colorSeparation = 3; // 0 - 80 recomended 0 - 10
function setup() {
createCanvas(windowWidth, windowHeight);
for(let i = 0 ; i < start.length; i++){
start[i] = random(i);
}
}
function draw() {
background(0);
for(let dnc = (amount + 1) * gap; dnc > gap; dnc -= gap){
drawNoiseCircle(dnc, getNoise(start.length));
}
start = start.map( c => c + 0.01 );
}
function getNoise(amount){
let lengths = [];
for(let i = 1; i < amount + 1; i++){
let n1 = noise(start[i - 1]);
let noise1 = map(n1, 0, 1, -amplify, amplify);
lengths.push(abs(-noise1));
}
return lengths;
}
function drawNoiseCircle(radius, lengths){
colorMode(HSB);
fill(((frameCount + radius) * colorSeparation)/-map(colorSpeed, 1, 10, -10, -1) % 360, 100, 50);
noStroke()
let x;
let y;
beginShape();
for(let l = 0; l < lengths.length; l++){
x = Math.cos(radians(l * 360 / lengths.length)) * (radius + lengths[l]) + width/2;
y = Math.sin(radians(l * 360 / lengths.length)) * (radius + lengths[l]) + height/2;
curveVertex(x, y);
}
endShape(CLOSE);
stroke("black");
line(width/2, height/2, width, height/2);
line(width/2, height/2 + 9, width, height/2 + 9);
}
<script src="https://cdn.jsdelivr.net/npm/p5#1.4.1/lib/p5.js"></script>
I understand the endShape(CLOSED) closes the shape with a straight line, but I'm not sure any other way to close the shape.
You can see the pointed edge on the right side, directly in the middle of the shape.
!EDIT!
I've added lines to the shape to show the line segment that isn't affected by the curve vertex. Also, I understand it may not be a very significant problem, but if the amount of vertexes shrink, it becomes a much bigger problem (eg. a square or a triangle).
Unfortunately I won't have time to dive deep and debug the actual issue with curveVertex (or it's math) at the time, but it seems there's something interesting with curveVertex() in particular.
#Ouoborus point makes sense and the function "should" behave that way (and it was with vertex(), but not curveVertex()). For some reason curveVertex() requires looping over the not just the first point again, but the second and third.
Here's basic example:
function setup() {
createCanvas(300, 300);
background(220);
let numPoints = 6;
let angleIncrement = TWO_PI / numPoints;
let radius = 120;
beginShape();
for(let i = 0 ; i < numPoints + 3; i++){
let angle = angleIncrement * i;
let x = 150 + cos(angle) * radius;
let y = 150 + sin(angle) * radius;
curveVertex(x, y);
}
endShape();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>
Try decreasing numPoints + 3 to numPoints + 2 or notice the behaviour you're describing.
(I could speculate it might have something to do with how curveVertex() (Catmull-Rom splines) are implemented in p5 and how many coordinates/points it requires, but this isn't accurate without reading the source code and debugging a bit)
Here's a version of your code using the above notes:
let start = Array(30).fill(0);
let colorSpeed = 1; // 1 - 9
let colorSeparation = 3; // 0 - 80 recomended 0 - 10
function setup() {
createCanvas(600, 600);
colorMode(HSB);
noStroke();
// init noise seeds
for(let i = 0 ; i < start.length; i++){
start[i] = random(i);
}
}
function getNoise(seeds, amplify = 50){
let amount = seeds.length;
let lengths = [];
for(let i = 1; i < amount + 1; i++){
let n1 = noise(seeds[i - 1]);
let noise1 = map(n1, 0, 1, -amplify, amplify);
lengths.push(abs(-noise1));
}
return lengths;
}
function drawNoiseCircle(radius, lengths){
let sides = lengths.length;
let ai = TWO_PI / sides;
let cx = width * 0.5;
let cy = height * 0.5;
fill(((frameCount + radius) * colorSeparation)/-map(colorSpeed, 1, 10, -10, -1) % 360, 100, 50);
beginShape();
for(let i = 0 ; i < sides + 3; i++){
let noiseRadius = radius + lengths[i % sides];
let a = ai * i;
let x = cx + cos(a) * noiseRadius;
let y = cy + sin(a) * noiseRadius;
curveVertex(x, y);
}
endShape();
}
function draw() {
background(0);
// draw with updated perlin noise values
drawNoiseCircle(120, getNoise(start));
// increment noise seed
start = start.map( c => c + 0.01 );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>
I have tried several ways but nothing is working, I want to put the contents of one javascript file into the other, the code I tried is:
for (k = 0; k < js_array2; k++) {
p[k]=Math.random();
if(p[k]<0.5){
$.getScript('/path/to/imported/script.js')
} else {
//Some code
}
The code in the script I want to include is:
var c = document.getElementById("canvas[" + k + "]");
document.getElementById("shape[" + k + "]").innerHTML = "Square";
var ctx = c.getContext("2d");
var width = c.width;
var height = c.height;
//ctx.strokeRect(0, 0, 120, 120);
var n = hour2[k];
var z = 0;
var m = minute2[k];
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
var x = 0 + (i - 1) * width / n;
var y = 0 + (j - 1) * height / n;
ctx.beginPath();
ctx.rect(x, y, width / n, height / n);
ctx.fillStyle = "cyan"
if (z < m) {
ctx.fillRect(x, y, width / n, height / n);
z = z + 1;
}
ctx.stroke();
}
}
I have tried several other ways too but this was the only one without errors but unfortunately no output.
In modern JavaScript it would look something like this:
export something from a file
export c = //whatever
import it dynamically from another file
if(some_condition){
{c} = await import('/path/to/imported/script.js')
// do whatever with c
}
Read more on exports on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
Read more about imports on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
What you can do is create a function out of the second file, then check to see if K exists
and the corresponding canvas exists on the page and run it for the other pages.
So for example this would be script.js:
function createSquare(k){
var c = document.getElementById("canvas[" + k + "]");
document.getElementById("shape[" + k + "]").innerHTML = "Square";
var ctx = c.getContext("2d");
var width = c.width;
var height = c.height;
//ctx.strokeRect(0, 0, 120, 120);
var n = hour2[k];
var z = 0;
var m = minute2[k];
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
var x = 0 + (i - 1) * width / n;
var y = 0 + (j - 1) * height / n;
ctx.beginPath();
ctx.rect(x, y, width / n, height / n);
ctx.fillStyle = "cyan"
if (z < m) {
ctx.fillRect(x, y, width / n, height / n);
z = z + 1;
}
ctx.stroke();
}
}
}
if(typeof k != "undefined" && document.getElementById("canvas[" + k + "]") != null){
createSquare(k);
}
Then to include it:
$.getScript('/path/to/imported/script.js',function(){
createSquare(k);
});
I'm trying to get the pixel data from an image to calculate the image's average brightness. I have no problem accessing the data with img.loadPixels(); but for some reason some elements of the pixel array are undefined, which breaks my computation.
Here is the code for sketch.js:
var img;
var brightness;
var inc;
var gotBright = false;
function preload(){
img = loadImage('assets/2.png');
}
function setup(){
createCanvas(500, 500);
background(0);
}
function draw(){
img.resize(10, 10);
image(img, 0, 0, img.width, img.height);
brightness = 0;
inc = 0;
if (gotBright == false) {
img.loadPixels();
loadPixels();
for (var i = 0; i < img.width; i++) {
for (var j = 0; j < img.height; j++) {
var index = (i * j * img.width) * 4;
var r = img.pixels[index + 0];
var g = img.pixels[index + 1];
var b = img.pixels[index + 2];
brightness += (r + g + b) / 3;
inc ++;
console.log(inc, r , g, b);
}
}
gotBright = true;
brightness = brightness/inc;
}
}
brightness should be equal to some number between 0 and 255, but now it's NaN...
If you have recommendations on other methods to calculate average brightness of an image, I am happy to hear them :)
Thanks!
I think your index calculation is wrong. Shouldn't it be:
var index = (i + j * img.width) * 4;
Bauer's answer is on the right track. You need to make sure your pixel index is correct. The best way to do that is to get out a piece of graph paper and draw out some examples.
Or you could just use the get() function that takes an x and a y parameter. From the reference:
var myImage;
var c;
function preload() {
myImage = loadImage("assets/rockies.jpg");
}
function setup() {
background(myImage);
noStroke();
c = myImage.get(60, 90);
fill(c);
rect(25, 25, 50, 50);
}