xxxxxxxxxx
403
// require https://cdn.jsdelivr.net/npm/tweakpane@3.0.7/dist/tweakpane.min.js
// require https://cdn.jsdelivr.net/npm/p5@latest/lib/p5.min.js
const pane = new Tweakpane.Pane();
const SHOULD_SAVE = true;
// constants
const FR = SHOULD_SAVE ? 5 : 30;
const CANVAS_WIDTH = 960;
const CANVAS_HEIGHT = 540;
const START_X = CANVAS_WIDTH * 1.4;// 0.75;
const START_POINT_COUNT = 50;
let xPos = 0;
const targetPoint = {
x: 0,
y: 0
}
const PARAMS = {
bgColor: "#FFF",
endColor: "#A3E000",
lineColor: "#FF787833",
// shape
diameter: CANVAS_WIDTH/2,
margin: 15,
angle: 30,
circlePoints: 7,
strokeWeight: 1,
curveVertex: true,
// anim
speed: 0.3,
seed: 315,
moveSpeed: 2,
// diam noise
useDiameterNoise: true,
dNoiseAmplitude: 1.5,
dNoiseFrequency: 0.004,
// shape noise
useShapeNoise: true,
sNoiseAmplitude: 0.4,
sNoiseFrequency: 0.08,
// points
dataPointDiameter: 6,
pointCenterX: 0.5,
pointCenterY: 0.8,
pointDiameter: 100,
pointRotationSpeed: 0.6,
// main
isDebug: false,
};
// global variables that are needed
let cutCount = 0;
let sphere_counter = 0;
const points = [];
let cnv = null;
function setup() {
cnv = createCanvas(CANVAS_WIDTH, CANVAS_HEIGHT);
noFill();
frameRate(FR)
pane.addInput(PARAMS,"isDebug");
// add parameters
const f1 = pane.addFolder({
title: 'Base Shape',
expanded: false,
});
f1.addInput(PARAMS, "bgColor", {
view: 'color',
});
f1.addInput(PARAMS, "diameter", {
min: 0,
max: CANVAS_WIDTH,
});
f1.addInput(PARAMS, "margin", {
min: 2,
max: 100,
});
f1.addInput(PARAMS, "angle", {
min: 0,
max: 45,
});
f1.addInput(PARAMS, "circlePoints", {
step: 1,
min: 0,
max: 100,
});
f1.addInput(PARAMS, "strokeWeight", {
min: 0,
max: 2,
});
f1.addInput(PARAMS, "curveVertex");
const f2 = pane.addFolder({
title: 'Animation',
expanded: false,
});
f2.addInput(PARAMS, "speed", {
min: 0,
max: 3,
});
f2.addInput(PARAMS, "seed", {
step: 1,
min: 0,
max: 999,
});
f2.addInput(PARAMS, "moveSpeed", {
min: 0,
max: 10,
});
const f3 = pane.addFolder({
title: 'Diameter Noise',
expanded: false,
});
f3.addInput(PARAMS, "useDiameterNoise");
f3.addInput(PARAMS, "dNoiseAmplitude", {
min: 0,
max: 10,
});
f3.addInput(PARAMS, "dNoiseFrequency", {
step: 0.001,
min: 0,
max: 0.05,
});
const f4 = pane.addFolder({
title: 'Shape Noise',
expanded: false,
});
f4.addInput(PARAMS, "useShapeNoise");
f4.addInput(PARAMS, "sNoiseAmplitude", {
min: 0,
max: 1,
});
f4.addInput(PARAMS, "sNoiseFrequency", {
step: 0.001,
min: 0,
max: 0.1,
});
const f5 = pane.addFolder({
title: 'DataBlob Points',
expanded: false,
});
f5.addInput(PARAMS, "dataPointDiameter", {
min: 1,
max: 20,
});
f5.addInput(PARAMS, "pointCenterX", {
min: 0,
max: 1,
});
f5.addInput(PARAMS, "pointCenterY", {
min: 0,
max: 1,
});
f5.addInput(PARAMS, "pointDiameter", {
label: "Point Aura",
min: 0,
max: 200,
});
f5.addInput(PARAMS, "pointRotationSpeed", {
min: 0,
max: 2,
});
adjustValues();
pane.on("change", adjustValues);
creatInitialPointBlob();
}
function adjustValues () {
cutCount = int(PARAMS.diameter / PARAMS.margin);
strokeWeight(PARAMS.strokeWeight);
noiseSeed(PARAMS.seed);
targetPoint.x = width * PARAMS.pointCenterX;
targetPoint.y = height * PARAMS.pointCenterY;
targetPoint.aura = PARAMS.pointDiameter;
// points.forEach( p => p.checkIfCenter() )
}
function draw() {
background(PARAMS.bgColor);
drawBG();
const colorEnd = color(PARAMS.endColor);
dataBlob();
points.forEach( p => p.draw() )
/*
if( frameCount % 10 === 0 ){
points.push( new DataPoint() )
}
*/
if( PARAMS.isDebug ){
push();
noFill();
stroke("blue");
circle(targetPoint.x, targetPoint.y, targetPoint.aura);
pop();
}
if( SHOULD_SAVE ){
let count = ( "000" + frameCount).slice(-4);
save(cnv, `Scene_03-${count}.jpg`);
}
}
const dataBlob = () => {
const randCut = floor( random(cutCount) );
const randPoint = floor( random(PARAMS.circlePoints) );
const spawnNewPoint = frameCount % 10 === 0;
push();
xPos -= PARAMS.moveSpeed
stroke(PARAMS.endColor);
if( xPos + START_X + PARAMS.diameter <= 0 ){
xPos = width - START_X + PARAMS.diameter;
}
const tX = sphere_counter * PARAMS.speed;
const p_now = tX / PARAMS.margin;
if( tX > PARAMS.margin ){
sphere_counter = 0;
}
translate( xPos, 0 )
translate(START_X - PARAMS.diameter/2 - PARAMS.margin/2,0);
for (let i = 0; i < cutCount; i++){
const p = lerp( i/cutCount, (i+1)/cutCount, p_now);
const sliceCut = lerp(0, PARAMS.diameter, p);
const radius = sqrt( PARAMS.diameter * sliceCut - pow(sliceCut,2) );
const h = radius * 2;
const d = radius * 2 * cos(radians(90-PARAMS.angle));
translate( PARAMS.margin, 0 );
const dn = PARAMS.useDiameterNoise ? noise( PARAMS.dNoiseFrequency * frameCount, p ) * PARAMS.dNoiseAmplitude : 1;
const sliceXVal = PARAMS.margin * i + START_X + xPos - d*2;
// draw circle
beginShape();
for( let c = 0; c <= PARAMS.circlePoints; c++ ){
let x = sin( c/PARAMS.circlePoints * TWO_PI ) * d/2 * dn;
let y = cos( c/PARAMS.circlePoints * TWO_PI - PI ) * h/2 * dn;
if( PARAMS.useShapeNoise ){
const n2 = sin( p * PI ) * PARAMS.sNoiseAmplitude * ( noise( frameCount * 0.01, PARAMS.sNoiseFrequency * c ) - 0.5 );
x += n2 * d;
y += n2 * h;
}
x += tX;
vertex( x, y );
if( spawnNewPoint && randCut === i && randPoint === c ){
// const actualX = xPos + PARAMS.margin * i + x;
const actualX = START_X - PARAMS.diameter/2 - PARAMS.margin/2 + xPos;
const actualY = y;
points.push( new DataPoint( actualX, actualY ) )
}
}
endShape(CLOSE);
}
sphere_counter++;
pop();
}
class DataPoint{
constructor( x = 0, y = 0 ){
this.x = x === 0 ? random( width ) : x;
this.y = y === 0 ? random( 0.1*height, 0.2*height ) : y;
this.speed = random( 2,4 );
this.amplifier = random( 8, 20 );
this.hasReachedCenter = false;
this.animCount = 0;
}
draw(){
this.checkIfCenter()
push();
noStroke();
fill( PARAMS.endColor );
translate( this.x, this.y )
if( this.hasReachedCenter ){
rotate( this.animCount / 30 * PI * ( this.speed / 8 ) * PARAMS.pointRotationSpeed )
translate( sin( this.animCount / 30 * PI * PARAMS.pointRotationSpeed ) * targetPoint.aura/2, 0 );
this.animCount++;
}else{
this.move();
}
circle( 0,0, PARAMS.dataPointDiameter );
pop();
}
move(){
const m = createVector(this.x - targetPoint.x, this.y - targetPoint.y );
m.normalize();
//Set d equal to the speed
this.x -= m.x * this.speed;
this.y -= m.y * this.speed;
}
checkIfCenter(){
this.hasReachedCenter = dist( this.x, this.y, targetPoint.x, targetPoint.y ) < 10
}
}
const creatInitialPointBlob = () => {
for( let i = 0; i < START_POINT_COUNT; i++ ){
const x = targetPoint.x + random( -20, 20 );
const y = targetPoint.y + random( -20, 20 );
points.push( new DataPoint( x, y ) )
}
};
const drawBG = () => {
push();
stroke( PARAMS.lineColor );
for( let i = 0; i < ( width / PARAMS.margin ); i++ ){
translate( PARAMS.margin, 0 );
line( 0,0,0,height );
}
pop();
// draw object
push();
noStroke();
fill( "#FFF6" );
rect( 0,0, width, height );
pop();
}