@anglefeint/astro-theme 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anglefeint/astro-theme",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "description": "Anglefeint core theme package for Astro",
6
6
  "license": "MIT",
@@ -11,6 +11,7 @@
11
11
  "src/config",
12
12
  "src/components",
13
13
  "src/layouts",
14
+ "src/scripts",
14
15
  "src/i18n",
15
16
  "src/styles",
16
17
  "src/assets/theme",
@@ -26,6 +27,7 @@
26
27
  ".": "./src/index.ts",
27
28
  "./components/*": "./src/components/*",
28
29
  "./layouts/*": "./src/layouts/*",
30
+ "./scripts/*": "./src/scripts/*",
29
31
  "./i18n/*": "./src/i18n/*",
30
32
  "./styles/*": "./src/styles/*",
31
33
  "./assets/*": "./src/assets/*",
@@ -216,12 +216,13 @@ body.ai-page::-webkit-scrollbar-thumb {
216
216
  opacity: 0.7;
217
217
  }
218
218
  }
219
- .ai-network {
219
+ .ai-network-canvas {
220
220
  position: absolute;
221
221
  inset: -8%;
222
222
  width: 116%;
223
223
  height: 116%;
224
224
  opacity: 1;
225
+ pointer-events: none;
225
226
  filter: brightness(1.28) saturate(1.08);
226
227
  animation: ai-drift 25s ease-in-out infinite;
227
228
  }
@@ -240,57 +241,6 @@ body.ai-page::-webkit-scrollbar-thumb {
240
241
  transform: translate(0.5%, -0.8%) scale(1.005);
241
242
  }
242
243
  }
243
- .ai-network .ai-dots circle {
244
- transform-origin: center;
245
- animation:
246
- ai-dot-float 8s ease-in-out infinite,
247
- ai-dot-breathe 5s ease-in-out infinite;
248
- }
249
- .ai-network .ai-dots circle:nth-child(odd) {
250
- animation-delay: -3s;
251
- }
252
- .ai-network .ai-dots circle:nth-child(3n) {
253
- animation-delay: -5s;
254
- }
255
- .ai-network .ai-dots circle:nth-child(5n) {
256
- animation-duration: 10s;
257
- }
258
- .ai-network .ai-dots circle:nth-child(4n) {
259
- animation-delay: -1s;
260
- }
261
- .ai-network .ai-lines line {
262
- stroke-dasharray: 6 12;
263
- animation: ai-line-pulse 4s linear infinite;
264
- }
265
- .ai-network .ai-lines line:nth-child(odd) {
266
- animation-delay: -2s;
267
- }
268
- @keyframes ai-line-pulse {
269
- to {
270
- stroke-dashoffset: -18;
271
- }
272
- }
273
- @keyframes ai-dot-float {
274
- 0%,
275
- 100% {
276
- transform: translate(0, 0);
277
- }
278
- 33% {
279
- transform: translate(1.5px, -2px);
280
- }
281
- 66% {
282
- transform: translate(-1px, 1.5px);
283
- }
284
- }
285
- @keyframes ai-dot-breathe {
286
- 0%,
287
- 100% {
288
- opacity: 1;
289
- }
290
- 50% {
291
- opacity: 0.75;
292
- }
293
- }
294
244
  body.ai-page .ai-content,
