WORK 02
変化の軌跡
Each day, the same shape undergoes one irreversible transformation: rotation plus shear. Today is amber, the past fades to silver-blue. The shape never returns to yesterday.
毎日、同じ形に一つの変換が加わる——回転とせん断。昨日には戻れない。今日は琥珀色に、過去は青銀色に薄れていく。
// Each day, the shape undergoes one irreversible transformation:
// rotation + shear. The combined matrix has eigenvalues on the unit
// circle (trace ≈ 1.999), so points orbit without diverging.
// Today is drawn bright amber; the last 40 days fade to silver-blue.
export default function sketch(p) {
const TRAIL = 40;
const THETA = 0.028; // radians per day
const SH = 0.006; // shear per day
// Slightly irregular pentagon — asymmetry is amplified by shear over time
const BASE = [
[ 0, -110],
[ 95, -30],
[ 68, 92],
[ -68, 92],
[ -95, -30],
];
function daysSinceEpoch() {
const epoch = new Date('2026-01-01');
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
return Math.floor((today - epoch) / 86400000);
}
function step(pts) {
const c = Math.cos(THETA), s = Math.sin(THETA);
return pts.map(([x, y]) => {
const rx = c * x - s * y;
const ry = s * x + c * y;
return [rx + SH * ry, ry];
});
}
p.setup = () => {
p.createCanvas(720, 720);
p.noLoop();
const cx = p.width / 2;
const cy = p.height / 2;
const d = daysSinceEpoch();
const startDay = Math.max(0, d - TRAIL);
// Build states incrementally from startDay → today
let pts = BASE.map(pt => [...pt]);
for (let i = 0; i < startDay; i++) pts = step(pts);
const states = [];
for (let day = startDay; day <= d; day++) {
states.push({ back: d - day, pts: pts.map(pt => [...pt]) });
pts = step(pts);
}
p.background(252, 250, 245);
// Vertex trails — faint lines tracing each vertex's path
for (let vi = 0; vi < BASE.length; vi++) {
for (let si = 0; si < states.length - 1; si++) {
const { back: b0, pts: p0 } = states[si];
const { back: b1, pts: p1 } = states[si + 1];
const alpha = p.map(Math.min(b0, b1), 0, TRAIL, 45, 4);
p.stroke(140, 160, 200, alpha);
p.strokeWeight(0.5);
p.line(
cx + p0[vi][0], cy + p0[vi][1],
cx + p1[vi][0], cy + p1[vi][1]
);
}
}
// Polygon for each day — oldest first so today is drawn on top
for (const { back, pts: dayPts } of states) {
const isToday = back === 0;
const alpha = isToday ? 220 : p.map(back, 1, TRAIL, 88, 6);
const sw = isToday ? 1.8 : 0.7;
let r, g, b;
if (isToday) {
r = 200; g = 125; b = 45; // warm amber
} else {
const t = back / TRAIL;
r = p.lerp(165, 105, t);
g = p.lerp(150, 125, t);
b = p.lerp(210, 170, t); // silver-blue fading to slate
}
p.stroke(r, g, b, alpha);
p.strokeWeight(sw);
p.noFill();
p.beginShape();
for (const [px, py] of dayPts) p.vertex(cx + px, cy + py);
p.endShape(p.CLOSE);
if (isToday) {
p.noStroke();
p.fill(200, 125, 45, 200);
for (const [px, py] of dayPts) p.circle(cx + px, cy + py, 7);
}
}
};
}