let artwork;
let colorArray;
let btnRegen;
function degrees_to_radians(degrees) {
var pi = Math.PI;
return degrees * (pi / 180);
}
function setup() {
createCanvas(windowWidth, windowHeight);
artwork = new Artwork();
setupRegenButton();
artwork.createNew(50, 10, 20);
}
function mousePressed(event) {
btnRegen.onClick();
return false;
}
function draw() {
background(0, 0, 0);
btnRegen.draw();
artwork.display();
}
function windowResized() {
waitress = millis() + 2000;
if (fullscreen()) {
resizeCanvas(displayWidth, displayHeight);
} else {
resizeCanvas(windowWidth, windowHeight);
}
showing = true;
setup();
}
class Artwork {
constructor() {
this.rings = [];
this.centerRadius;
this.baseBandSize;
this.rotationRate = 10;
this.rotationIndex = 0;
}
createNew(numberOfRings, centerRadius, baseBandSize) {
this.centerRadius = centerRadius;
this.baseBandSize = baseBandSize;
for (let i = 0; i < numberOfRings; i++) {
this.rings.push(
new Ring(
i,
i,
this.baseBandSize,
this.centerRadius,
color(random(0, 256), random(0, 256), random(0, 256)),
color(random(0, 256), random(0, 256), random(0, 256))
)
);
}
}
display() {
_.forEach(this.rings, (r) => r.display());
}
}
class Ring {
constructor(
id,
layer,
baseBandSize,
centerRadius,
ringTriangleColor,
ringOuter
) {
this.id = id;
this.layer = layer;
this.baseBandSize = baseBandSize;
this.centerRadius = centerRadius;
this.ringTriangleColor = ringTriangleColor;
this.ringOuter = ringOuter;
this.innerRadius = this.centerRadius + this.layer * this.baseBandSize;
this.outerRadius = this.innerRadius + this.baseBandSize;
this.angle = 0;
this.rateOfChange = 0.25;
this.directionClockwise = this.layer % 2;
this.inverseDensity = 3;
this.maxRotations = 360 / this.inverseDensity;
this.angleFind = 360 / this.maxRotations;
this.tick = [];
this.tickMax = [];
this.tickMin = [];
this.ticksTarget = [];
this.tick.length = this.maxRotations;
this.tickMax.length = this.maxRotations;
this.tickMin.length = this.maxRotations;
this.ticksTarget.length = this.maxRotations;
this.rateOfTickChange = 0.5;
for (let i = 0; i < this.maxRotations; i++) {
this.tick[i] = 0;
let r1 = random(this.innerRadius, this.outerRadius);
let r2 = random(this.innerRadius, this.outerRadius);
this.tickMax[i] = r2 > r1 ? r2 : r1;
this.tickMin[i] = r2 > r1 ? r1 : r2;
this.ticksTarget[i] = 0;
}
}
display() {
noFill();
strokeWeight(1);
this.drawBands();
this.drawTicTockBand();
}
drawBands() {
stroke(this.ringOuter);
ellipse(windowWidth / 2, windowHeight / 2, this.outerRadius * 2);
}
drawTicTockBand() {
if (this.directionClockwise) {
this.angle = (this.angle + this.rateOfChange) % 360;
} else {
this.angle = (this.angle - this.rateOfChange) % 360;
}
for (let i = 0; i < this.maxRotations; i++) {
this.drawTick((this.angle + i * this.angleFind) % 360, this.angleFind, i);
}
}
drawTick(topAngle, angleFind, index) {
let point1 = this.findPointByAngleAndCircle(topAngle, this.innerRadius);
if (this.ticksTarget[index] == 0) {
this.tick[index] = this.tickMin[index];
this.ticksTarget[index] = this.tickMax[index];
}
if (this.tick[index] >= this.tickMax[index]) {
this.ticksTarget[index] = this.tickMin[index];
}
if (this.tick[index] <= this.tickMin[index]) {
this.ticksTarget[index] = this.tickMax[index];
}
if (this.ticksTarget[index] > this.tick[index]) {
this.tick[index] += this.rateOfTickChange;
} else {
this.tick[index] -= this.rateOfTickChange;
}
let point2 = this.findPointByAngleAndCircle(topAngle, this.tick[index]);
line(point1.x, point1.y, point2.x, point2.y);
}
findPointByAngleAndCircle(a, r) {
let x = windowWidth / 2 + r * cos(degrees_to_radians(a));
let y = windowHeight / 2 + r * sin(degrees_to_radians(a));
return { x: x, y: y };
}
}
function setupRegenButton() {
btnRegen = new Button(this);
btnRegen.textColor = color(0, 192, 0);
btnRegen.color = color(64, 64, 64);
btnRegen.y = 10;
btnRegen.x = 10;
btnRegen.width = 50;
btnRegen.height = 30;
btnRegen.text = "REGEN";
btnRegen.rounding = 10;
btnRegen.borderColor = color(256, 256, 0);
btnRegen.borderWidth = 1;
btnRegen.dropShadow = false;
btnRegen.subscribe(() => setup());
}
class Drawable {
constructor() {
this.mouseEnterHandlers = [];
this.mouseLeaveHandlers = [];
this.x = 0;
this.y = 0;
this.height = 100;
this.width = 100;
this.borderWidth = 0;
this.rounding = 0;
this.dropShadow = false;
this.dropShadowOffset = 5;
this.color = undefined;
this.borderColor = undefined;
this.visible = true;
}
draw() {
if (this.visible) {
if (this.dropShadow) {
fill(color(0, 0, 0, 128));
rect(
this.relativeX + this.dropShadowOffset,
this.relativeY + this.dropShadowOffset,
this.width,
this.height,
this.rounding
);
}
fill(this.color);
strokeWeight(this.borderWidth);
if (this.borderColor) {
stroke(this.borderColor);
}
rect(this.relativeX, this.relativeY, this.width, this.height, this.rounding);
strokeWeight(0);
this.onMouseEnter();
this.onMouseLeave();
}
}
get relativeX() {
return this.container ? this.container.relativeX + this.x : this.x;
}
get relativeY() {
return this.container ? this.container.relativeY + this.y : this.y;
}
mouseEnter() {
if (
mouseX > this.relativeX &&
mouseX < this.relativeX + this.width &&
mouseY > this.relativeY &&
mouseY < this.relativeY + this.height
) {
return true;
}
return false;
}
subscribeMouseEnter(fn) {
this.mouseEnterHandlers.push(fn);
}
unsubscribeMouseEnter(fn) {
this.mouseEnterHandlers = this.handlers.filter(function (item) {
if (item !== fn) {
return item;
}
});
}
onMouseEnter() {
this.mouseEnterHandlers.forEach((item) => {
if (this.mouseEnter()) {
item.call(this);
}
});
}
mouseLeave() {
if (
mouseX > this.relativeX &&
mouseX < this.relativeX + this.width &&
mouseY > this.relativeY &&
mouseY < this.relativeY + this.height
) {
return false;
}
return true;
}
subscribeMouseLeave(fn) {
this.mouseLeaveHandlers.push(fn);
}
unsubscribeMouseLeave(fn) {
this.mouseLeaveHandlers = this.handlers.filter(function (item) {
if (item !== fn) {
return item;
}
});
}
onMouseLeave() {
this.mouseLeaveHandlers.forEach((item) => {
if (this.mouseLeave()) {
item.call(this);
}
});
}
}
class Clickable extends Drawable {
constructor() {
super();
this.clickHandlers = [];
}
clicked() {
if (
mouseX > this.relativeX &&
mouseX < this.relativeX + this.width &&
mouseY > this.relativeY &&
mouseY < this.relativeY + this.height
) {
return true;
}
return false;
}
subscribe(fn) {
this.clickHandlers.push(fn);
}
unsubscribe(fn) {
this.clickHandlers = this.handlers.filter(function (item) {
if (item !== fn) {
return item;
}
});
}
onClick() {
this.clickHandlers.forEach((item) => {
if (this.clicked() && this.visible) {
item.call(this);
}
});
}
}
class Button extends Clickable {
constructor() {
super();
this.textSize = 8;
this.text = "";
this.textColor = undefined;
}
draw() {
if (this.visible) {
super.draw();
if (this.textColor) {
fill(this.textColor);
}
textSize(this.textSize);
textAlign(CENTER, CENTER);
text(this.text, this.relativeX, this.relativeY, this.width, this.height);
}
}
}
html,
body {
padding: 0px;
margin: 0px;
overflow: hidden;
}
console