diff --git a/deploy/site/ambient.js b/deploy/site/ambient.js
index 790f879..eb49625 100644
--- a/deploy/site/ambient.js
+++ b/deploy/site/ambient.js
@@ -9,7 +9,7 @@
};
}
function createCurrent() {
- return { sequence: 0n, shards: [], from: 0, to: 0, at: 0 };
+ return { sequence: 0n, seed: 0n, entropy: 0n, width: 390, height: 900, shards: [], from: 0, to: 0, at: 0 };
}
function progress(current, now) {
return Math.max(0, Math.min(1, (now - current.at) / 5000));
@@ -20,15 +20,16 @@
function lightAt(shard, t) {
return shard.light + (shard.target - shard.light) * t;
}
- function makeShards(sequence) {
+ function makeShards(sequence, width, height) {
const random = randomFrom(sequence);
const points = [];
- const columns = 5, rows = 9;
+ const columns = Math.max(3, Math.min(24, Math.ceil(width / 120)));
+ const rows = Math.max(4, Math.min(16, Math.ceil(height / 115)));
for (let row = 0; row <= rows; row++) {
for (let col = 0; col <= columns; col++) {
points.push([
- (col + (col && col < columns ? (random() - .5) * .85 : 0)) / columns,
- (row + (row && row < rows ? (random() - .5) * .85 : 0)) / rows,
+ (col + (col && col < columns ? (random() - .5) * .45 : 0)) / columns,
+ (row + (row && row < rows ? (random() - .5) * .45 : 0)) / rows,
]);
}
}
@@ -45,12 +46,23 @@
}
return shards;
}
+ function resizeCurrent(current, width, height) {
+ if (current.width === width && current.height === height) return;
+ current.width = width; current.height = height;
+ if (current.sequence === 0n) return;
+ current.shards = makeShards(current.seed, width, height);
+ const random = randomFrom(current.entropy);
+ for (const shard of current.shards) {
+ shard.light = shard.target = current.entropy === 0n ? 0 : random() ** 4;
+ }
+ }
function receive(current, sequence, now, entropy = 0n) {
if (sequence <= 0n || sequence === current.sequence) return false;
const fresh = current.sequence === 0n || sequence < current.sequence;
const t = progress(current, now);
const delta = fresh ? 0 : Number(sequence - current.sequence > 5000n ? 5000n : sequence - current.sequence);
- if (fresh) current.shards = makeShards(sequence);
+ if (fresh) { current.seed = sequence; current.shards = makeShards(sequence, current.width, current.height); }
+ current.entropy = entropy;
const random = randomFrom(entropy);
for (const shard of current.shards) {
shard.light = lightAt(shard, t);
@@ -66,7 +78,7 @@
for (let i = 0; i < message.length; i++) seed = Math.imul(seed ^ message.charCodeAt(i), 16777619);
return seed >>> 0;
}
- if (typeof module !== 'undefined') module.exports = { createCurrent, position, receive, absorb };
+ if (typeof module !== 'undefined') module.exports = { createCurrent, position, receive, absorb, resizeCurrent };
if (typeof document === 'undefined') return;
const canvas = document.querySelector('canvas[data-current]');
if (!canvas) return;
@@ -97,20 +109,30 @@
const [a, b, c] = points;
context.beginPath();
context.moveTo(...a); context.lineTo(...b); context.lineTo(...c); context.closePath();
- const centerX = (a[0] + b[0] + c[0]) / 3, centerY = (a[1] + b[1] + c[1]) / 3;
- const angle = shard.tint * Math.PI + phase * 2;
- const reach = Math.min(width, height) * .22;
- const dx = Math.cos(angle) * reach, dy = Math.sin(angle) * reach;
- const glass = context.createLinearGradient(centerX - dx, centerY - dy, centerX + dx, centerY + dy);
- glass.addColorStop(0, `rgba(${pigment},.015)`);
- glass.addColorStop(.48, `rgba(${pigment},${.035 + light * .23})`);
- glass.addColorStop(.52, `rgba(${pigment},${.018 + light * .06})`);
- glass.addColorStop(1, `rgba(${pigment},.008)`);
- context.fillStyle = glass; context.fill();
- context.strokeStyle = 'rgba(74,105,112,.09)'; context.lineWidth = .5; context.stroke();
+ context.fillStyle = `rgba(${pigment},${.012 + light * .025})`;
+ context.fill();
+ context.save(); context.clip();
+ const offset = (shard.tint - .5) * 14;
+ for (let channel = 0; channel < 4; channel++) {
+ context.beginPath();
+ for (let step = 0; step <= 24; step++) {
+ const x = step / 24 * width;
+ const y = height * (.15 + channel * .23) +
+ Math.sin(x / 430 - phase * 5 + channel * 1.7) * 35 +
+ Math.sin(x / 190 + channel - phase * 2) * 8 + offset;
+ if (step === 0) context.moveTo(x, y); else context.lineTo(x, y);
+ }
+ context.strokeStyle = `rgba(${pigment},${.018 + light * .08})`;
+ context.lineWidth = 10 + shard.tint * 14;
+ context.stroke();
+ context.strokeStyle = `rgba(147,179,171,${.015 + light * .06})`;
+ context.lineWidth = 1.1;
+ context.stroke();
+ }
+ context.restore();
context.beginPath(); context.moveTo(...a); context.lineTo(...b);
- context.strokeStyle = `rgba(155,183,175,${.025 + light * .2})`;
- context.lineWidth = .65; context.stroke();
+ context.strokeStyle = `rgba(155,183,175,${.012 + light * .075})`;
+ context.lineWidth = .45; context.stroke();
}
}
function animate(now) {
@@ -126,6 +148,7 @@
function resize() {
const ratio = Math.min(devicePixelRatio || 1, 2);
width = canvas.clientWidth; height = canvas.clientHeight;
+ resizeCurrent(current, width, height);
canvas.width = Math.round(width * ratio); canvas.height = Math.round(height * ratio);
context.setTransform(ratio, 0, 0, ratio, 0, 0);
paint(performance.now());
diff --git a/deploy/site/index.html b/deploy/site/index.html
index 08309b2..6fbb558 100644
--- a/deploy/site/index.html
+++ b/deploy/site/index.html
@@ -81,7 +81,7 @@ footer .icon{width:11px;height:11px;vertical-align:-1px;margin-right:.6ch}
source
-
+