3cd267ee6e
feat: Implement LlamadorAPI component for API interaction with dynamic request handling feat: Create MetodoSelect component for selecting HTTP methods with visual feedback feat: Add VisualizacionesRandom component to display various charts using ECharts feat: Develop custom 404 Error page with holographic shader effect feat: Create HoloShader component for dynamic background effects on 404 page style: Add CSS styles for Appshell layout and navigation feat: Build Appshell component to manage application layout and navigation feat: Add ColorSchemeToggle component for switching between light and dark themes feat: Create Plantilla component as a template for future pages style: Define styles for Welcome component feat: Implement Welcome component with introductory text and links feat: Develop HomePage component to serve as the main entry point of the application feat: Create Biblioteca component for managing notes and libraries with rich text editor feat: Add Editor_Test component for testing rich text editor functionality style: Define styles for the rich text editor in Biblioteca
143 lines
3.8 KiB
TypeScript
143 lines
3.8 KiB
TypeScript
import { Card, Title, Box, useMantineTheme } from '@mantine/core';
|
||
import { Canvas, extend, useFrame, useThree } from '@react-three/fiber';
|
||
import { useRef, useMemo } from 'react';
|
||
import * as THREE from 'three';
|
||
|
||
// 🎨 Utilidad para convertir hex a RGB [0–1]
|
||
function hexToRGBArray(hex: string): [number, number, number] {
|
||
const bigint = parseInt(hex.replace('#', ''), 16);
|
||
return [
|
||
((bigint >> 16) & 255) / 255,
|
||
((bigint >> 8) & 255) / 255,
|
||
(bigint & 255) / 255,
|
||
];
|
||
}
|
||
|
||
// ✨ Shader personalizado estilo holográfico, con color dinámico
|
||
class HoloShaderMaterial extends THREE.ShaderMaterial {
|
||
constructor(color: [number, number, number]) {
|
||
super({
|
||
uniforms: {
|
||
u_time: { value: 0 },
|
||
u_resolution: { value: new THREE.Vector2() },
|
||
u_color: { value: new THREE.Vector3(...color) },
|
||
},
|
||
vertexShader: `
|
||
void main() {
|
||
gl_Position = vec4(position, 1.0);
|
||
}
|
||
`,
|
||
fragmentShader: `
|
||
precision mediump float;
|
||
uniform float u_time;
|
||
uniform vec2 u_resolution;
|
||
uniform vec3 u_color;
|
||
|
||
void main() {
|
||
vec2 uv = gl_FragCoord.xy / u_resolution;
|
||
vec2 pos = uv * 10.0;
|
||
pos.x += u_time * 0.3;
|
||
pos.y += sin(u_time * 0.2) * 2.0;
|
||
|
||
float color = sin(pos.x + sin(pos.y + sin(pos.x))) * 0.5 + 0.5;
|
||
|
||
vec3 c = vec3(
|
||
u_color.r + 0.2 * sin(u_time + pos.x),
|
||
u_color.g + 0.2 * cos(u_time + pos.y),
|
||
u_color.b + 0.2 * sin(pos.x + pos.y + u_time)
|
||
);
|
||
|
||
gl_FragColor = vec4(c * color, 1.0);
|
||
}
|
||
`,
|
||
});
|
||
}
|
||
}
|
||
|
||
extend({ HoloShaderMaterial });
|
||
|
||
// 🎥 Plano con el shader
|
||
function HoloPlane({ color }: { color: [number, number, number] }) {
|
||
const mat = useRef<any>(null);
|
||
const { size } = useThree();
|
||
|
||
useFrame(({ clock }) => {
|
||
if (mat.current) {
|
||
mat.current.uniforms.u_time.value = clock.getElapsedTime();
|
||
mat.current.uniforms.u_resolution.value.set(size.width, size.height);
|
||
}
|
||
});
|
||
|
||
const material = useMemo(() => new HoloShaderMaterial(color), [color]);
|
||
|
||
return (
|
||
<mesh>
|
||
<planeGeometry args={[2, 2]} />
|
||
<primitive object={material} ref={mat} attach="material" />
|
||
</mesh>
|
||
);
|
||
}
|
||
|
||
// 🎨 Fondo que ocupa todo el contenedor
|
||
function HolographicBackground({ color }: { color: [number, number, number] }) {
|
||
return (
|
||
<Box
|
||
style={{
|
||
position: 'absolute',
|
||
inset: 0,
|
||
zIndex: 0,
|
||
pointerEvents: 'none',
|
||
}}
|
||
>
|
||
<Canvas orthographic camera={{ zoom: 1, position: [0, 0, 1] }}>
|
||
<HoloPlane color={color} />
|
||
</Canvas>
|
||
</Box>
|
||
);
|
||
}
|
||
|
||
// 🧩 Componente final con fondo shader y texto 404
|
||
export function MantineCardWithShader() {
|
||
const theme = useMantineTheme();
|
||
const hex = theme.colors[theme.primaryColor][6];
|
||
const rgb = hexToRGBArray(hex);
|
||
|
||
return (
|
||
<Card
|
||
withBorder
|
||
radius="lg"
|
||
shadow="xl"
|
||
style={{
|
||
position: 'relative',
|
||
overflow: 'hidden',
|
||
minHeight: 300,
|
||
minWidth: 400,
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'center',
|
||
}}
|
||
>
|
||
<HolographicBackground color={rgb} />
|
||
|
||
<Box style={{ position: 'relative', zIndex: 1, textAlign: 'center' }}>
|
||
<Title
|
||
order={1}
|
||
style={{
|
||
fontSize: '15rem',
|
||
fontWeight: 900,
|
||
backgroundImage: 'linear-gradient(to bottom, rgba(255,255,255,1), rgba(255,255,255,0))',
|
||
WebkitBackgroundClip: 'text',
|
||
WebkitTextFillColor: 'transparent',
|
||
textAlign: 'center',
|
||
lineHeight: 1,
|
||
userSelect: 'none', // <-- evita selección
|
||
textDecoration: 'none', // <-- evita subrayado
|
||
}}
|
||
>
|
||
404
|
||
</Title>
|
||
</Box>
|
||
</Card>
|
||
);
|
||
}
|