rotating a custom shape moves it in the corner - javascript

When rotating a custom shape using translate(width/2,height/2); rotate(angle)),
it moves the shape in the bottom left corner. I tried making translate values negative, it fixed it but then the origin was at 0,0. I have used pop(); push() and beginShape(); endShape with no success.
var points = [];
var r;
var lines = 30;
function setup() {
createCanvas(window.innerWidth, window.windowHeight);
angleMode(DEGREES);
// get the points of the corners of the hexagon
r = Math.min(width, height) * 0.4;
var angle = 60;
for (var i = 1; i < 7; i++) {
var tempX = r * sin((angle * i + 30) % 360) + width / 2;
var tempY = r * cos((angle * i + 30) % 360) + height / 2;
points.push([tempX, tempY]);
}
background(0);
stroke(0, 0, 255);
rectMode(CENTER);
}
function draw() {
background(0);
// draw the lines of ...
push();
translate(width/2, height/2);
rotate(frameCount * 0.75);
beginShape();
for (var i = 0; i < points.length; i++) {
// ... the hexagon perimeter
line(points[i][0], points[i][1], points[(i + 1) % 6][0], points[(i + 1) % 6][1]);
var tempAngle = 240 + i * 60;
var tempX = r * 1.1545 * sin(tempAngle) + points[i][0];
var tempY = r * 1.1545 * cos(tempAngle) + points[i][1];
for (var j = 0; j < lines + 1; j++) {
// ... the lines inside the hexagon
var tempAngle2 = tempAngle = (30 / lines * j) + 210 + i * 60;
var distance = r / cos(30 / lines * j);
var tempX2 = distance * sin(tempAngle2) + points[i][0];
var tempY2 = distance * cos(tempAngle2) + points[i][1];;
line(points[i][0], points[i][1], tempX2, tempY2);
}
endShape();
}
pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>

I think the problem is that you are defining your points for your shape with an x/y offset. By removing the width / 2 & height / 2 from your point definitions it centers your shape.
var points = [];
var r;
var lines = 30;
function setup() {
createCanvas(window.innerWidth, window.windowHeight);
angleMode(DEGREES);
// get the points of the corners of the hexagon
r = Math.min(width, height) * 0.4;
var angle = 60;
for (var i = 1; i < 7; i++) {
var tempX = r * sin((angle * i + 30) % 360)
var tempY = r * cos((angle * i + 30) % 360)
points.push([tempX, tempY]);
}
background(0);
stroke(0, 0, 255);
//rectMode(CENTER);
}
function draw() {
background(0);
// draw the lines of ...
push();
translate(width/2, height/2);
rotate(frameCount * 0.75);
beginShape();
for (var i = 0; i < points.length; i++) {
// ... the hexagon perimeter
line(points[i][0], points[i][1], points[(i + 1) % 6][0], points[(i + 1) % 6][1]);
var tempAngle = 240 + i * 60;
var tempX = r * 1.1545 * sin(tempAngle) + points[i][0];
var tempY = r * 1.1545 * cos(tempAngle) + points[i][1];
for (var j = 0; j < lines + 1; j++) {
// ... the lines inside the hexagon
var tempAngle2 = tempAngle = (30 / lines * j) + 210 + i * 60;
var distance = r / cos(30 / lines * j);
var tempX2 = distance * sin(tempAngle2) + points[i][0];
var tempY2 = distance * cos(tempAngle2) + points[i][1];;
line(points[i][0], points[i][1], tempX2, tempY2);
}
endShape();
}
pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>

Related

p5.js replace let url to local link

Im noob with p5j and i need help from someone please! :-(
On the website i must upload it , they not allow the external links.
and i need to change the "let url" to a png/jpg local link ( not external link ).
i dont know what the solution is ( maybe something similar with: "loadImage" or something.... please help me :-) )
Thank you so much and have a blessed week!
Here is the code:
//let url = "https://coolors.co/3a2e39-1e555c-f4d8cd-edb183-f15152";
let url = "https://blog.logrocket.com/wp-content/uploads/2022/03/Creating-animations-p5-js.png";
let palette;
let font;
function preload() {
font = loadFont("https://openprocessing.org/sketch/1359269/files/Happy Monsters.ttf");
}
function setup() {
createCanvas(1112, 834);
colorMode(HSB, 360, 100, 100, 100);
angleMode(DEGREES);
palette = createPalette(url);
background(10);
}
function draw() {
//background(0, 0, 90);
let offset = 100//width / 100;
let margin = 0; //offset / 5;
let cells = 1//int(random(2, 8));
let d = (width - offset * 2 - margin * (cells - 1)) / cells;
for (let j = 0; j < cells; j++) {
for (let i = 0; i < cells; i++) {
let x = offset + i * (d + margin) + d / 2;
let y = offset + j * (d + margin) + d / 2;
drawFancyShape(x, y, d, palette.concat());
}
}
frameRate(0.5);
noLoop();
}
function drawFancyShape(x, y, d, colors, char = String.fromCodePoint(65 + int(random(26)))) {
let g = createGraphics(d, d);
let g2 = createGraphics(d, d);
colors = shuffle(colors);
let c0 = colors[0];
colors.splice(0, 1);
let ratio = 0.2;
let xStep, yStep;
for (let y = 0; y < g.height; y += yStep) {
yStep = random(ratio, 1 - ratio) * g.height / 2;
if (y + yStep > g.height) yStep = g.height - y;
if (g.height - y - yStep < g.height / 100) yStep = g.height - y;
for (let x = 0; x < g.width; x += xStep) {
xStep = random(ratio, 1 - ratio) * g.width / 2;
if (x + xStep > g.width) xStep = g.width - x;
if (g.width - x - xStep < g.width / 100) xStep = g.width - x;
let r = [];
for (let i = 0; i < 4; i++) {
r.push(int(random(5)) * max(xStep, yStep) / 4);
}
g.rectMode(CENTER);
g.fill(random(colors));
g.noStroke();
g.rect(x + xStep / 2, y + yStep / 2, xStep - 2, yStep - 2, r[0], r[1], r[2], r[3]);
}
}
g2.textSize(g.width * 0.6);
g2.textAlign(CENTER, CENTER);
g2.textFont(font)
g2.textStyle(BOLD);
g2.fill(c0);
// g2.stroke(0);
g2.text(char, g.width / 2, g.height / 2 - g.height / 8);
let g_tmp = g.get();
let g2_tmp = g2.get();
g_tmp.mask(g2_tmp);
// g_tmp.mask(g2_tmp);
drawingContext.shadowColor = color(0, 0, 0, 33);
drawingContext.shadowBlur = d / 10;
push();
translate(x, y);
imageMode(CENTER);
// image(g, 0, 0);
let scl = 1.1;
image(g2, 0, 0, g2.width * scl, g2.height * scl);
image(g_tmp, 0, 0, g_tmp.width * scl, g_tmp.height * scl);
pop();
}
function createPalette(_url) {
let slash_index = _url.lastIndexOf('/');
let pallate_str = _url.slice(slash_index + 1);
let arr = pallate_str.split('-');
for (let i = 0; i < arr.length; i++) {
arr[i] = color('#' + arr[i]);
}
return arr;
}
// save jpg
let lapse = 0; // mouse timer
function mousePressed(){
// prevents mouse press from registering twice
if (millis() - lapse > 400){
save("img_" + month() + '-' + day() + '_' + hour() + '-' + minute() + '-' + second() + ".jpg");
lapse = millis();
}
}

How to plot a imperfect circle in JS with p5

I've created a script to calculate coordinates of a circle in JS. I'm using p5.js to draw the circle but when I run the script nothing happens. I assume it has to do with the way I'm plotting the vertices?
var xValues = [];
var yValues = [];
function setup() {
createCanvas(400, 400);
background(220);
crookedCircle(10, 10, 10, 10);
}
function draw() {}
function crookedCircle(radius, steps, centerX, centerY) {
for (var i = 0; i < steps; i++) {
xValues[i] = (centerX + radius * Math.cos(2 * Math.PI * i / steps));
yValues[i] = (centerY + radius * Math.sin(2 * Math.PI * i / steps));
for (let x = 0; x < xValues.length; x++) {
for (let y = 0; y < yValues.length; y++) {
//console.log("x: "+xValues[x] + " y: "+yValues[y])
beginShape();
vertex(xValues[x] + random(-10, 10), yValues[y]) + random(-10, 10);
endShape(CLOSE);
}
}
}
}
Here I cleaned what was written, I can annotate it to explain if you wish so. Also instead of random, I recommend you explore the noise() function here, which would make the circle look smoother.
function setup() {
createCanvas(400, 400);
background(220);
crookedCircle(10, 10, width / 2, height / 2);
}
function draw() {}
function crookedCircle(radius, steps, centerX, centerY) {
var xValues = [];
var yValues = [];
for (var i = 0; i < steps; i++) {
let rad = radius + random(-radius / 10,radius / 10) // you can change the 10 here to how intense you want the change to be;
xValues[i] = (centerX + rad * cos(2 * PI * i / steps));
yValues[i] = (centerY + rad * sin(2 * PI * i / steps));
}
beginShape();
for(let i = 0; i < xValues.length; i ++){
curveVertex(xValues[i], yValues[i]);
}
endShape(CLOSE);
}
You draw many many shapes with just 1 point. beginShape and endShape encloses the vertices of a shape. Therefore you have to call beginShape before the loop and endShape after the loop:
function crookedCircle(radius, steps, centerX, centerY) {
beginShape();
for (var i = 0; i < steps; i++) {
// [...]
}
endShape(CLOSE);
}
One loop is enough if you want to draw 1 circle:
var xValues = [];
var yValues = [];
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
fill(255)
crookedCircle(100, 90, 120, 120);
}
function crookedCircle(radius, steps, centerX, centerY) {
for (var i = 0; i < steps; i++) {
xValues[i] = centerX + radius * Math.cos(2 * Math.PI * i / steps);
yValues[i] = centerY + radius * Math.sin(2 * Math.PI * i / steps);
}
beginShape();
for(let i = 0; i < steps; i ++) {
vertex(xValues[i] + random(-2, 2), yValues[i] + random(-2, 2));
}
endShape(CLOSE);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>

centring the canvas moves it in the corner

I am trying to centre my whole canvas in the middle so I can scale it, as the edges are not complete and I can't fill up the space using values lower or bigger than the canvas as it bring up errors. Here is a picture without scaling and with scaling.
var rows = 10;
var cols = 10;
var points = [];
var sat = 70;
var bright = 80;
var timesDrawed = 0;
function setup() {
createCanvas(600, 600);
colorMode(HSB, 100, 100, 100);
noStroke();
rectMode(CENTER);
}
function draw() {
translate(width/2,height/2);
if (timesDrawed >= 3) {
noLoop();
} else {
timesDrawed++;
}
scale(1.2);
for (var r = 0; r < rows; r++) {
for (var c = 0; c < cols; c++) {
var tempX = random((width / (cols)) * c - (width / cols * 0.5), (width / (cols)) * c + (width / cols * 0.5));
var tempY = random((height / (rows)) * r - (height / rows * 0.5), (height / (rows)) * r + (height / rows * 0.5));
points.push([tempX, tempY]);
}
}
print(points);
for (var r = 0; r < rows - 1; r++) {
for (var c = 0; c < cols -1; c++) {
fill(random(0, 100), sat, bright);
var point1 = c + (r * rows);
var point2 = c + (r * rows) + 1;
var point3 = c + (r * rows) + rows;
triangle(points[point1][0], points[point1][1], points[point2][0], points[point2][1], points[point3][0], points[point3][1]);
fill(random(0, 100), sat, bright);
var point1 = c + (r * rows) + rows;
var point2 = c + (r * rows) + 1;
var point3 = c + (r * rows) + rows + 1;
triangle(points[point1][0], points[point1][1], points[point2][0], points[point2][1], points[point3][0], points[point3][1]);
}
}
}
If the canvas is tiled in columns (cols) and rows rows, then the start of each column is c * width/cols and the end of each column is (c+1) * width/cols, the start of each row is (r * height/rowsand the end of each row is(r+1) * height/rows, wherecis the column andr` is the row.
Since the center of the canvas is (0, 0), the half with and the half height have to be subtracted from the coordinate:
var tempX = random(c * width/cols - width/2, (c+1) * width/cols - width/2);
var tempY = random(r * height/rows - height/2, (r+1) * height/rows - height/2);
or
var tempX = random(c, c+1) * width/cols - width/2;
var tempY = random(r, r+1) * height/rows - height/2;
See the preview, where I applied the suggested changes to your original code and I removed the scale scale(1.2):
var rows = 10;
var cols = 10;
var points = [];
var sat = 70;
var bright = 80;
var timesDrawed = 0;
function setup() {
createCanvas(400, 400);
colorMode(HSB, 100, 100, 100);
noStroke();
rectMode(CENTER);
}
function draw() {
background(64);
translate(width/2,height/2);
if (timesDrawed >= 3) {
noLoop();
} else {
timesDrawed++;
}
//scale(1.2);
for (var r = 0; r < rows; r++) {
for (var c = 0; c < cols; c++) {
var tempX = random(c, c+1) * width/cols - width/2;
var tempY = random(r, r+1) * height/rows - height/2;
points.push([tempX, tempY]);
}
}
print(points);
for (var r = 0; r < rows - 1; r++) {
for (var c = 0; c < cols -1; c++) {
fill(random(0, 100), sat, bright);
var point1 = c + (r * rows);
var point2 = c + (r * rows) + 1;
var point3 = c + (r * rows) + rows;
triangle(points[point1][0], points[point1][1], points[point2][0], points[point2][1], points[point3][0], points[point3][1]);
fill(random(0, 100), sat, bright);
var point1 = c + (r * rows) + rows;
var point2 = c + (r * rows) + 1;
var point3 = c + (r * rows) + rows + 1;
triangle(points[point1][0], points[point1][1], points[point2][0], points[point2][1], points[point3][0], points[point3][1]);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>

Drawing parallel equidistant lines inside a circle

I'm trying to draw parallel equidistant lines inside a circle. I've got to the stage that if i connect points from their opposite angles on the circumference I get parallel lines... but they're not equidistant...
Here's some code:
var num_lines = 8;
var num_points = num_lines * 2;
var start_angle = 100;
var points = [];
var radius = 200;
ctx.strokeCircle(w/2, h/2, radius, radius); // shorthand for ctx.arc( x, y, 5, 0, Math.PI * 2, true );
for (var i = 0; i < num_points; i++) {
var angle = 360/num_points * i;
ctx.fillStyle = "red";
if (i %2 == 0 ) ctx.fillStyle = "blue";
var x = w/2 + Math.cos(angle) * radius/2;
var y = h/2 + Math.sin(angle) * radius/2;
ctx.circle(x, y, 10, 10); // shorthand for ctx.arc( x, y, 5, 0, Math.PI * 2, true );
points.push({x: x, y: y});
}
for (var i = 0; i < num_lines; i++) {
ctx.line(points[i].x, points[i].y, points[points.length-i-1].x, points[points.length-i-1].y)
}
Use Pythagoras' theorem.
The ...
y: vertical position of the line relative to the center
x: horizontal distance of its endpoints from the center
r: radius of the circle
... must satisfy y^2 + x^2 = r^2.
Code:
var radius = 200;
var num_lines = 8;
// vertical spacing
var delta_y = (2.0 * radius) / (num_lines + 1);
ctx.strokeCircle(w/2, h/2, radius, radius);
for (var i = 0; i < num_lines; i++)
{
// applying pythagoras
var y = delta_y * (i + 1) - radius / 2;
var x = Math.sqrt(radius * radius - y * y);
// calculating endpoints
var left_x = w / 2 - x;
var right_x = w / 2 + x;
var end_y = h / 2 + y;
ctx.fillStyle = (i % 2 == 0) ? "blue" : "red";
ctx.circle(left_x, end_y, 10, 10);
ctx.circle(right_x, end_y, 10, 10);
ctx.line(left_x, end_y, right_x, end_y);
}
EDIT: rotation
To rotate a vector by angle a clockwise:
x' = x * cos(a) + y * sin(a)
y' = y * cos(a) - x * sin(a)
Code:
var radius = 200;
var num_lines = 50;
var angle = 60;
// temporary variables
var delta_y = (2.0 * radius) / (num_lines);
var cos_a = Math.cos(angle * Math.PI / 180.0);
var sin_a = Math.sin(angle * Math.PI / 180.0);
ctx.strokeCircle(w / 2, h / 2, radius * 2, radius * 2);
for (var i = 0; i < num_lines; i++)
{
// applying pythagoras
var y = delta_y * i - radius;
var x = Math.sqrt(radius * radius - y * y);
// rotating the displacement vector
var left_x = y * sin_a + x * cos_a;
var right_x = y * sin_a - x * cos_a;
var left_y = y * cos_a - x * sin_a;
var right_y = y * cos_a + x * sin_a;
ctx.fillStyle = (i % 2 == 0) ? "blue" : "red";
ctx.line(w / 2 + left_x , h / 2 + left_y ,
w / 2 + right_x, h / 2 + right_y);
}
got it to work like so... wondering how I can rotate the lines at an angle (mathematically, not using ctx.translate and ctx.rotate ):
var radius = 200;
var num_lines = 50;
// vertical spacing
var delta_y = (2.0 * radius) / (num_lines);
ctx.strokeCircle(w/2, h/2, radius * 2, radius * 2);
for (var i = 0; i < num_lines; i++)
{
// applying pythagoras
var y = delta_y * (i) - radius;
var x = Math.sqrt(radius * radius - y * y);
// calculating endpoints
var left_x = w / 2 - x;
var right_x = w / 2 + x;
var end_y = h / 2 + y;
ctx.fillStyle = (i % 2 == 0) ? "blue" : "red";
ctx.line(left_x, end_y, right_x, end_y);
}

adding custom animation in canvas html5

this might be somewhat difficult but i wil still ask, so i made a starfield ,now what i want to do is to have my stars( a pair each) connected to eachother by a line ,now this line will expand as the stars move forward and disappear when the stars move out of the canvas .any help would be appreciated here this is difficult i have the logic but i seem unable to follow the correct way to implement it
function randomRange(minVal, maxVal) {
return Math.floor(Math.random() * (maxVal - minVal - 1)) + minVal;
}
function initStars() {
for (var i = 0; i < stars.length; i++) {
stars[i] = {
x: randomRange(-25, 25),
y: randomRange(-25, 25),
z: randomRange(1, MAX_DEPTH)
}
}
}
function degToRad(deg) {
radians = (deg * Math.PI / 180) - Math.PI / 2;
return radians;
}
function animate() {
var halfWidth = canvas.width / 2;
var halfHeight = canvas.height / 2;
ctx.fillStyle = "rgb(0,0,0)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < stars.length; i++) {
stars[i].z -= 0.2;
if (stars[i].z <= 0) {
stars[i].x = randomRange(-25, 25);
stars[i].y = randomRange(-25, 25);
stars[i].z = MAX_DEPTH;
}
var k = 128.0 / stars[i].z;
var px = stars[i].x * k + halfWidth;
var py = stars[i].y * k + halfHeight;
if (px >= 0 && px <= 1500 && py >= 0 && py <= 1500) {
var size = (1 - stars[i].z / 32.0) * 5;
var shade = parseInt((1 - stars[i].z / 32.0) * 750);
ctx.fillStyle = "rgb(" + shade + "," + shade + "," + shade + ")";
ctx.beginPath();
ctx.arc(px, py, size, degToRad(0), degToRad(360));
ctx.fill();
}
}
}
function animate() {
var halfWidth = canvas.width / 2;
var halfHeight = canvas.height / 2;
ctx.fillStyle = "rgb(0,0,0)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < stars.length; i++) {
stars[i].z -= 0.2;
if (stars[i].z <= 0) {
stars[i].x = randomRange(-25, 25);
stars[i].y = randomRange(-25, 25);
stars[i].z = MAX_DEPTH;
}
var k = 128.0 / stars[i].z;
var px = stars[i].x * k + halfWidth;
var py = stars[i].y * k + halfHeight;
if (px >= 0 && px <= 1500 && py >= 0 && py <= 1500) {
var size = (1 - stars[i].z / 32.0) * 5;
var shade = parseInt((1 - stars[i].z / 32.0) * 750);
ctx.fillStyle = "rgb(" + shade + "," + shade + "," + shade + ")";
ctx.beginPath();
ctx.arc(px, py, size, degToRad(0), degToRad(360));
ctx.fill();
}
}
}
<!DOCTYPE html5>
<html>
<head>
<title>stars</title>
<script src="convergis.js"></script>
<script>
MAX_DEPTH = 32;
var canvas, ctx;
var stars = new Array(500);
window.onload = function() {
canvas = document.getElementById("tutorial");
if( canvas && canvas.getContext ) {
ctx = canvas.getContext("2d");
initStars();
setInterval(animate,17);
}
}
</script>
</head>
<body>
<canvas id='tutorial' width='1500' height='1500'>
</canvas>
</body>
</html>
You could just say you want a lightspeed effect!
One way very cheap way to do it is to paint the background with some transparency. You can also render a set of points close together in order to make the illusion of the effect.
The good way to do it is shaders since they will allow you to add glow and some other nice image trickery that will make it look better. Here is a good example: https://www.shadertoy.com/view/Xdl3D2
Below I used the canvas api lineTo and even with a fixed line width, it's a pretty good final result.
var MAX_DEPTH = 64;
var LINELENGTH = 0.1;
var stars = new Array(500);
var canvas = document.getElementById("tutorial");
canvas.width = innerWidth;
canvas.height = innerHeight;
var ctx = canvas.getContext("2d");
initStars();
setInterval(animate,17);
function randomRange(minVal, maxVal) {
return Math.floor(Math.random() * (maxVal - minVal - 1)) + minVal;
}
function initStars() {
for (var i = 0; i < stars.length; i++) {
stars[i] = {
x: randomRange(-25, 25),
y: randomRange(-25, 25),
z: randomRange(1, MAX_DEPTH)
}
}
}
function degToRad(deg) {
radians = (deg * Math.PI / 180) - Math.PI / 2;
return radians;
}
function animate() {
var halfWidth = canvas.width / 2;
var halfHeight = canvas.height / 2;
ctx.fillStyle = "rgba(0,0,0,1)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < stars.length; i++) {
stars[i].z -= 0.5;
if (stars[i].z <= 0) {
stars[i].x = randomRange(-25, 25);
stars[i].y = randomRange(-25, 25);
stars[i].z = MAX_DEPTH;
}
var k = 254.0 / stars[i].z;
var px = stars[i].x * k + halfWidth;
var py = stars[i].y * k + halfHeight;
if (px >= 0 && px <= 1500 && py >= 0 && py <= 1500) {
var size = (1 - stars[i].z / 32.0) * 2;
var shade = parseInt((1 - stars[i].z / 32.0) * 750);
ctx.strokeStyle = "rgb(" + shade + "," + shade + "," + shade + ")";
ctx.lineWidth = size;
ctx.beginPath();
ctx.moveTo(px,py);
var ox = size * (px - halfWidth) * LINELENGTH;
var oy = size * (py - halfHeight) * LINELENGTH;
ctx.lineTo(px + ox, py + oy);
ctx.stroke();
}
}
}
<canvas id='tutorial' width='1500' height='1500'></canvas>

Categories