WORK 67
つく
Points set out from different distances toward the same single place. Some are already standing there and never draw a line at all. Every trail is polished away at one rate for everyone, so the far end of a long route goes first and what is left floats free of both its origin and its destination. Whether a point came a long way or was there from the start cannot be read from where it ended up.
いくつかの点が、それぞれ違う距離から同じ一点へ向かう。はじめからそこに立っていて、線を一本も引かないものもいる。跡は誰の分も同じ速さで褪せていくので、長い道ほど遠い側から先に消え、残った断片は出発点からも到着点からも切り離されて宙に浮く。長い道を来たのか、はじめからそこにいたのかは、着いた先からは読めない。
出発点は毎回ちがう。着く場所はいつも同じ。
跡は、引かれた側から順に、同じ速さで薄くなっていく。速く消えるものも、残るものもない。だから絵の中には「どれくらい遠くから来たか」を測る目盛りが一つも無い。見ているあいだは分かる——長い線と、線を一本も持たない点が、同時に画面にいる。けれど最後まで見ると、その差が画面から抜けていく。
中心まで届いている線と、どこにも繋がっていない線分が、同じ画面に並ぶ。前者は着いたもので、後者はまだ途中のものだ。けれど断片だけを見ても、それが向かっているのか、もう消えたあとなのかは分からない。
はじめからそこにいた点は、待っているようには見えない。ただ、そこにいる。
const SIZE = 720;
const N = 40;
const SPEED = 1.0;
const FADE = 2; // the trail is polished away at one rate for everyone
const SETTLE = 260; // how long an arrived point stays before it is replaced
export default function sketch(p) {
let pts = [];
let cx, cy;
// a point either starts far out, or is already standing on the destination
const spawn = (stagger) => {
const already = p.random() < 0.16;
const a = p.random(p.TWO_PI);
const r = already ? 0 : p.random(70, SIZE * 0.46);
return {
x: cx + Math.cos(a) * r,
y: cy + Math.sin(a) * r,
r0: r,
arrived: already,
rest: already ? Math.floor(p.random(SETTLE)) : 0,
wait: stagger,
bend: p.random(-0.55, 0.55),
};
};
p.setup = () => {
p.createCanvas(SIZE, SIZE);
const d = new Date();
const seed = d.getFullYear() * 10000 + (d.getMonth() + 1) * 100 + d.getDate();
p.noiseSeed(seed);
p.randomSeed(seed);
p.strokeCap(p.ROUND);
p.background(9, 9, 11);
cx = SIZE / 2;
cy = SIZE / 2;
pts = [];
for (let i = 0; i < N; i++) pts.push(spawn(Math.floor(p.random(0, 520))));
};
p.draw = () => {
p.noStroke();
p.fill(9, 9, 11, FADE);
p.rect(0, 0, SIZE, SIZE);
for (let i = 0; i < pts.length; i++) {
const q = pts[i];
if (q.wait > 0) { q.wait--; continue; }
if (q.arrived) {
q.rest++;
p.noStroke();
p.fill(240, 242, 248, 34);
p.circle(cx, cy, 4.2);
if (q.rest > SETTLE) pts[i] = spawn(Math.floor(p.random(0, 240)));
continue;
}
const dx = cx - q.x;
const dy = cy - q.y;
const d = Math.hypot(dx, dy);
if (d < SPEED * 1.5) {
q.x = cx; q.y = cy; q.arrived = true; q.rest = 0;
continue;
}
const px = q.x, py = q.y;
const ang = Math.atan2(dy, dx) + q.bend * (d / SIZE) * 0.9;
q.x += Math.cos(ang) * SPEED;
q.y += Math.sin(ang) * SPEED;
p.stroke(232, 234, 240, 205);
p.strokeWeight(1.3);
p.line(px, py, q.x, q.y);
}
};
}