295
245
  body.ai-page footer {
296
246
  position: relative;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * About page content and runtime behavior configuration.
3
- * Used by src/pages/[lang]/about.astro and public/scripts/about-effects.js.
3
+ * Used by src/pages/[lang]/about.astro and packages/theme/src/scripts/about-effects.js.
4
4
  */
5
5
  export const ABOUT_CONFIG = {
6
6
  metaLine: '$ profile booted | mode: builder',
@@ -48,29 +48,6 @@ const hasSystemMeta = Boolean(aiModel || aiMode || aiState);
48
48
  const hasResponseMeta = aiLatencyMs !== undefined || aiConfidence !== undefined;
49
49
  const hasStats = aiModel || wordCount !== undefined || tokenCount !== undefined;
50
50
  const confidenceText = aiConfidence !== undefined ? aiConfidence.toFixed(2) : undefined;
51
-
52
- // 点云:全屏分散但不过于稀疏
53
- const w = 1200; const h = 800;
54
- const pts: { x: number; y: number; r: number; depth: number }[] = [];
55
- const pad = 50;
56
- for (let i = 0; i < 58; i++) {
57
- const x = pad + Math.random() * (w - pad * 2);
58
- const y = pad + Math.random() * (h - pad * 2);
59
- const depth = Math.random();
60
- pts.push({
61
- x, y,
62
- r: 1.1 + depth * 1.3,
63
- depth,
64
- });
65
- }
66
- const connectDist = 138;
67
- const edges: [number, number][] = [];
68
- for (let i = 0; i < pts.length; i++) {
69
- for (let j = i + 1; j < pts.length; j++) {
70
- const d = Math.hypot(pts[i].x - pts[j].x, pts[i].y - pts[j].y);
71
- if (d < connectDist) edges.push([i, j]);
72
- }
73
- }
74
51
  ---
75
52
 
76
53
  <AiShell
@@ -99,45 +76,7 @@ for (let i = 0; i < pts.length; i++) {
99
76
  <span class="ai-particle" style={`--x: ${20 + (i * 7) % 60}%; --y: ${10 + (i * 11) % 70}%; --d: ${3 + (i % 4)}s`}></span>
100
77
  ))}
101
78
  </div>
102
- <svg class="ai-network" viewBox="0 0 1200 800" preserveAspectRatio="xMidYMid slice">
103
- <defs>
104
- <linearGradient id="ai-line-grad" x1="0%" y1="0%" x2="100%" y2="0%">
105
- <stop offset="0%" stop-color="rgba(180,235,255,0.26)" />
106
- <stop offset="50%" stop-color="rgba(236,252,255,0.74)" />
107
- <stop offset="100%" stop-color="rgba(180,235,255,0.26)" />
108
- </linearGradient>
109
- <filter id="ai-dot-glow">
110
- <feGaussianBlur stdDeviation="2.2" result="blur" />
111
- <feMerge>
112
- <feMergeNode in="blur" />
113
- <feMergeNode in="SourceGraphic" />
114
- </feMerge>
115
- </filter>
116
- </defs>
117
- <g class="ai-lines">
118
- {edges.map(([i, j]) => (
119
- <line
120
- x1={pts[i].x}
121
- y1={pts[i].y}
122
- x2={pts[j].x}
123
- y2={pts[j].y}
124
- stroke="url(#ai-line-grad)"
125
- stroke-width="0.4"
126
- />
127
- ))}
128
- </g>
129
- <g class="ai-dots">
130
- {pts.map((p) => (
131
- <circle
132
- cx={p.x}
133
- cy={p.y}
134
- r={p.r}
135
- fill={`rgba(232,255,255,${0.72 + p.depth * 0.48})`}
136
- filter="url(#ai-dot-glow)"
137
- />
138
- ))}
139
- </g>
140
- </svg>
79
+ <canvas class="ai-network-canvas" aria-hidden="true"></canvas>
141
80
  </div>
142
81
  <aside class="rq-tv rq-tv-collapsed">
143
82
  <div class="rq-tv-stage" data-rq-src={themeRedqueen1.src} data-rq-src2={themeRedqueen2.src}></div>
