Skip to content

Commit f75ad35

Browse files
author
Quarto GHA Workflow Runner
committed
Built site for gh-pages
1 parent 813dc23 commit f75ad35

66 files changed

Lines changed: 1169 additions & 983 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.nojekyll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6bb7f6f2
1+
74fa37fd

bg-lines.js

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// bg-lines.js — Animated background line chart drawings
2+
(function () {
3+
'use strict';
4+
5+
const GRID = 40;
6+
const MAX_OPACITY = 0.25;
7+
const POINT_R = 2.5;
8+
const LINE_W = 1.25;
9+
const MAX_SERIES = 4;
10+
const DRAW_DURATION = 12000; // ms to draw full line
11+
const HOLD_MS = 1500;
12+
const FADE_MS = 2500;
13+
const SPAWN_MIN = 500;
14+
const SPAWN_MAX = 2000;
15+
16+
const COLORS = [
17+
[0, 95, 115], // darkteal
18+
[10, 147, 150], // teal
19+
[148, 210, 189], // lightteal
20+
];
21+
22+
const canvas = document.getElementById('bg-lines');
23+
if (!canvas) return;
24+
const ctx = canvas.getContext('2d');
25+
26+
// --- Helpers ---
27+
function rand(lo, hi) { return lo + Math.random() * (hi - lo); }
28+
function randInt(lo, hi) { return Math.floor(rand(lo, hi + 1)); }
29+
function pick(arr) { return arr[randInt(0, arr.length - 1)]; }
30+
function rgba(c, a) { return 'rgba(' + c[0] + ',' + c[1] + ',' + c[2] + ',' + a + ')'; }
31+
32+
// --- Resize ---
33+
let W, H;
34+
function resize() {
35+
const dpr = window.devicePixelRatio || 1;
36+
W = window.innerWidth;
37+
H = window.innerHeight;
38+
canvas.width = W * dpr;
39+
canvas.height = H * dpr;
40+
canvas.style.width = W + 'px';
41+
canvas.style.height = H + 'px';
42+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
43+
}
44+
45+
let resizeTimer;
46+
window.addEventListener('resize', function () {
47+
clearTimeout(resizeTimer);
48+
resizeTimer = setTimeout(resize, 100);
49+
});
50+
resize();
51+
52+
// --- Line generation ---
53+
const STEP_X = 40; // fixed sampling interval along x
54+
55+
function generatePoints() {
56+
const n = Math.ceil(W / STEP_X) + 1;
57+
const startY = rand(H * 0.15, H * 0.85);
58+
const volatility = rand(25, 60);
59+
60+
const pts = [];
61+
let y = startY;
62+
for (let i = 0; i < n; i++) {
63+
pts.push({ x: i * STEP_X, y: y });
64+
y += (Math.random() - 0.5) * 2 * volatility;
65+
y = Math.max(GRID * 2, Math.min(H - GRID * 2, y));
66+
}
67+
return pts;
68+
}
69+
70+
// --- Series ---
71+
function createSeries() {
72+
return {
73+
pts: generatePoints(),
74+
color: pick(COLORS),
75+
state: 'drawing', // drawing | holding | fading | dead
76+
progress: 0, // fractional segment index
77+
opacity: MAX_OPACITY,
78+
stateStart: 0,
79+
};
80+
}
81+
82+
function updateSeries(s, now, dt) {
83+
switch (s.state) {
84+
case 'drawing':
85+
s.progress += (s.pts.length - 1) * (dt / DRAW_DURATION);
86+
if (s.progress >= s.pts.length - 1) {
87+
s.progress = s.pts.length - 1;
88+
s.state = 'holding';
89+
s.stateStart = now;
90+
}
91+
break;
92+
case 'holding':
93+
if (now - s.stateStart > HOLD_MS) {
94+
s.state = 'fading';
95+
s.stateStart = now;
96+
}
97+
break;
98+
case 'fading': {
99+
const t = (now - s.stateStart) / FADE_MS;
100+
s.opacity = MAX_OPACITY * (1 - t);
101+
if (s.opacity <= 0) {
102+
s.opacity = 0;
103+
s.state = 'dead';
104+
}
105+
break;
106+
}
107+
}
108+
}
109+
110+
function drawSeries(s) {
111+
if (s.opacity <= 0) return;
112+
const col = rgba(s.color, s.opacity);
113+
const full = Math.floor(s.progress);
114+
115+
// Line
116+
ctx.strokeStyle = col;
117+
ctx.lineWidth = LINE_W;
118+
ctx.lineJoin = 'round';
119+
ctx.lineCap = 'round';
120+
ctx.beginPath();
121+
ctx.moveTo(s.pts[0].x, s.pts[0].y);
122+
for (let i = 1; i <= full; i++) {
123+
ctx.lineTo(s.pts[i].x, s.pts[i].y);
124+
}
125+
// Partial segment
126+
const frac = s.progress - full;
127+
if (frac > 0 && full + 1 < s.pts.length) {
128+
const a = s.pts[full];
129+
const b = s.pts[full + 1];
130+
ctx.lineTo(a.x + (b.x - a.x) * frac, a.y + (b.y - a.y) * frac);
131+
}
132+
ctx.stroke();
133+
134+
// Points
135+
ctx.fillStyle = col;
136+
for (let i = 0; i <= full; i++) {
137+
ctx.beginPath();
138+
ctx.arc(s.pts[i].x, s.pts[i].y, POINT_R, 0, Math.PI * 2);
139+
ctx.fill();
140+
}
141+
}
142+
143+
// --- Main loop ---
144+
let series = [];
145+
let nextSpawn = 0;
146+
let prev = 0;
147+
let paused = false;
148+
149+
function tick(now) {
150+
if (paused) { requestAnimationFrame(tick); return; }
151+
const dt = prev ? now - prev : 16;
152+
prev = now;
153+
154+
ctx.clearRect(0, 0, W, H);
155+
156+
// Spawn
157+
if (series.length < MAX_SERIES && now > nextSpawn) {
158+
series.push(createSeries());
159+
nextSpawn = now + rand(SPAWN_MIN, SPAWN_MAX);
160+
}
161+
162+
// Update & draw
163+
for (const s of series) {
164+
updateSeries(s, now, dt);
165+
drawSeries(s);
166+
}
167+
168+
// Prune
169+
series = series.filter(function (s) { return s.state !== 'dead'; });
170+
171+
requestAnimationFrame(tick);
172+
}
173+
174+
// --- Visibility ---
175+
document.addEventListener('visibilitychange', function () {
176+
paused = document.hidden;
177+
if (!paused) prev = 0; // reset dt to avoid jump
178+
});
179+
180+
// --- Start ---
181+
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
182+
requestAnimationFrame(tick);
183+
}
184+
})();

faq.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@
8080
<link href="site_libs/quarto-html/quarto-syntax-highlighting-a36260601fbdf6a4904b36220d3e3906.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
8181
<script src="site_libs/bootstrap/bootstrap.min.js"></script>
8282
<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
83-
<link href="site_libs/bootstrap/bootstrap-ae3a23e5fff51768ec3dc754f784de44.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
84-
<link href="site_libs/bootstrap/bootstrap-dark-bb8758b6ba4144100911e1d00292335d.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="light">
85-
<link href="site_libs/bootstrap/bootstrap-ae3a23e5fff51768ec3dc754f784de44.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
83+
<link href="site_libs/bootstrap/bootstrap-45af3f7fa62cfd53c9ba66fef88ce393.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
84+
<link href="site_libs/bootstrap/bootstrap-dark-7f6f16d4a61aa8c2bdeb8ab7db0872fc.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="light">
85+
<link href="site_libs/bootstrap/bootstrap-45af3f7fa62cfd53c9ba66fef88ce393.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
8686
<script id="quarto-search-options" type="application/json">{
8787
"location": "navbar",
8888
"copy-button": false,

0 commit comments

Comments
 (0)