1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
document.addEventListener("DOMContentLoaded", () => {
const canvas = document.getElementById("background");
if (!canvas) return;
const ctx = canvas.getContext("2d");
// Grab config from the embedded <script>
const configEl = document.getElementById("background-config");
const config = configEl ? JSON.parse(configEl.textContent) : {};
// Use config values with defaults as fallback
const spacing = config.spacing ?? 24;
const maxRadius = config.maxRadius ?? 8;
const baseOffset = config.baseOffset ?? 120;
const freq = config.freq ?? 0.008;
const speed = config.speed ?? 0.02;
const baseAmp = config.baseAmp ?? 100;
const env1Freq = config.envelope1Freq ?? 0.002;
const env1Amp = config.envelope1Amp ?? 120;
const env2Freq = config.envelope2Freq ?? 0.0005;
const env2Amp = config.envelope2Amp ?? 200;
let t = parseFloat(localStorage.getItem("waveProgress")) || 0;
let widthCss = window.innerWidth;
let heightCss = window.innerHeight;
let pixelRatio = window.devicePixelRatio || 1;
function resize() {
widthCss = window.innerWidth;
heightCss = window.innerHeight;
pixelRatio = window.devicePixelRatio || 1;
canvas.width = Math.floor(widthCss * pixelRatio);
canvas.height = Math.floor(heightCss * pixelRatio);
canvas.style.width = widthCss + "px";
canvas.style.height = heightCss + "px";
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
}
window.addEventListener("resize", resize);
resize();
function draw() {
const styles = getComputedStyle(document.documentElement);
const fg = styles.getPropertyValue("--fg").trim();
ctx.clearRect(0, 0, widthCss, heightCss);
ctx.fillStyle = fg;
for (let x = 0; x <= widthCss + spacing; x += spacing) {
// envelope: controls crest variance
const envelope =
baseAmp
+ Math.sin(x * env1Freq + t * 0.1) * env1Amp
+ Math.sin(x * env2Freq + t * 0.05) * env2Amp;
const waveY = heightCss - (Math.sin(x * freq + t) * envelope + baseOffset);
// const waveY = Math.max(heightCss - 50, heightCss - (Math.sin(x * freq + t) * envelope + baseOffset));
for (let y = heightCss; y >= 0; y -= spacing) {
const dist = Math.max(0, y - waveY);
const radius = Math.min(maxRadius, dist / 40);
if (radius > 0.2) {
ctx.beginPath();
// ctx.arc(x + spacing / 2, y - spacing / 2, radius, 0, Math.PI * 2);
ctx.fillRect(
x + spacing / 2 - radius,
y - spacing / 2 - radius,
radius * 2,
radius * 2
);
ctx.fill();
}
}
}
t += speed;
localStorage.setItem("waveProgress", t);
requestAnimationFrame(draw);
}
draw();
});
|