@@ -257,6 +196,9 @@ for (let i = 0; i < pts.length; i++) {
257
196
  </a>
258
197
  </nav>
259
198
  <Fragment slot="body-end">
260
- <script is:inline src="/scripts/blogpost-effects.js" defer></script>
199
+ <script>
200
+ import { initBlogpostEffects } from '../scripts/blogpost-effects.js';
201
+ initBlogpostEffects();
202
+ </script>
261
203
  </Fragment>
262
204
  </AiShell>
@@ -14,6 +14,11 @@ const { locale, title, description } = Astro.props as Props;
14
14
  <ThemeFrame locale={locale} title={title} description={description} bodyClass="page-home" mainClass="page-main home-content">
15
15
  <link slot="head" rel="stylesheet" href="/styles/home-page.css" />
16
16
  <canvas slot="body-start" id="matrix-bg" aria-hidden="true"></canvas>
17
- <script slot="body-end" is:inline src="/scripts/home-matrix.js" defer></script>
17
+ <Fragment slot="body-end">
18
+ <script>
19
+ import { initHomeMatrix } from '../../scripts/home-matrix.js';
20
+ initHomeMatrix();
21
+ </script>
22
+ </Fragment>
18
23
  <slot />
19
24
  </ThemeFrame>
@@ -1,5 +1,4 @@
1
- (function() {
2
- function init() {
1
+ export function initAboutEffects() {
3
2
  var runtimeConfig = {};
4
3
  var runtimeConfigEl = document.getElementById('hacker-runtime-config');
5
4
  if (runtimeConfigEl && runtimeConfigEl.textContent) {
@@ -551,11 +550,4 @@
551
550
  }, 1200);
552
551
  });
553
552
  }
554
- }
555
-
556
- if (document.readyState === 'loading') {
557
- document.addEventListener('DOMContentLoaded', init);
558
- } else {
559
- init();
560
- }
561
- })();
553
+ }
@@ -1,5 +1,4 @@
1
- (function() {
2
- function init() {
1
+ export function initBlogpostEffects() {
3
2
  var prefersReducedMotion = false;
4
3
  try {
5
4
  prefersReducedMotion = !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches);
@@ -54,6 +53,118 @@
54
53
  window.scrollTo({ top: 0, behavior: prefersReducedMotion ? 'auto' : 'smooth' });
55
54
  });
56
55
  }
56
+ function initNetworkCanvas() {
57
+ var canvas = document.querySelector('.ai-network-canvas');
58
+ if (!canvas) return;
59
+ var ctx = canvas.getContext('2d');
60
+ if (!ctx) return;
61
+ var MAX_DPR = 2;
62
+ var rafId = 0;
63
+ var start = 0;
64
+ var last = 0;
65
+ var fps = prefersReducedMotion ? 1 : 30;
66
+ var frameMs = 1000 / fps;
67
+ var points = [];
68
+ var edges = [];
69
+
70
+ function seededRandom(seed) {
71
+ var s = seed >>> 0;
72
+ return function() {
73
+ s = (1664525 * s + 1013904223) >>> 0;
74
+ return s / 4294967296;
75
+ };
76
+ }
77
+
78
+ function resize() {
79
+ var rect = canvas.getBoundingClientRect();
80
+ var dpr = Math.min(MAX_DPR, window.devicePixelRatio || 1);
81
+ canvas.width = Math.max(2, Math.round(rect.width * dpr));
82
+ canvas.height = Math.max(2, Math.round(rect.height * dpr));
83
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
84
+
85
+ var w = rect.width;
86
+ var h = rect.height;
87
+ var rand = seededRandom(0xA13F09);
88
+ var count = Math.max(20, Math.min(36, Math.round((w * h) / 32000)));
89
+ var connectDist = Math.min(160, Math.max(90, Math.min(w, h) * 0.18));
90
+ var maxEdges = 120;
91
+ points = [];
92
+ for (var i = 0; i < count; i++) {
93
+ points.push({
94
+ x: 20 + rand() * Math.max(20, w - 40),
95
+ y: 20 + rand() * Math.max(20, h - 40),
96
+ r: 1 + rand() * 1.6,
97
+ p: rand() * Math.PI * 2,
98
+ a: 0.5 + rand() * 0.5,
99
+ });
100
+ }
101
+ edges = [];
102
+ for (var a = 0; a < points.length; a++) {
103
+ for (var b = a + 1; b < points.length; b++) {
104
+ if (edges.length >= maxEdges) break;
105
+ var dx = points[a].x - points[b].x;
106
+ var dy = points[a].y - points[b].y;
107
+ var d = Math.sqrt(dx * dx + dy * dy);
108
+ if (d < connectDist) edges.push([a, b, d / connectDist]);
109
+ }
110
+ if (edges.length >= maxEdges) break;
111
+ }
112
+ }
113
+
114
+ function render(ts) {
115
+ if (!start) start = ts;
116
+ if (!prefersReducedMotion && ts - last < frameMs) {
117
+ rafId = requestAnimationFrame(render);
118
+ return;
119
+ }
120
+ last = ts;
121
+ var t = (ts - start) * 0.001;
122
+ var w = canvas.clientWidth;
123
+ var h = canvas.clientHeight;
124
+ ctx.clearRect(0, 0, w, h);
125
+
126
+ for (var i = 0; i < edges.length; i++) {
127
+ var e = edges[i];
128
+ var p1 = points[e[0]];
129
+ var p2 = points[e[1]];
130
+ var alpha = (1 - e[2]) * (prefersReducedMotion ? 0.2 : (0.18 + 0.06 * Math.sin(t * 0.9 + i)));
131
+ ctx.strokeStyle = 'rgba(190, 236, 255,' + Math.max(0.06, alpha).toFixed(3) + ')';
132
+ ctx.lineWidth = 0.6;
133
+ ctx.beginPath();
134
+ ctx.moveTo(p1.x, p1.y);
135
+ ctx.lineTo(p2.x, p2.y);
136
+ ctx.stroke();
137
+ }
138
+
139
+ for (var j = 0; j < points.length; j++) {
140
+ var p = points[j];
141
+ var pulse = prefersReducedMotion ? 1 : (1 + 0.18 * Math.sin(t * 1.5 + p.p));
142
+ ctx.fillStyle = 'rgba(228, 251, 255,' + (0.58 * p.a).toFixed(3) + ')';
143
+ ctx.beginPath();
144
+ ctx.arc(p.x, p.y, p.r * pulse, 0, Math.PI * 2);
145
+ ctx.fill();
146
+ }
147
+
148
+ if (!prefersReducedMotion) rafId = requestAnimationFrame(render);
149
+ }
150
+
151
+ function stop() {
152
+ if (!rafId) return;
153
+ cancelAnimationFrame(rafId);
154
+ rafId = 0;
155
+ }
156
+
157
+ resize();
158
+ render(performance.now());
159
+ window.addEventListener('resize', resize, { passive: true });
160
+ document.addEventListener('visibilitychange', function() {
161
+ if (prefersReducedMotion) return;
162
+ if (document.hidden) stop();
163
+ else if (!rafId) rafId = requestAnimationFrame(render);
164
+ });
165
+ window.addEventListener('beforeunload', stop, { once: true });
166
+ }
167
+ initNetworkCanvas();
57
168
  function initHeroCanvas() {
58
169
  var shell = document.querySelector('.hero-shell');
59
170
  if (!shell) return;
@@ -972,11 +1083,4 @@
972
1083
  }, 1200);
973
1084
  });
974
1085
  }
975
- }
976
-
977
- if (document.readyState === 'loading') {
978
- document.addEventListener('DOMContentLoaded', init);
979
- } else {
980
- init();
981
- }
982
- })();
1086
+ }
@@ -1,4 +1,4 @@
1
- (() => {
1
+ export function initHomeMatrix() {
2
2
  const chars =
3
3
  '!"#$%&\'()*+,-./:;<=>?[\\]^_{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
4
4
  const matrixFont =
@@ -114,4 +114,4 @@
114
114
  document.body.style.setProperty('--matrix-mx', `${event.clientX}px`);
115
115
  document.body.style.setProperty('--matrix-my', `${event.clientY}px`);
116
116
  });
117
- })();
117
+ }