summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--site/themes/sine/static/js/background.js216
-rw-r--r--site/themes/sine/static/js/old-background.js82
-rw-r--r--site/themes/sine/static/js/oldish-background.js90
3 files changed, 309 insertions, 79 deletions
diff --git a/site/themes/sine/static/js/background.js b/site/themes/sine/static/js/background.js
index e9b61a2..174820a 100644
--- a/site/themes/sine/static/js/background.js
+++ b/site/themes/sine/static/js/background.js
@@ -1,82 +1,140 @@
-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);
+const canvas = document.getElementById("background");
+const ctx = canvas.getContext("2d");
+
+// Resize Handling
+
+function resizeCanvas() {
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+}
+
+resizeCanvas();
+window.addEventListener("resize", resizeCanvas);
+
+// Custom Math Functions
+
+function customFunction(x, t, c) {
+ const centerY = c.height / 2;
+
+ return centerY + (30 + 10 * Math.sin(0.05 * t)) *
+ Math.sin(0.006 * x - 0.4 * t) +
+ 20 * Math.sin(0.011 * x - 0.25 * t + 2);
+}
+
+function customFunctionTwo(x, t, c) {
+ const centerY = c.height / 2;
+
+ return centerY + (
+ 40 * Math.sin(0.005 * x - 0.6 * t) +
+ 25 * Math.sin(0.009 * x - 0.35 * t + 2) +
+ 15 * Math.sin(0.015 * x - 0.2 * t + 5)
+ );
+}
+
+// Math Function Drawing Engine
+
+// Get time from localstorage if it exists
+let time = parseFloat(localStorage.getItem("time")) || 0;
+
+function drawFunction(fn, color) {
+
+ ctx.beginPath();
+
+ // Start at left edge
+ ctx.moveTo(0, fn(0, time, canvas));
+
+ // Plot function across entire width
+ for (let x = 0; x < canvas.width; x++) {
+ const y = fn(x, time, canvas);
+ ctx.lineTo(x, y);
+ }
+
+ ctx.strokeStyle = color;
+ ctx.lineWidth = 2;
+ ctx.stroke();
+}
+
+// Starfield Drawing Engine
+
+function makeStarfield(width, height, count, seed = 1) {
+ function rng() {
+ seed |= 0;
+ seed = seed + 0x6D2B79F5 | 0;
+ let t = Math.imul(seed ^ seed >>> 15, 1 | seed);
+ t ^= t + Math.imul(t ^ t >>> 7, 61 | t);
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
+ }
+
+ const stars = [];
+
+ for (let i = 0; i < count; i++) {
+ stars.push({
+ x: rng() * width,
+ y: rng() * height,
+ size: rng() * 1.5 + 0.3,
+ base: 0.5 + rng() * 0.3,
+ phase: rng() * Math.PI * 2,
+ speed: 0.5 + rng() * 2.0
+ });
+ }
+
+ return stars;
+}
+
+function drawStars(ctx, stars, time, color) {
+ ctx.fillStyle = color;
+
+ for (const s of stars) {
+ const twinkle = Math.sin(time * s.speed + s.phase) * 0.5 + 0.5;
+ const alpha = s.base + twinkle * 0.5;
+
+ ctx.globalAlpha = alpha;
+ ctx.fillRect(s.x, s.y, s.size, s.size);
}
- 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);
+
+ ctx.globalAlpha = 1;
+}
+
+// Animation Loop
+
+let animationId = null;
+let lastTime = 0;
+
+const stars = makeStarfield(canvas.width, canvas.height, 600, 42);
+
+function animate(timestamp) {
+ animationId = requestAnimationFrame(animate);
+
+ // First frame setup
+ if (!lastTime) {
+ lastTime = timestamp;
}
- draw();
-});
+ // Time difference in seconds
+ const delta = (timestamp - lastTime) / 1000;
+ lastTime = timestamp;
+
+ // Advance time
+ time += delta;
+
+ // save time in localstorage
+ localStorage.setItem("time", time);
+
+ // Get colors
+ const styles = getComputedStyle(document.documentElement);
+ const fgColor = styles.getPropertyValue("--fg").trim();
+
+ // Clear the canvas
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+
+ // Draw Stars
+ drawStars(ctx, stars, time, fgColor);
+
+ // Draw first custom function
+ drawFunction(customFunction, fgColor);
+
+ // draw second custom function
+ drawFunction(customFunctionTwo, fgColor);
+}
+
+animate(0);
diff --git a/site/themes/sine/static/js/old-background.js b/site/themes/sine/static/js/old-background.js
new file mode 100644
index 0000000..e9b61a2
--- /dev/null
+++ b/site/themes/sine/static/js/old-background.js
@@ -0,0 +1,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();
+});
diff --git a/site/themes/sine/static/js/oldish-background.js b/site/themes/sine/static/js/oldish-background.js
new file mode 100644
index 0000000..3a55a0f
--- /dev/null
+++ b/site/themes/sine/static/js/oldish-background.js
@@ -0,0 +1,90 @@
+document.addEventListener("DOMContentLoaded", () => {
+ const canvas = document.getElementById("background");
+
+ if (canvas.getContext) {
+ const ctx = canvas.getContext("2d");
+
+ // Source - https://stackoverflow.com/a/58673385
+ // Posted by Sanxofon, modified by community. See post 'Timeline' for change history
+ // Retrieved 2026-02-15, License - CC BY-SA 4.0
+
+ var w = canvas.width; // Canvas width => Frequency is relative to this
+ var h = canvas.height/2; // Canvas height over two => Amplitude: Volume
+ var f=1; // How many cycles per canvas width => Frequency: Tone & Speed
+ // Calculates y position from x
+ function calcSineY(x) {
+ // This is the meat (unles you are vegan)
+ // Note that:
+ // h is the amplitude of the wave
+ // x is the current x value we get every time interval
+ // 2 * PI is the length of one cycle (full circumference)
+ // f/w is the frequency fraction
+ return h - h * Math.sin( x * 2 * Math.PI * (f/w) );
+ }
+ function drawSine(x){
+ ctx.clearRect(0, 0, w, h*2);
+ //draw x axis
+ ctx.beginPath(); // Draw a new path
+ ctx.strokeStyle = "green"; // Pick a color
+ ctx.moveTo(0,h); // Where to start drawing
+ ctx.lineTo(w,h); // Where to draw to
+ ctx.stroke(); // Draw
+
+ // // draw horizontal line of current amplitude
+ // ctx.beginPath(); // Draw a new path
+ // ctx.moveTo(0,h); // Where to start drawing
+ // ctx.strokeStyle = "gray"; // Pick a color
+ // for(var i=0;i<x;i++){ // Loop from left side to current x
+ // var y = calcSineY(x); // Calculate y value from x
+ // ctx.moveTo(i,y); // Where to start drawing
+ // ctx.lineTo(x,y); // Where to draw to
+ // }
+ // ctx.stroke(); // Draw
+ //
+ // // draw amplitude bar at current point
+ // ctx.beginPath(); // Draw a new path
+ // ctx.strokeStyle = "red"; // Pick a color
+ // for(var i=0;i<x;i++){ // Loop from left side to current x
+ // var y = calcSineY(x); // Calculate y value from x
+ // ctx.moveTo(x,h); // Where to start drawing
+ // ctx.lineTo(x,y); // Where to draw to
+ // }
+ // ctx.stroke(); // Draw
+ //
+ // // draw area below y
+ // ctx.beginPath(); // Draw a new path
+ // ctx.strokeStyle = "orange"; // Pick a color
+ // for(var i=0;i<x;i++){ // Loop from left side to current x
+ // if(i/3==Math.round(i/3)) { // Draw only one line each 3 pixels
+ // var y = calcSineY(i); // Calculate y value from x
+ // ctx.moveTo(i,h); // Where to start drawing
+ // ctx.lineTo(i,y); // Where to draw to
+ // }
+ // }
+ // ctx.stroke(); // Draw
+
+ // draw sin curve point to point until x
+ ctx.beginPath(); // Draw a new path
+ ctx.strokeStyle = "black"; // Pick a color
+ for(var i=0;i<x;i++){ // Loop from left side to current x
+ var y = calcSineY(i); // Calculate y value from x
+ ctx.lineTo(i,y); // Where to draw to
+ }
+ ctx.stroke(); // Draw
+ }
+ // Define initial value of x positiom (leftmost side of cnanvas)
+ var x=0;
+ // Start time interval
+ var interval = setInterval(function(){
+ drawSine(x); // Call draww function every cycle
+ x++; // Increment x by 1
+ // if(x>w){
+ // x=0; // x cannot be more than canvas with, so back to 0
+ // f++; // increment frequency for demonstration
+ // }
+ },10); // Loop every 10 milliseconds
+
+ } else {
+
+ }
+});