xxxxxxxxxx
456
let samples = [];
let timer = 0;
let period = 0.5;
let graphSpeed = 2;
let margin = 40;
let needleHeight = 40;
let canvasH = 400;
let minY = margin + 10;
let maxY = canvasH - minY;
let needleBaseY = canvasH / 2;
let needleAmplitude = needleBaseY - minY;
let angle = 0;
let scroll = 0;
let majorGrid = 100;
let minorGridDivisions = 5;
let minorGrid = majorGrid / minorGridDivisions;
let shift = 0;
let shiftSpeed = 0;
let minShiftSpeed = -graphSpeed * 0.8;
let maxShiftSpeed = graphSpeed * 2;
let shiftAcceleration = 0.1;
let minH = 240;
let minS = 50;
let minV = 90;
let midH = 120;
let midS = 10;
let midV = 40;
let maxH = 0;
let maxS = 80;
let maxV = 90;
let canvasW;
let needleLength;
let needleInterceptX;
let needleBaseX;
let shiftMax;
let shiftMin;
let maxAngle;
let minAngle;
let needleTipX;
let needleTipY;
let nA;
let nB;
let nC;
let nD;
let nE;
let nF;
let pivot;
let shafadientL;
let shadeGradientR;
let prevTouches;
function preload()
{
shadeGradientL = loadImage("ShadeGradientL.png");
shadeGradientR = loadImage("ShadeGradientR.png");
}
function setup()
{
canvasW = windowWidth;
createCanvas(canvasW, canvasH);
angleMode(RADIANS);
needleLength = canvasW - 3.6 * margin;
needleInterceptX = canvasW / 2;
needleBaseX = needleInterceptX - needleLength;
shiftMax = canvasW / 2 - margin * 1.8;
shiftMin = -shiftMax;
maxAngle = asin(needleAmplitude / needleLength);
minAngle = -maxAngle;
// c *----____
// | ----____
// | * b
// | \
// d * - - - - - - - - - * a
// | /
// | ____ * f
// | ____----
// e *----
nA = { x: needleInterceptX + 4 - 0.5, y: needleBaseY - 0.5 };
nB = { x: needleInterceptX - 0.5, y: needleBaseY - 4 - 0.5 };
nC = { x: needleBaseX - 0.5, y: needleBaseY - 10 - 0.5 };
nD = { x: needleBaseX - 4 - 0.5, y: needleBaseY - 0.5 };
nE = { x: needleBaseX - 0.5, y: needleBaseY + 10 - 0.5 };
nF = { x: needleInterceptX - 0.5, y: needleBaseY + 4 - 0.5 };
pivot = { x: needleBaseX - 0.5, y: needleBaseY - 0.5 };
}
function Reset()
{
timer = 0;
shift = 0;
shiftSpeed = 0;
scroll = 0;
samples = [];
}
function draw()
{
background(240, 235, 200);
// background(40);
let inputReceived = false;
if (RightInput())
{
shiftSpeed += shiftAcceleration;
inputReceived = true;
}
if (LeftInput())
{
shiftSpeed -= shiftAcceleration;
inputReceived = true;
}
if (!inputReceived)
{
if (shiftSpeed > 0)
shiftSpeed = max(0, shiftSpeed - shiftAcceleration);
else
shiftSpeed = min(0, shiftSpeed + shiftAcceleration);
}
shiftSpeed = constrain(shiftSpeed, minShiftSpeed, maxShiftSpeed);
shift += shiftSpeed;
if (shift > shiftMax)
{
shift = shiftMax;
shiftSpeed = 0;
}
else if (shift < shiftMin)
{
shift = shiftMin;
shiftSpeed = 0;
}
angle = Vary(timer);
needleTipX = needleBaseX + shift + needleLength * cos(angle);
needleTipY = needleBaseY + needleLength * sin(angle);
let sample = {};
sample.x = needleTipX;
sample.y = needleTipY;
sample.t = shiftSpeed / (shiftSpeed < 0 ? -minShiftSpeed :
maxShiftSpeed);
samples.push(sample);
DrawGrid();
DrawGraph();
DrawShade();
DrawNeedle();
timer = (timer + Dt()) % period;
}
function RightInput()
{
if (shift > shiftMax) return false;
let key = keyIsDown(RIGHT_ARROW);
let touch = touches.length < 0 && touches[0].x > width * 2 / 3;
let mouse = mouseIsPressed && mouseX > width * 2 / 3;
return key || touch || mouse;
}
function LeftInput()
{
if (shift < shiftMin) return false;
let key = keyIsDown(LEFT_ARROW);
let touch = touches.length < 0 && touches[0].x < width / 3;
let mouse = mouseIsPressed && mouseX < width / 3;
return key || touch || mouse;
}
function Vary(t)
{
let range = maxAngle - minAngle;
let trig = (1 - sin(TAU * timer / period)) / 2;
return range * trig + minAngle;
}
function DrawGrid()
{
let halfH = height / 2;
let minorRowCount = int(halfH / minorGrid);
let majorRowCount = int(halfH / majorGrid);
let minorColCount = int(width / minorGrid) + majorGrid / minorGrid;
let majorColCount = int(width / majorGrid) + 2;
stroke(10, 30, 250, 60);
// stroke(255, 60);
strokeWeight(1);
let x;
let y;
let yOffset;
for (let i = 0; i < minorRowCount; ++i)
{
yOffset = (i + 1) * minorGrid;
y = needleBaseY - yOffset;
line(0, y - 0.5, width, y - 0.5);
y = needleBaseY + yOffset;
line(0, y - 0.5, width, y - 0.5);
}
for (let i = 0; i < minorColCount; ++i)
{
x = i * minorGrid - scroll;
line(x - 0.5, 0, x - 0.5, height);
}
strokeWeight(2);
for (let i = 0; i < majorRowCount; ++i)
{
yOffset = (i + 1) * majorGrid;
y = needleBaseY - yOffset;
line(0, y - 0.5, width, y - 0.5);
y = needleBaseY + yOffset;
line(0, y - 0.5, width, y - 0.5);
}
for (let i = 0; i < majorColCount; ++i)
{
x = i * majorGrid - scroll;
line(x - 0.5, 0, x - 0.5, height);
}
stroke(200, 10, 100, 80);
// stroke(200, 10, 100, 200);
strokeWeight(3);
line(0, needleBaseY - 0.5, width, needleBaseY - 0.5);
scroll = (scroll + graphSpeed) % majorGrid;
}
function DrawGraph()
{
let newSamples = [];
strokeWeight(2);
push();
colorMode(HSB);
for (let i = 0; i < samples.length; ++i)
{
let a = samples[i];
if (i < samples.length - 1)
{
let b = samples[i + 1];
Connect(a, b);
}
a.x -= graphSpeed;
if (a.x >= -graphSpeed)
newSamples.push(a);
}
pop();
samples = newSamples;
}
function DrawShade()
{
image(shadeGradientL, 2 * margin, 0, -2 * margin, height);
image(shadeGradientR, width - 2 * margin, 0, 2 * margin, height);
}
function DrawNeedle()
{
//
// c *----____
// | ----____
// | * b
// | \
// d * - - - - - - - - - * a
// | /
// | ____ * f
// | ____----
// e *----
//
let a = RotatePoint(nA, angle, pivot);
let b = RotatePoint(nB, angle, pivot);
let c = RotatePoint(nC, angle, pivot);
let d = RotatePoint(nD, angle, pivot);
let e = RotatePoint(nE, angle, pivot);
let f = RotatePoint(nF, angle, pivot);
a.x += shift;
b.x += shift;
c.x += shift;
d.x += shift;
e.x += shift;
f.x += shift;
// shadow
noStroke();
fill(0, 80);
beginShape();
{
vertex(a.x, a.y);
vertex(b.x, b.y);
vertex(c.x, c.y);
vertex(d.x, d.y);
vertex(e.x, e.y);
vertex(f.x, f.y);
}
endShape(CLOSE);
// stylus
let upperTipY = needleTipY - needleHeight;
stroke(100);
strokeWeight(4);
line(needleTipX, needleTipY, needleTipX, upperTipY);
// needle
a.y -= needleHeight;
b.y -= needleHeight;
c.y -= needleHeight;
d.y -= needleHeight;
e.y -= needleHeight;
f.y -= needleHeight;
noStroke();
fill(240, 100, 80);
beginShape();
{
vertex(a.x, a.y);
vertex(b.x, b.y);
vertex(c.x, c.y);
vertex(d.x, d.y);
vertex(e.x, e.y);
vertex(f.x, f.y);
}
endShape(CLOSE);
fill(240 * 0.7, 100 * 0.7, 80 * 0.7);
quad(d.x, d.y, e.x, e.y, f.x, f.y, a.x, a.y);
}
function Connect(a, b)
{
let h, s, v;
let t = b.t;
if (t < 0)
{
t = -t;
h = lerp(midH, minH, t);
s = lerp(midS, minS, t);
v = lerp(midV, minV, t);
}
else
{
h = lerp(midH, maxH, t);
s = lerp(midS, maxS, t);
v = lerp(midV, maxV, t);
}
stroke(h, s, v);
line(a.x - 0.5, a.y - 0.5, b.x - 0.5, b.y - 0.5);
}
function RotatePoint(p, angle, pivot)
{
let output = { x: p.x, y: p.y };
let s = sin(angle);
let c = cos(angle);
output.x -= pivot.x;
output.y -= pivot.y;
let x = output.x * c - output.y * s;
let y = output.x * s + output.y * c;
output.x = x + pivot.x;
output.y = y + pivot.y;
return output;
}
function keyPressed()
{
if (keyCode === 32) // Spacebar
TogglePause();
if (keyCode === ENTER)
Step();
if (keyCode === 82) // R
Reset();
}
function TogglePause()
{
if (isLooping())
Pause();
else
Unpause();
}
function Pause()
{
noLoop();
}
function Unpause()
{
loop();
}
function Step()
{
if (isLooping()) return;
redraw();
}
function Dt() { return 1.0 / 60.0; }