@anglefeint/astro-theme 0.1.19 → 0.1.21

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.19",
3
+ "version": "0.1.21",
4
4
  "type": "module",
5
5
  "description": "Anglefeint core theme package for Astro",
6
6
  "keywords": [
@@ -4,13 +4,17 @@ export function initHeroCanvas(prefersReducedMotion) {
4
4
 
5
5
  var canvas = shell.querySelector('.hero-canvas');
6
6
  var wrap = shell.querySelector('.hero-canvas-wrap');
7
- if (!canvas || !wrap) return;
7
+ var heroStack = shell.querySelector('.hero-stack');
8
+ if (!canvas || !wrap || !heroStack) return;
9
+ var ctx = canvas.getContext('2d');
10
+ if (!ctx) return;
8
11
 
9
12
  var src = canvas.getAttribute('data-hero-src');
10
13
  if (!src) return;
11
14
 
12
15
  var heroStart = 0;
13
16
  var heroRaf = 0;
17
+ var resizeTimer = 0;
14
18
  var baseCanvas = document.createElement('canvas');
15
19
  var baseCtx = baseCanvas.getContext('2d');
16
20
  var pixelCanvas = document.createElement('canvas');
@@ -19,14 +23,17 @@ export function initHeroCanvas(prefersReducedMotion) {
19
23
  var noiseCtx = noiseCanvas.getContext('2d');
20
24
  var edgeCanvas = document.createElement('canvas');
21
25
  var edgeCtx = edgeCanvas.getContext('2d');
26
+ var edgeWorkCanvas = document.createElement('canvas');
27
+ var edgeWorkCtx = edgeWorkCanvas.getContext('2d');
22
28
  var edgeReady = false;
29
+ var frameCount = 0;
23
30
 
24
31
  var EDGE_PHASE = 1.8;
25
32
  var REVEAL_PHASE = 2.5;
26
33
  var INTRO_END = EDGE_PHASE + REVEAL_PHASE;
27
34
 
28
35
  function sizeCanvas() {
29
- var rect = shell.querySelector('.hero-stack').getBoundingClientRect();
36
+ var rect = heroStack.getBoundingClientRect();
30
37
  var dpr = Math.min(window.devicePixelRatio || 1, 2);
31
38
  canvas.width = Math.max(2, Math.round(rect.width * dpr));
32
39
  canvas.height = Math.max(2, Math.round(rect.height * dpr));
@@ -55,28 +62,44 @@ export function initHeroCanvas(prefersReducedMotion) {
55
62
  baseCanvas.width = w;
56
63
  baseCanvas.height = h;
57
64
  drawBase(baseCtx, img, w, h);
58
- drawBase(edgeCtx, img, w, h);
65
+ var workW = Math.max(2, Math.round(w * 0.5));
66
+ var workH = Math.max(2, Math.round(h * 0.5));
67
+ edgeWorkCanvas.width = workW;
68
+ edgeWorkCanvas.height = workH;
69
+ drawBase(edgeWorkCtx, img, workW, workH);
59
70
 
60
- var srcImage = edgeCtx.getImageData(0, 0, w, h);
71
+ var srcImage = edgeWorkCtx.getImageData(0, 0, workW, workH);
61
72
  var d = srcImage.data;
62
- var out = edgeCtx.createImageData(w, h);
73
+ var out = edgeWorkCtx.createImageData(workW, workH);
63
74
  var od = out.data;
75
+ var rowStride = workW * 4;
64
76
 
65
- for (var y = 1; y < h - 1; y++) {
66
- for (var x = 1; x < w - 1; x++) {
67
- var idx = function(px, py) {
68
- return ((py * w) + px) * 4;
69
- };
70
- var i = idx(x, y);
71
- function luma(px, py) {
72
- var j = idx(px, py);
73
- return d[j] * 0.299 + d[j + 1] * 0.587 + d[j + 2] * 0.114;
74
- }
77
+ for (var y = 1; y < workH - 1; y++) {
78
+ var row = y * rowStride;
79
+ var rowAbove = row - rowStride;
80
+ var rowBelow = row + rowStride;
81
+ for (var x = 1; x < workW - 1; x++) {
82
+ var i = row + x * 4;
83
+ var iLeft = i - 4;
84
+ var iRight = i + 4;
85
+ var iAbove = rowAbove + x * 4;
86
+ var iAboveLeft = iAbove - 4;
87
+ var iAboveRight = iAbove + 4;
88
+ var iBelow = rowBelow + x * 4;
89
+ var iBelowLeft = iBelow - 4;
90
+ var iBelowRight = iBelow + 4;
91
+
92
+ var lumAboveLeft = d[iAboveLeft] * 0.299 + d[iAboveLeft + 1] * 0.587 + d[iAboveLeft + 2] * 0.114;
93
+ var lumAbove = d[iAbove] * 0.299 + d[iAbove + 1] * 0.587 + d[iAbove + 2] * 0.114;
94
+ var lumAboveRight = d[iAboveRight] * 0.299 + d[iAboveRight + 1] * 0.587 + d[iAboveRight + 2] * 0.114;
95
+ var lumLeft = d[iLeft] * 0.299 + d[iLeft + 1] * 0.587 + d[iLeft + 2] * 0.114;
96
+ var lumRight = d[iRight] * 0.299 + d[iRight + 1] * 0.587 + d[iRight + 2] * 0.114;
97
+ var lumBelowLeft = d[iBelowLeft] * 0.299 + d[iBelowLeft + 1] * 0.587 + d[iBelowLeft + 2] * 0.114;
98
+ var lumBelow = d[iBelow] * 0.299 + d[iBelow + 1] * 0.587 + d[iBelow + 2] * 0.114;
99
+ var lumBelowRight = d[iBelowRight] * 0.299 + d[iBelowRight + 1] * 0.587 + d[iBelowRight + 2] * 0.114;
75
100
 
76
- var gx = -luma(x - 1, y - 1) - 2 * luma(x - 1, y) - luma(x - 1, y + 1)
77
- + luma(x + 1, y - 1) + 2 * luma(x + 1, y) + luma(x + 1, y + 1);
78
- var gy = -luma(x - 1, y - 1) - 2 * luma(x, y - 1) - luma(x + 1, y - 1)
79
- + luma(x - 1, y + 1) + 2 * luma(x, y + 1) + luma(x + 1, y + 1);
101
+ var gx = -lumAboveLeft - 2 * lumLeft - lumBelowLeft + lumAboveRight + 2 * lumRight + lumBelowRight;
102
+ var gy = -lumAboveLeft - 2 * lumAbove - lumAboveRight + lumBelowLeft + 2 * lumBelow + lumBelowRight;
80
103
  var mag = Math.min(255, Math.sqrt(gx * gx + gy * gy));
81
104
 
82
105
  od[i] = Math.min(255, mag * 0.4);
@@ -86,15 +109,18 @@ export function initHeroCanvas(prefersReducedMotion) {
86
109
  }
87
110
  }
88
111
 
89
- edgeCtx.putImageData(out, 0, 0);
112
+ edgeWorkCtx.putImageData(out, 0, 0);
113
+ edgeCtx.clearRect(0, 0, w, h);
114
+ edgeCtx.imageSmoothingEnabled = true;
115
+ edgeCtx.drawImage(edgeWorkCanvas, 0, 0, workW, workH, 0, 0, w, h);
90
116
  edgeReady = true;
91
117
  }
92
118
 
93
119
  function heroRender(t) {
94
120
  if (!heroStart) heroStart = t;
95
121
  var elapsed = (t - heroStart) * 0.001;
96
- var ctx = canvas.getContext('2d');
97
- if (!ctx || !canvas.img) {
122
+ frameCount++;
123
+ if (!canvas.img) {
98
124
  heroRaf = requestAnimationFrame(heroRender);
99
125
  return;
100
126
  }
@@ -161,7 +187,7 @@ export function initHeroCanvas(prefersReducedMotion) {
161
187
  ctx.fillStyle = barGrad;
162
188
  ctx.fillRect(0, scanPos - 30, w, 60);
163
189
 
164
- if (Math.random() < 0.08) {
190
+ if ((frameCount % 2) === 0 && Math.random() < 0.08) {
165
191
  var glitchY = Math.random() * h;
166
192
  var glitchH = 2 + Math.random() * 12;
167
193
  var shiftX = (Math.random() - 0.5) * 12;
@@ -171,14 +197,14 @@ export function initHeroCanvas(prefersReducedMotion) {
171
197
  ctx.restore();
172
198
  }
173
199
 
174
- if (elapsed >= 6 && Math.random() < 0.025) {
200
+ if ((frameCount % 3) === 0 && elapsed >= 6 && Math.random() < 0.025) {
175
201
  var dropoutY = Math.floor(Math.random() * h);
176
202
  var dropoutH = 2 + Math.floor(Math.random() * 2);
177
203
  ctx.fillStyle = 'rgba(0, 0, 0, 0.85)';
178
204
  ctx.fillRect(0, dropoutY, w, dropoutH);
179
205
  }
180
206
 
181
- if (Math.random() < 0.03) {
207
+ if ((frameCount % 3) === 0 && Math.random() < 0.03) {
182
208
  var burstY = Math.random() * h * 0.8;
183
209
  var burstH = 4 + Math.random() * 20;
184
210
  if (noiseCanvas.width !== w) {
@@ -221,8 +247,7 @@ export function initHeroCanvas(prefersReducedMotion) {
221
247
  buildEdge(img);
222
248
  wrap.classList.add('ready');
223
249
  if (prefersReducedMotion) {
224
- var staticCtx = canvas.getContext('2d');
225
- if (staticCtx) staticCtx.drawImage(baseCanvas, 0, 0);
250
+ ctx.drawImage(baseCanvas, 0, 0);
226
251
  return;
227
252
  }
228
253
  heroRaf = requestAnimationFrame(heroRender);
@@ -230,10 +255,13 @@ export function initHeroCanvas(prefersReducedMotion) {
230
255
  img.src = new URL(src, window.location.href).href;
231
256
 
232
257
  window.addEventListener('resize', function() {
233
- if (canvas.img) {
258
+ if (!canvas.img) return;
259
+ if (resizeTimer) clearTimeout(resizeTimer);
260
+ resizeTimer = setTimeout(function() {
261
+ resizeTimer = 0;
234
262
  sizeCanvas();
235
263
  buildEdge(canvas.img);
236
- }
264
+ }, 180);
237
265
  }, { passive: true });
238
266
 
239
267
  function onHeroVisibilityChange() {
@@ -248,6 +276,7 @@ export function initHeroCanvas(prefersReducedMotion) {
248
276
 
249
277
  document.addEventListener('visibilitychange', onHeroVisibilityChange);
250
278
  window.addEventListener('beforeunload', function() {
279
+ if (resizeTimer) clearTimeout(resizeTimer);
251
280
  cancelAnimationFrame(heroRaf);
252
281
  }, { once: true });
253
282
  }
@@ -124,67 +124,40 @@ export function initRedQueenTv(prefersReducedMotion) {
124
124
  preloadRetryTimers.add(id);
125
125
  }
126
126
 
127
- function preloadGif(item, token, attempt, done) {
127
+ function preloadDecoderData(item, token, attempt, done) {
128
128
  if (token !== playToken || !isPlaying) return;
129
129
  var tryCount = typeof attempt === 'number' ? attempt : 0;
130
130
  var cachedData = mediaDataCache[item.url];
131
-
132
- if (cachedData instanceof ArrayBuffer) {
133
- if (typeof ImageDecoder === 'undefined') {
134
- done(true);
131
+ function retryOrFail() {
132
+ if (tryCount >= PRELOAD_RETRY_MAX) {
133
+ done(false);
135
134
  return;
136
135
  }
137
- var cachedDecoder = new ImageDecoder({ data: cachedData, type: item.type });
138
- cachedDecoder.tracks.ready.then(async function() {
139
- var result = await cachedDecoder.decode({ frameIndex: 0 });
136
+ var retryDelay = Math.min(1800, RETRY_BASE_MS * (tryCount + 1));
137
+ schedulePreloadRetry(function() {
138
+ preloadDecoderData(item, token, tryCount + 1, done);
139
+ }, retryDelay);
140
+ }
141
+
142
+ function verifyBuffer(buffer) {
143
+ mediaDataCache[item.url] = buffer;
144
+ var decoder = new ImageDecoder({ data: buffer, type: item.type });
145
+ decoder.tracks.ready.then(async function() {
146
+ var result = await decoder.decode({ frameIndex: 0 });
140
147
  if (result && result.image && result.image.close) result.image.close();
141
148
  done(true);
142
- }).catch(function() {
143
- if (tryCount >= PRELOAD_RETRY_MAX) {
144
- done(false);
145
- return;
146
- }
147
- var retryDelay = Math.min(1800, RETRY_BASE_MS * (tryCount + 1));
148
- schedulePreloadRetry(function() {
149
- preloadGif(item, token, tryCount + 1, done);
150
- }, retryDelay);
151
- });
149
+ }).catch(retryOrFail);
150
+ }
151
+
152
+ if (cachedData instanceof ArrayBuffer) {
153
+ verifyBuffer(cachedData);
152
154
  return;
153
155
  }
154
156
 
155
157
  fetch(resolveItemUrl(item))
156
158
  .then(function(response) { return response.arrayBuffer(); })
157
- .then(function(buffer) {
158
- mediaDataCache[item.url] = buffer;
159
- if (typeof ImageDecoder === 'undefined') {
160
- done(true);
161
- return;
162
- }
163
- var decoder = new ImageDecoder({ data: buffer, type: item.type });
164
- decoder.tracks.ready.then(async function() {
165
- var result = await decoder.decode({ frameIndex: 0 });
166
- if (result && result.image && result.image.close) result.image.close();
167
- done(true);
168
- }).catch(function() {
169
- if (tryCount >= PRELOAD_RETRY_MAX) {
170
- done(false);
171
- return;
172
- }
173
- var retryDelay = Math.min(1800, RETRY_BASE_MS * (tryCount + 1));
174
- schedulePreloadRetry(function() {
175
- preloadGif(item, token, tryCount + 1, done);
176
- }, retryDelay);
177
- });
178
- }).catch(function() {
179
- if (tryCount >= PRELOAD_RETRY_MAX) {
180
- done(false);
181
- return;
182
- }
183
- var retryDelay = Math.min(1800, RETRY_BASE_MS * (tryCount + 1));
184
- schedulePreloadRetry(function() {
185
- preloadGif(item, token, tryCount + 1, done);
186
- }, retryDelay);
187
- });
159
+ .then(verifyBuffer)
160
+ .catch(retryOrFail);
188
161
  }
189
162
 
190
163
  function preloadImage(item, token, attempt, done) {
@@ -235,8 +208,9 @@ export function initRedQueenTv(prefersReducedMotion) {
235
208
  if (left <= 0) finish(!failed);
236
209
  }
237
210
 
211
+ var hasImageDecoder = typeof ImageDecoder !== 'undefined';
238
212
  playlist.forEach(function(item) {
239
- if (item.type === 'image/gif') preloadGif(item, token, 0, markDone);
213
+ if (hasImageDecoder) preloadDecoderData(item, token, 0, markDone);
240
214
  else preloadImage(item, token, 0, markDone);
241
215
  });
242
216
  }
@@ -50,6 +50,7 @@ body.ai-page .ai-content .prose {
50
50
  /* 加载扫描线 */
51
51
  .ai-load-scan {
52
52
  position: fixed;
53
+ top: 0;
53
54
  left: 0;
54
55
  right: 0;
55
56
  height: 2px;
@@ -64,14 +65,15 @@ body.ai-page .ai-content .prose {
64
65
  animation: ai-scan 0.8s ease-out forwards;
65
66
  pointer-events: none;
66
67
  z-index: 20;
68
+ will-change: transform, opacity;
67
69
  }
68
70
  @keyframes ai-scan {
69
71
  0% {
70
- top: 0;
72
+ transform: translateY(0);
71
73
  opacity: 1;
72
74
  }
73
75
  100% {
74
- top: 100vh;
76
+ transform: translateY(100vh);
75
77
  opacity: 0.2;
76
78
  }
77
79
  }
@@ -150,11 +150,11 @@
150
150
  inset 0 1px 0 rgba(220, 242, 255, 0.22);
151
151
  overflow: hidden;
152
152
  backdrop-filter: blur(1.5px);
153
+ transform: translate3d(0, 0, 0);
154
+ will-change: transform, opacity;
153
155
  transition:
154
- width 360ms cubic-bezier(0.23, 1, 0.32, 1),
155
- top 320ms ease,
156
- padding 320ms ease,
157
- border-radius 320ms ease,
156
+ transform 320ms ease,
157
+ opacity 220ms ease,
158
158
  box-shadow 320ms ease,
159
159
  background 320ms ease;
160
160
  }
@@ -243,10 +243,10 @@
243
243
  outline-offset: -2px;
244
244
  }
245
245
  .rq-tv.rq-tv-collapsed {
246
- top: 27vh;
247
246
  width: 34px;
248
247
  padding: 0;
249
248
  border-radius: 6px;
249
+ transform: translate3d(0, 2vh, 0);
250
250
  background: linear-gradient(165deg, rgba(34, 58, 78, 0.9), rgba(10, 19, 30, 0.92));
251
251
  box-shadow:
252
252
  0 10px 20px rgba(4, 10, 18, 0.42),
@@ -338,7 +338,7 @@
338
338
  position: absolute;
339
339
  top: 0;
340
340
  bottom: 0;
341
- left: -35%;
341
+ left: 0;
342
342
  width: 35%;
343
343
  background: linear-gradient(
344
344
  90deg,
@@ -346,11 +346,13 @@
346
346
  rgba(164, 228, 255, 0.88),
347
347
  rgba(132, 214, 255, 0)
348
348
  );
349
+ transform: translateX(-100%);
350
+ will-change: transform;
349
351
  animation: ai-title-flow-run 3.8s linear infinite;
350
352
  }
351
353
  @keyframes ai-title-flow-run {
352
354
  to {
353
- left: 100%;
355
+ transform: translateX(285%);
354
356
  }
355
357
  }
356
358
  .ai-stage-toast {
@@ -490,6 +490,7 @@ body.cyber-page ul li a:hover img {
490
490
  }
491
491
  body.cyber-page .title {
492
492
  margin: 0;
493
+ font-size: 1.2rem;
493
494
  line-height: 1;
494
495
  transition:
495
496
  color 0.2s,