xxxxxxxxxx
387
let canvasW = 400;
let canvasH = 400;
let hudHeight = 40;
let minRadius = 40;
let maxRadius;
let minCenterX;
let maxCenterX;
let minCenterY;
let maxCenterY;
let centerX = canvasW / 2;
let centerY = 0;
let radius = 0;
let rayLength;
let hovering = false;
let pressing = false;
let holding = false;
let downDX;
let downDY;
let angle;
let handleRadius = 6;
let white;
let lineColor;
let defaultHandleColor;
let hoveringHandleColor;
let holdingHandleColor;
let radiusColor;
let shadowColor;
let hudColor;
let backgroundColor;
let toCenterX;
let toCenterY;
let toRadius;
let fromCenterX;
let fromCenterY;
let fromRadius;
let easing = true;
let easeCounter = 0;
let easeFrames = 20;
function setup()
{
createCanvas(400, 400);
if (canvasW === canvasH || min(canvasW, canvasH) === canvasH)
maxRadius = (canvasH - hudHeight) / 2 - handleRadius;
else
maxRadius = canvasW / 2 - handleRadius;
rayLength = sqrt(canvasW * canvasW + canvasH * canvasH);
white = color(255);
lineColor = color(255, 100);
defaultHandleColor = white;
hoveringHandleColor = color(20, 200, 120);
holdingHandleColor = color(250, 40, 60);
radiusColor = color(250, 220, 20);
shadowColor = color(0, 200);
hudColor = color(0, 100);
backgroundColor = color(40);
angle = QUARTER_PI;
Begin();
}
function draw()
{
background(backgroundColor);
let x = centerX + radius * cos(angle);
let y = centerY - radius * sin(angle);
let mouseDX = mouseX - x;
let mouseDY = mouseY - y;
let mouseDSq = mouseDX * mouseDX + mouseDY * mouseDY;
hovering = mouseDSq <= handleRadius * handleRadius;
if (easing)
{
Ease();
}
else
{
if (pressing)
{
if (!(mouseIsPressed && mouseButton === LEFT))
{
EndPressing();
}
}
else
{
if (mouseIsPressed && mouseButton === LEFT)
{
BeginPressing(x, y);
}
}
if (holding)
{
if (pressing)
{
// move the segment
x = mouseX - downDX;
y = mouseY - downDY;
if (x < 0)
x = 0;
else if (x > canvasW)
x = canvasW;
if (y < hudHeight)
y = hudHeight;
else if (y > canvasH)
y = canvasH;
let centerToX = x - centerX;
let centerToY = y - centerY;
let distanceToCenter = dist(centerX, centerY, x, y);
let normalizedX = centerToX / distanceToCenter;
let normalizedY = -centerToY / distanceToCenter;
angle = atan2(normalizedY, normalizedX);
x = centerX + normalizedX * radius;
y = centerY - normalizedY * radius;
}
else
{
EndHolding();
}
}
else
{
if (pressing)
{
let downDSq = downDX * downDX + downDY * downDY;
if (downDSq <= handleRadius * handleRadius)
{
BeginHolding();
}
}
}
}
DrawCircle();
DrawRay();
DrawCenter();
DrawHandle(x, y);
PrintRadius(x, y);
DrawHud();
}
function keyPressed()
{
if (easing)
return;
if (keyCode === 32)
Begin();
}
function Begin()
{
toRadius = round(random(minRadius, maxRadius), 2);
minCenterX = toRadius + handleRadius;
maxCenterX = canvasW - minCenterX;
minCenterY = toRadius + hudHeight + handleRadius;
maxCenterY = canvasH - (toRadius + handleRadius);
toCenterX = random(minCenterX, maxCenterX);
toCenterY = random(minCenterY, maxCenterY);
BeginEasing();
}
function DrawCircle()
{
push();
noFill();
stroke(lineColor);
strokeWeight(2);
circle(centerX, centerY, radius * 2);
pop();
}
function DrawRay()
{
let cosine = cos(angle);
let sine = sin(angle);
let x = centerX + radius * cosine;
let y = centerY - radius * sine;
let rayX = centerX + cosine * rayLength;
let rayY = centerY - sine * rayLength;
push();
stroke(250, 40, 40, 200);
strokeWeight(2);
line(centerX, centerY, x, centerY);
stroke(40, 40, 250, 200);
line(x, centerY, x, y);
stroke(lineColor);
strokeWeight(2);
line(x, y, rayX, rayY);
stroke(radiusColor);
strokeWeight(4);
line(centerX, centerY, x, y);
pop();
}
function DrawCenter()
{
push();
stroke(white);
strokeWeight(6);
point(centerX, centerY);
pop();
}
function DrawHandle(x, y)
{
if (holding)
DrawHoldingHandle(x, y);
else if (hovering)
DrawHoveringHandle(x, y);
else
DrawDefaultHandle(x, y);
}
function DrawDefaultHandle(x, y)
{
push();
stroke(defaultHandleColor);
strokeWeight(handleRadius * 2);
point(x, y);
pop();
}
function DrawHoveringHandle(x, y)
{
push();
stroke(hoveringHandleColor);
strokeWeight(handleRadius * 2 + 2);
point(x, y);
pop();
}
function DrawHoldingHandle(x, y)
{
push();
stroke(holdingHandleColor);
strokeWeight(handleRadius * 2);
point(x, y);
pop();
}
function PrintRadius(x, y)
{
let rotationAngle = angle;
if (rotationAngle < -HALF_PI)
rotationAngle += PI;
else if (rotationAngle > HALF_PI)
rotationAngle -= PI;
let radiusMidX = (centerX + x) / 2;
let radiusMidY = (centerY + y) / 2;
let radiusText = round(radius, 1).toLocaleString(
undefined, {minimumFractionDigits: 1});
push();
textAlign(CENTER, CENTER);
textSize(16);
translate(radiusMidX, radiusMidY);
rotate(-rotationAngle);
ShadowText(radiusText, 0, 0);
pop();
}
function BeginPressing(x, y)
{
pressing = true;
downDX = mouseX - x;
downDY = mouseY - y;
}
function EndPressing()
{
pressing = false;
downDX = undefined;
downDY = undefined;
}
function BeginHolding()
{
holding = true;
}
function EndHolding()
{
holding = false;
}
function BeginEasing()
{
easing = true;
easeCounter = 0;
fromCenterX = centerX;
fromCenterY = centerY;
fromRadius = radius;
}
function Ease()
{
function a(t) { return pow(t, 2.0); }
function b(t) { return 1 - a(1 - t); }
++easeCounter;
let t = easeCounter / easeFrames;
let interpolant = t < 0.5 ? a(2 * t) / 2 : b(2 * t - 1) / 2 + 0.5;
centerX = lerp(fromCenterX, toCenterX, interpolant);
centerY = lerp(fromCenterY, toCenterY, interpolant);
radius = lerp(fromRadius, toRadius, interpolant);
if (easeCounter >= easeFrames)
EndEasing();
}
function EndEasing()
{
easing = false;
centerX = toCenterX;
centerY = toCenterY;
radius = toRadius;
}
function DrawHud()
{
let canvasCenterX = canvasW / 2;
let radiusString = radius.toLocaleString(
undefined, {minimumFractionDigits: 2});
push();
noStroke();
fill(hudColor);
rect(0, 0, canvasW, hudHeight);
textAlign(CENTER, CENTER);
textSize(12);
ShadowText("Circle Radius", canvasCenterX, 12);
textSize(16);
ShadowText(radiusString, canvasCenterX, 28, radiusColor);
pop();
}
function ShadowText(str, x, y, textColor = white)
{
textStyle(BOLD);
fill(shadowColor);
stroke(shadowColor);
strokeWeight(4);
text(str, x + 1, y + 1);
fill(textColor);
noStroke();
text(str, x, y);
}