Skip to content

Commit 78f88da

Browse files
committed
registry home page
1 parent 4e08743 commit 78f88da

File tree

8 files changed

+542
-551
lines changed

8 files changed

+542
-551
lines changed
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/index-B5ywWXR1.js

Lines changed: 0 additions & 70 deletions
This file was deleted.

assets/index-Bpxi7g5L.js

Lines changed: 82 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@
100100
gtag("js", new Date());
101101
gtag("config", "G-1B67VYZMXF");
102102
</script>
103-
<script type="module" crossorigin src="/assets/index-B5ywWXR1.js"></script>
104-
<link rel="stylesheet" crossorigin href="/assets/index-C5WbEy8w.css">
103+
<script type="module" crossorigin src="/assets/index-Bpxi7g5L.js"></script>
104+
<link rel="stylesheet" crossorigin href="/assets/index-B15jggpO.css">
105105
<link rel="manifest" href="/manifest.webmanifest"></head>
106106

107107
<body>

sw.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
<template>
2+
<canvas ref="cv" class="net" aria-hidden="true"></canvas>
3+
</template>
4+
5+
<script setup>
6+
import { onMounted, onBeforeUnmount, ref } from "vue";
7+
8+
const cv = ref(null);
9+
10+
let raf = 0;
11+
let ctx = null;
12+
13+
let w = 0;
14+
let h = 0;
15+
let dpr = 1;
16+
17+
const nodes = [];
18+
const baseNodes = 42;
19+
20+
const mouse = {
21+
x: 0,
22+
y: 0,
23+
active: false,
24+
down: false,
25+
lastSpawnX: 0,
26+
lastSpawnY: 0,
27+
};
28+
29+
function rand(min, max) {
30+
return min + Math.random() * (max - min);
31+
}
32+
33+
function clamp(v, a, b) {
34+
return Math.max(a, Math.min(b, v));
35+
}
36+
37+
function resize() {
38+
const el = cv.value;
39+
if (!el) return;
40+
41+
const rect = el.getBoundingClientRect();
42+
dpr = Math.max(1, Math.min(2, window.devicePixelRatio || 1));
43+
44+
w = Math.floor(rect.width);
45+
h = Math.floor(rect.height);
46+
47+
el.width = Math.floor(w * dpr);
48+
el.height = Math.floor(h * dpr);
49+
50+
ctx = el.getContext("2d");
51+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
52+
53+
ensureNodeCount();
54+
}
55+
56+
function ensureNodeCount() {
57+
const target = baseNodes + Math.floor((w * h) / 70000);
58+
while (nodes.length < target) spawnNode(rand(0, w), rand(0, h), true);
59+
while (nodes.length > target) nodes.pop();
60+
}
61+
62+
function spawnNode(x, y, calm = false) {
63+
const n = {
64+
x,
65+
y,
66+
vx: calm ? rand(-0.15, 0.15) : rand(-0.45, 0.45),
67+
vy: calm ? rand(-0.15, 0.15) : rand(-0.45, 0.45),
68+
s: Math.random() < 0.12 ? 8 : 6, // pixel size
69+
a: rand(0.22, 0.62), // alpha
70+
tone: pickTone(),
71+
};
72+
nodes.push(n);
73+
}
74+
75+
function pickTone() {
76+
const r = Math.random();
77+
if (r < 0.72) return "teal";
78+
if (r < 0.90) return "slate";
79+
return "yellow";
80+
}
81+
82+
function toneColor(tone, alpha) {
83+
if (tone === "yellow") return `rgba(250, 204, 21, ${alpha})`;
84+
if (tone === "slate") return `rgba(148, 163, 184, ${alpha})`;
85+
return `rgba(94, 234, 212, ${alpha})`; // teal
86+
}
87+
88+
function lineColor(alpha) {
89+
return `rgba(94, 234, 212, ${alpha})`;
90+
}
91+
92+
function step() {
93+
raf = requestAnimationFrame(step);
94+
95+
if (!ctx) return;
96+
ctx.clearRect(0, 0, w, h);
97+
98+
const maxDist = Math.min(220, Math.max(140, w * 0.18));
99+
const maxDist2 = maxDist * maxDist;
100+
101+
// Update nodes
102+
for (const n of nodes) {
103+
// subtle attraction to mouse when active
104+
if (mouse.active) {
105+
const dx = mouse.x - n.x;
106+
const dy = mouse.y - n.y;
107+
const d2 = dx * dx + dy * dy;
108+
const pullR = 220;
109+
if (d2 < pullR * pullR) {
110+
const d = Math.max(1, Math.sqrt(d2));
111+
const f = (1 - d / pullR) * 0.015;
112+
n.vx += (dx / d) * f;
113+
n.vy += (dy / d) * f;
114+
}
115+
}
116+
117+
// integrate
118+
n.x += n.vx;
119+
n.y += n.vy;
120+
121+
// gentle damping
122+
n.vx *= 0.995;
123+
n.vy *= 0.995;
124+
125+
// bounce
126+
if (n.x < 0) {
127+
n.x = 0;
128+
n.vx = Math.abs(n.vx);
129+
}
130+
if (n.x > w) {
131+
n.x = w;
132+
n.vx = -Math.abs(n.vx);
133+
}
134+
if (n.y < 0) {
135+
n.y = 0;
136+
n.vy = Math.abs(n.vy);
137+
}
138+
if (n.y > h) {
139+
n.y = h;
140+
n.vy = -Math.abs(n.vy);
141+
}
142+
}
143+
144+
// Lines
145+
ctx.lineWidth = 1.15;
146+
for (let i = 0; i < nodes.length; i++) {
147+
const a = nodes[i];
148+
for (let j = i + 1; j < nodes.length; j++) {
149+
const b = nodes[j];
150+
const dx = a.x - b.x;
151+
const dy = a.y - b.y;
152+
const d2 = dx * dx + dy * dy;
153+
if (d2 > maxDist2) continue;
154+
155+
const d = Math.sqrt(d2);
156+
let alpha = (1 - d / maxDist) * 0.42;
157+
158+
// boost near mouse
159+
if (mouse.active) {
160+
const mdx = (a.x + b.x) * 0.5 - mouse.x;
161+
const mdy = (a.y + b.y) * 0.5 - mouse.y;
162+
const md2 = mdx * mdx + mdy * mdy;
163+
if (md2 < 240 * 240) alpha *= 1.45;
164+
}
165+
166+
alpha = clamp(alpha, 0.02, 0.55);
167+
168+
ctx.strokeStyle = lineColor(alpha);
169+
ctx.beginPath();
170+
ctx.moveTo(a.x, a.y);
171+
ctx.lineTo(b.x, b.y);
172+
ctx.stroke();
173+
}
174+
}
175+
176+
// Nodes (small squares)
177+
for (const n of nodes) {
178+
const size = n.s;
179+
const aa = mouse.active ? n.a * 1.05 : n.a;
180+
ctx.fillStyle = toneColor(n.tone, clamp(aa, 0.12, 0.92));
181+
ctx.fillRect(n.x - size / 2, n.y - size / 2, size, size);
182+
}
183+
184+
// soft vignette like JSR
185+
const g = ctx.createRadialGradient(w * 0.5, h * 0.55, 0, w * 0.5, h * 0.55, Math.max(w, h) * 0.65);
186+
g.addColorStop(0, "rgba(0,0,0,0)");
187+
g.addColorStop(1, "rgba(0,0,0,0.38)");
188+
ctx.fillStyle = g;
189+
ctx.fillRect(0, 0, w, h);
190+
}
191+
192+
function pointerPos(e) {
193+
const rect = cv.value.getBoundingClientRect();
194+
return {
195+
x: e.clientX - rect.left,
196+
y: e.clientY - rect.top,
197+
};
198+
}
199+
200+
function maybeSpawnTree(x, y) {
201+
const dx = x - mouse.lastSpawnX;
202+
const dy = y - mouse.lastSpawnY;
203+
const d2 = dx * dx + dy * dy;
204+
205+
// spacing between new nodes while dragging
206+
if (d2 < 18 * 18) return;
207+
208+
mouse.lastSpawnX = x;
209+
mouse.lastSpawnY = y;
210+
211+
// spawn 1-2 nodes for a dense "tree"
212+
const count = Math.random() < 0.35 ? 2 : 1;
213+
for (let i = 0; i < count; i++) {
214+
spawnNode(
215+
x + rand(-6, 6),
216+
y + rand(-6, 6),
217+
false
218+
);
219+
}
220+
}
221+
222+
function onMove(e) {
223+
if (!cv.value) return;
224+
const p = pointerPos(e);
225+
mouse.x = p.x;
226+
mouse.y = p.y;
227+
mouse.active = true;
228+
229+
if (mouse.down) {
230+
maybeSpawnTree(p.x, p.y);
231+
}
232+
}
233+
234+
function onDown(e) {
235+
if (!cv.value) return;
236+
const p = pointerPos(e);
237+
mouse.down = true;
238+
mouse.active = true;
239+
mouse.x = p.x;
240+
mouse.y = p.y;
241+
mouse.lastSpawnX = p.x;
242+
mouse.lastSpawnY = p.y;
243+
244+
// immediate burst
245+
for (let i = 0; i < 3; i++) {
246+
spawnNode(p.x + rand(-10, 10), p.y + rand(-10, 10), false);
247+
}
248+
}
249+
250+
function onUp() {
251+
mouse.down = false;
252+
}
253+
254+
function onLeave() {
255+
mouse.active = false;
256+
mouse.down = false;
257+
}
258+
259+
onMounted(() => {
260+
const el = cv.value;
261+
if (!el) return;
262+
263+
// initial nodes after first resize
264+
resize();
265+
266+
// seed calm nodes
267+
if (nodes.length === 0) {
268+
for (let i = 0; i < baseNodes; i++) spawnNode(rand(0, w), rand(0, h), true);
269+
ensureNodeCount();
270+
}
271+
272+
// events
273+
el.addEventListener("pointermove", onMove, { passive: true });
274+
el.addEventListener("pointerdown", onDown, { passive: true });
275+
window.addEventListener("pointerup", onUp, { passive: true });
276+
el.addEventListener("pointerleave", onLeave, { passive: true });
277+
278+
const ro = new ResizeObserver(() => resize());
279+
ro.observe(el);
280+
281+
raf = requestAnimationFrame(step);
282+
283+
onBeforeUnmount(() => {
284+
cancelAnimationFrame(raf);
285+
el.removeEventListener("pointermove", onMove);
286+
el.removeEventListener("pointerdown", onDown);
287+
window.removeEventListener("pointerup", onUp);
288+
el.removeEventListener("pointerleave", onLeave);
289+
ro.disconnect();
290+
});
291+
});
292+
</script>
293+
294+
<style scoped>
295+
.net{
296+
position: absolute;
297+
inset: 0;
298+
width: 100%;
299+
height: 100%;
300+
}
301+
</style>

vix-site/src/data/github_stats.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"repo": "vixcpp/vix",
3-
"fetched_at": "2026-02-10T15:03:24.152Z",
3+
"fetched_at": "2026-02-10T15:24:19.487Z",
44
"stars": 267,
55
"forks": 22,
66
"open_issues": 182,

0 commit comments

Comments
 (0)