Skip to content

Commit aff33c2

Browse files
committed
style: refine header canvas dynamics with linked phase and fm warp (#8641)
1 parent a67d7d4 commit aff33c2

1 file changed

Lines changed: 14 additions & 16 deletions

File tree

apps/portal/canvas/HeaderCanvas.mjs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -237,29 +237,27 @@ class HeaderCanvas extends Base {
237237
ctx.lineJoin = 'round';
238238
ctx.shadowBlur = 10;
239239

240-
// We use globalAlpha to implement the "Shimmer" effect
241-
// However, setting globalAlpha on the whole path makes it flash uniformly.
242-
// To have "traveling" shimmer, we would need segments or a gradient mask.
243-
// A simpler, performant approach: Use the "breath" to also modulate global intensity slightly?
244-
// Or stick to the "Breathing" for geometry and keep opacity constant for now to avoid segmenting.
245-
// User asked for "parts fading in or out".
246-
// Let's use a subtle global pulse for the strands.
240+
// REF 1: Linked Phase - Shimmer leads Breath by 90deg ("Charging up")
241+
let baseShimmer = 0.75 + (Math.sin(me.time * 0.5 + Math.PI / 2) * 0.25);
247242

248-
let shimmer = 0.8 + (Math.sin(me.time * 2) * 0.2); // 0.6 to 1.0
243+
// REF 2: Independent Strand Shimmer
244+
// Strand A follows base shimmer
245+
// Strand B follows base shimmer but slightly out of phase for "call and response"
246+
let shimmerA = baseShimmer,
247+
shimmerB = 0.75 + (Math.sin(me.time * 0.5 + Math.PI / 2 + Math.PI / 3) * 0.25);
249248

250249
// --- Strand A (Top / Sine) ---
251250
ctx.strokeStyle = grad1;
252251
ctx.shadowColor = PRIMARY;
253-
ctx.globalAlpha = shimmer;
252+
ctx.globalAlpha = shimmerA;
254253
ctx.beginPath();
255254

256255
for (let x = 0; x <= width; x += step) {
257256
let {offsetY, intensity} = me.getStreamOffset(x, height);
258257

259-
// FREQUENCY MODULATION:
260-
// Vary the phase speed along X to stretch/compress the wave.
261-
// We use a low-frequency sine to modulate the input to the high-frequency sine.
262-
let freqMod = Math.sin(x * 0.002 + me.time * 0.1) * 20, // Slowly changing warp
258+
// REF 3: Interactive FM Warp
259+
// Amplify frequency modulation near interactions
260+
let freqMod = Math.sin(x * 0.002 + me.time * 0.1) * (20 + (intensity * 10)),
263261
timeShift = me.time * 2,
264262
sine = Math.sin(((x + freqMod) * 0.04) - timeShift) * baseAmp,
265263
noise = (Math.random() - 0.5) * hoverAmp * intensity;
@@ -274,14 +272,14 @@ class HeaderCanvas extends Base {
274272
// --- Strand B (Bottom / Cosine or Inverted Sine) ---
275273
ctx.strokeStyle = grad2;
276274
ctx.shadowColor = SECONDARY;
277-
ctx.globalAlpha = shimmer; // Keep in sync or phase shift? Let's keep in sync for coherence.
275+
ctx.globalAlpha = shimmerB;
278276
ctx.beginPath();
279277

280278
for (let x = 0; x <= width; x += step) {
281279
let {offsetY, intensity} = me.getStreamOffset(x, height);
282280

283-
// Same FM for coherence, just inverted phase
284-
let freqMod = Math.sin(x * 0.002 + me.time * 0.1) * 20,
281+
// Same FM with interaction boost
282+
let freqMod = Math.sin(x * 0.002 + me.time * 0.1) * (20 + (intensity * 10)),
285283
timeShift = me.time * 2,
286284
sine = Math.sin(((x + freqMod) * 0.04) - timeShift + Math.PI) * baseAmp,
287285
noise = (Math.random() - 0.5) * hoverAmp * intensity;

0 commit comments

Comments
 (0)