mirror of
https://github.com/geoffsee/open-gsio.git
synced 2025-09-08 22:56:46 +00:00
Add visible
prop to toggle components and simplify conditional rendering
This commit is contained in:

committed by
Geoff Seemueller

parent
e72198628c
commit
6cc5e038a7
@@ -1,51 +1,51 @@
|
|||||||
import { Box } from '@chakra-ui/react';
|
import { Box } from '@chakra-ui/react';
|
||||||
import { useEffect } from 'react';
|
import React, { memo, useEffect, useMemo } from 'react';
|
||||||
|
|
||||||
export interface BevySceneProps {
|
export interface BevySceneProps {
|
||||||
speed?: number; // transition seconds
|
speed?: number;
|
||||||
intensity?: number;
|
intensity?: number; // 0-1 when visible
|
||||||
glow?: boolean;
|
glow?: boolean;
|
||||||
|
visible?: boolean; // NEW — defaults to true
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BevyScene: React.FC<BevySceneProps> = ({ speed = 1, intensity = 1, glow = false }) => {
|
const BevySceneInner: React.FC<BevySceneProps> = ({
|
||||||
|
speed = 1,
|
||||||
|
intensity = 1,
|
||||||
|
glow = false,
|
||||||
|
visible,
|
||||||
|
}) => {
|
||||||
|
/* initialise once */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
let dispose: (() => void) | void;
|
||||||
(async () => {
|
(async () => {
|
||||||
const module = await import('/public/yachtpit.js', { type: 'module' });
|
const { default: init } = await import(/* webpackIgnore: true */ '/public/yachtpit.js');
|
||||||
console.log('init', module);
|
dispose = await init(); // zero-arg, uses #yachtpit-canvas
|
||||||
await module.default();
|
|
||||||
})();
|
})();
|
||||||
// const script = document.createElement('script');
|
return () => {
|
||||||
// script.src = '';
|
if (typeof dispose === 'function') dispose();
|
||||||
// script.type = 'module';
|
};
|
||||||
// document.body.appendChild(script);
|
|
||||||
// script.onload = loaded => {
|
|
||||||
// loaded.target?.init();
|
|
||||||
// console.log('loaded', loaded);
|
|
||||||
// };
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
/* memoised styles */
|
||||||
|
const wrapperStyles = useMemo(
|
||||||
|
() => ({
|
||||||
|
position: 'absolute' as const,
|
||||||
|
inset: 0,
|
||||||
|
zIndex: 0,
|
||||||
|
pointerEvents: 'none' as const,
|
||||||
|
opacity: visible ? Math.min(Math.max(intensity, 0), 1) : 0,
|
||||||
|
filter: glow ? 'blur(1px)' : 'none',
|
||||||
|
transition: `opacity ${speed}s ease-in-out`,
|
||||||
|
display: visible ? 'block' : 'none', // optional: reclaim hit-testing entirely
|
||||||
|
}),
|
||||||
|
[visible, intensity, glow, speed],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box as="div" sx={wrapperStyles}>
|
||||||
pos="absolute"
|
<canvas id="yachtpit-canvas" width={1280} height={720} aria-hidden />
|
||||||
inset={0}
|
|
||||||
zIndex={0}
|
|
||||||
pointerEvents="none"
|
|
||||||
opacity={Math.min(Math.max(intensity, 0), 1)}
|
|
||||||
filter={glow ? 'blur(1px)' : 'none'}
|
|
||||||
transition={`opacity ${speed}s ease-in-out`}
|
|
||||||
>
|
|
||||||
<script type="module"></script>
|
|
||||||
<canvas id="yachtpit-canvas" width="1280" height="720"></canvas>
|
|
||||||
{/*<iframe*/}
|
|
||||||
{/* src="/yachtpit.html"*/}
|
|
||||||
{/* style={{*/}
|
|
||||||
{/* width: '100%',*/}
|
|
||||||
{/* height: '100%',*/}
|
|
||||||
{/* border: 'none',*/}
|
|
||||||
{/* backgroundColor: 'transparent',*/}
|
|
||||||
{/* }}*/}
|
|
||||||
{/* title="Bevy Scene"*/}
|
|
||||||
{/*/>*/}
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const BevyScene = memo(BevySceneInner);
|
||||||
|
@@ -34,7 +34,7 @@ export const LandingComponent: React.FC = () => {
|
|||||||
<Tweakbox
|
<Tweakbox
|
||||||
sliders={{
|
sliders={{
|
||||||
speed: {
|
speed: {
|
||||||
value: speed,
|
value: !particles ? speed : 0.99,
|
||||||
onChange: setSpeed,
|
onChange: setSpeed,
|
||||||
label: 'Animation Speed',
|
label: 'Animation Speed',
|
||||||
min: 0.01,
|
min: 0.01,
|
||||||
@@ -43,7 +43,7 @@ export const LandingComponent: React.FC = () => {
|
|||||||
ariaLabel: 'animation-speed',
|
ariaLabel: 'animation-speed',
|
||||||
},
|
},
|
||||||
intensity: {
|
intensity: {
|
||||||
value: intensity,
|
value: !particles ? intensity : 0.99,
|
||||||
onChange: setIntensity,
|
onChange: setIntensity,
|
||||||
label: 'Effect Intensity',
|
label: 'Effect Intensity',
|
||||||
min: 0.01,
|
min: 0.01,
|
||||||
@@ -94,9 +94,9 @@ export const LandingComponent: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
{!particles && !matrixRain && <BevyScene speed={speed} intensity={intensity} glow={glow} />}
|
<BevyScene speed={speed} intensity={intensity} glow={glow} visible={bevyScene} />
|
||||||
{!particles && matrixRain && <MatrixRain speed={speed} intensity={intensity} glow={glow} />}
|
<MatrixRain speed={speed} intensity={intensity} glow={glow} visible={matrixRain} />
|
||||||
{particles && <Particles particles glow speed={speed} intensity={intensity} />}
|
<Particles glow speed={speed} intensity={intensity} visible={particles} />
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -8,12 +8,14 @@ interface MatrixRainProps {
|
|||||||
speed?: number;
|
speed?: number;
|
||||||
glow?: boolean;
|
glow?: boolean;
|
||||||
intensity?: number;
|
intensity?: number;
|
||||||
|
visible?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MatrixRain: React.FC<MatrixRainProps> = ({
|
export const MatrixRain: React.FC<MatrixRainProps> = ({
|
||||||
speed = 1,
|
speed = 1,
|
||||||
glow = false,
|
glow = false,
|
||||||
intensity = 1,
|
intensity = 1,
|
||||||
|
visible,
|
||||||
}) => {
|
}) => {
|
||||||
const fontSize = useBreakpointValue({ base: 14, md: 18, lg: 22 }) ?? 14;
|
const fontSize = useBreakpointValue({ base: 14, md: 18, lg: 22 }) ?? 14;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@@ -111,7 +113,12 @@ export const MatrixRain: React.FC<MatrixRainProps> = ({
|
|||||||
cancelAnimationFrame(animationRef.current);
|
cancelAnimationFrame(animationRef.current);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [fontSize, speed, glow, intensity]);
|
}, [fontSize, speed, glow, intensity, visible]);
|
||||||
|
|
||||||
return <canvas ref={canvasRef} style={{ display: 'block' }} />;
|
return (
|
||||||
|
<canvas
|
||||||
|
ref={canvasRef}
|
||||||
|
style={{ display: visible ? 'block' : 'none', pointerEvents: 'none' }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
@@ -6,6 +6,7 @@ interface ParticlesProps {
|
|||||||
intensity: number;
|
intensity: number;
|
||||||
particles: boolean;
|
particles: boolean;
|
||||||
glow: boolean;
|
glow: boolean;
|
||||||
|
visible?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Particle {
|
interface Particle {
|
||||||
@@ -16,7 +17,7 @@ interface Particle {
|
|||||||
size: number;
|
size: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Particles: React.FC<ParticlesProps> = ({ speed, intensity, particles, glow }) => {
|
const Particles: React.FC<ParticlesProps> = ({ speed, intensity, glow, visible }) => {
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
const particlesRef = useRef<Particle[]>([]);
|
const particlesRef = useRef<Particle[]>([]);
|
||||||
const animationFrameRef = useRef<number | undefined>(undefined);
|
const animationFrameRef = useRef<number | undefined>(undefined);
|
||||||
@@ -33,7 +34,7 @@ const Particles: React.FC<ParticlesProps> = ({ speed, intensity, particles, glow
|
|||||||
|
|
||||||
// Main animation effect
|
// Main animation effect
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!particles) {
|
if (!visible) {
|
||||||
if (animationFrameRef.current) {
|
if (animationFrameRef.current) {
|
||||||
cancelAnimationFrame(animationFrameRef.current);
|
cancelAnimationFrame(animationFrameRef.current);
|
||||||
animationFrameRef.current = undefined;
|
animationFrameRef.current = undefined;
|
||||||
@@ -128,11 +129,11 @@ const Particles: React.FC<ParticlesProps> = ({ speed, intensity, particles, glow
|
|||||||
animationFrameRef.current = undefined;
|
animationFrameRef.current = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [particles, intensity, speed, glow, theme.colors.text.accent]);
|
}, [visible, intensity, speed, glow, theme.colors.text.accent]);
|
||||||
|
|
||||||
// Separate effect for speed changes - update existing particle velocities
|
// Separate effect for speed changes - update existing particle velocities
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!particles) return;
|
if (!visible) return;
|
||||||
|
|
||||||
particlesRef.current.forEach(particle => {
|
particlesRef.current.forEach(particle => {
|
||||||
const currentSpeed = Math.sqrt(particle.vx * particle.vx + particle.vy * particle.vy);
|
const currentSpeed = Math.sqrt(particle.vx * particle.vx + particle.vy * particle.vy);
|
||||||
@@ -146,13 +147,13 @@ const Particles: React.FC<ParticlesProps> = ({ speed, intensity, particles, glow
|
|||||||
particle.vy = (Math.random() - 0.5) * speed;
|
particle.vy = (Math.random() - 0.5) * speed;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, [speed, particles]);
|
}, [speed, visible]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box zIndex={0} pointerEvents={'none'}>
|
<Box zIndex={0} pointerEvents={'none'}>
|
||||||
<canvas
|
<canvas
|
||||||
ref={canvasRef}
|
ref={canvasRef}
|
||||||
style={{ display: particles ? 'block' : 'none', pointerEvents: 'none' }}
|
style={{ display: visible ? 'block' : 'none', pointerEvents: 'none' }}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user