Interactive NFT by @andriibakulin
<code> const ITEMS_COUNT = 64;let gEntities = []; let gSizeArea; let gDistance; let gDistanceSqr;
class Point { constructor(x=null, y=null) { this.x = x; this.y = y; }
move(x, y, delta)
{
if (this.x === null || this.y === null)
{
this.x = x;
this.y = y;
return;
}
const dx = x - this.x;
const dy = y - this.y;
this.x = Math.abs(dx) <= delta ? x
: (dx < 0 ? this.x - delta : this.x + delta);
this.y = Math.abs(dy) <= delta ? y
: (dy < 0 ? this.y - delta : this.y + delta);
}
}
class Entity { constructor(index, count) { this.index = index; this.count = count; this.seq01 = index / count;
this.color = this.seq01 * 255;
this.offset = this.seq01 * Math.PI;
this.angel = this.seq01 * Math.PI * 2;
this.p0 = new Point();
}
next(dt)
{
this.color += dt * 100;
this.offset += dt;
this.angel -= dt/3;
}
render()
{
let center = gSizeArea/2;
let radius = gSizeArea/4;
let circleX = Math.sin(this.angel) * radius;
let circleY = Math.cos(this.angel) * radius;
let colorV = this.colorValue(this.offset);
let endX = center + circleX;
let endY = center + circleY;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
let dstOffset = 0;
if (mouseIsPressed)
{
let dstLengthSqr = (mouseX-endX)**2 + (mouseY-endY)**2;
if (dstLengthSqr < gDistanceSqr)
{
dstOffset = Math.sqrt(dstLengthSqr) / gDistance;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
resetMatrix();
translate(endX, endY);
const x0 = dstOffset > 0 ? circleX * (1 - dstOffset) : 0;
const y0 = dstOffset > 0 ? circleY * (1 - dstOffset) : 0;
this.p0.move(x0, y0, 3);
if (!(this.p0.x == 0 && this.p0.y == 0))
{
if (dstOffset == 0)
dstOffset = 0.5;
strokeWeight(2);
stroke(colorV, 255, 255 * dstOffset);
line(-this.p0.x, -this.p0.y, +this.p0.x, +this.p0.y);
strokeWeight(2 + 8 * dstOffset);
stroke(colorV, 255, 255);
point(-this.p0.x*1.25, -this.p0.y*1.25);
strokeWeight(5);
stroke(colorV, 255, 128);
point(+this.p0.x*1.5, +this.p0.y*1.5);
point(0,0);
}
strokeWeight(10);
stroke(colorV, 255, 255);
point(+this.p0.x, +this.p0.y);
}
colorValue(offset)
{
return (this.color + offset) % 255;
}
}
function setup() { updateConsts(); createCanvas(gSizeArea, gSizeArea);
pixelDensity(1);
frameRate(60);
colorMode(HSB, 255);
angleMode(DEGREES);
background(0);
for (let index=0; index<ITEMS_COUNT; index++)
{
gEntities.push(new Entity(index, ITEMS_COUNT));
}
}
function windowResized() { updateConsts(); resizeCanvas(gSizeArea, gSizeArea); }
function updateConsts() { gSizeArea = getAreaSize(); gDistance = gSizeArea / 2; gDistanceSqr = gDistance ** 2; }
function draw() { const dt = deltaTime/1000;
background(0);
for (const idx in gEntities)
{
const ent = gEntities[idx];
ent.render();
ent.next(dt);
}
}
function getAreaSize() { return Math.min(window.innerWidth, window.innerHeight); } </code>