Sparkles Globe
Sparkles Globe é um componente de efeito para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.
UI Layouts
MIT
effects
O que é
Sparkles Globe é um componente de efeito para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.
Como usar
Abre o componente no catálogo, carrega em copiar, e cola no teu projeto. O prompt copiado leva o código e as regras para o teu agente o reproduzir sem alterar nada.
Cinco cópias grátis por mês. Sem cartão.
Não precisa de pacotes além do que o projeto já tem
Licença
Este componente vem de UI Layouts e é redistribuído sob a licença MIT, que permite uso comercial. O aviso de copyright viaja com o código.
Sparkles Globe
import React from 'react';
import Earth from '@/components/globe';
import { Sparkles } from '@/components/sparkles';
function index() {
return (
<>
<div className='h-screen overflow-hidden bg-black text-white'>
<article className='grid gap-4 text-center relative z-10 pt-10'>
<span className='inline-block text-sm border p-1 px-3 w-fit mx-auto rounded-full border-[#3273ff] bg-[#0f1c35]'>
Get Access
</span>
<h1 className='text-4xl font-semibold bg-linear-to-b from-[#edeffd] to-[#7b9cda] bg-clip-text text-transparent leading-[100%] tracking-tighter'>
Design with a Global
<br />
Perspective, Innovate with Ease.
</h1>
<Earth />
</article>
<div className='relative -mt-32 h-80 w-screen overflow-hidden mask-[radial-gradient(50%_50%,white,transparent)] before:absolute before:inset-0 before:bg-[radial-gradient(circle_at_bottom_center,#3273ff,transparent_90%)] before:opacity-40 after:absolute after:-left-1/2 after:top-1/2 after:aspect-[1/0.7] after:w-[200%] after:rounded-[10%] after:border-t after:border-[#163474] after:bg-[#08132b]'>
<Sparkles
density={800}
speed={1.2}
size={1.2}
direction='top'
opacitySpeed={2}
color='#32A7FF'
className='absolute inset-x-0 bottom-0 h-full w-full '
/>
</div>
</div>
</>
);
}
export default index;
'use client';
import { useEffect, useId, useState } from 'react';
import Particles, { initParticlesEngine } from '@tsparticles/react';
import { loadSlim } from '@tsparticles/slim';
interface SparklesProps {
className?: string;
size?: number;
minSize?: number | null;
density?: number;
speed?: number;
minSpeed?: number | null;
opacity?: number;
direction?: string;
opacitySpeed?: number;
minOpacity?: number | null;
color?: string;
mousemove?: boolean;
hover?: boolean;
background?: string;
options?: Record<string, any>; // Adjust type as needed based on `options` structure
}
export function Sparkles({
className,
size = 1.2,
minSize = null,
density = 800,
speed = 1.5,
minSpeed = null,
opacity = 1,
direction = '',
opacitySpeed = 3,
minOpacity = null,
color = '#ffffff',
mousemove = false,
hover = false,
background = 'transparent',
options = {},
}: SparklesProps) {
const [isReady, setIsReady] = useState(false);
useEffect(() => {
initParticlesEngine(async (engine) => {
await loadSlim(engine);
}).then(() => {
setIsReady(true);
});
}, []);
const id = useId();
const defaultOptions = {
background: {
color: {
value: background,
},
},
fullScreen: {
enable: false,
zIndex: 1,
},
fpsLimit: 300,
interactivity: {
events: {
onClick: {
enable: true,
mode: 'push',
},
onHover: {
enable: hover,
mode: 'grab',
parallax: {
enable: mousemove,
force: 60,
smooth: 10,
},
},
resize: true as any,
},
modes: {
push: {
quantity: 4,
},
repulse: {
distance: 200,
duration: 0.4,
},
},
},
particles: {
color: {
value: color,
},
move: {
enable: true,
direction,
speed: {
min: minSpeed || speed / 130,
max: speed,
},
straight: true,
},
collisions: {
absorb: {
speed: 2,
},
bounce: {
horizontal: {
value: 1,
},
vertical: {
value: 1,
},
},
enable: false,
maxSpeed: 50,
mode: 'bounce',
overlap: {
enable: true,
retries: 0,
},
},
number: {
value: density,
},
opacity: {
value: {
min: minOpacity || opacity / 10,
max: opacity,
},
animation: {
enable: true,
sync: false,
speed: opacitySpeed,
},
},
size: {
value: {
min: minSize || size / 1.5,
max: size,
},
},
},
detectRetina: true,
};
return (
isReady && (
<Particles id={id}
// @ts-nocheck
options={defaultOptions} className={className} />
)
);
}
'use client';
import { cn } from '@/lib/utils';
import createGlobe from 'cobe';
import type React from 'react';
import { useEffect, useRef, useState } from 'react';
interface EarthProps {
className?: string;
theta?: number;
dark?: number;
scale?: number;
diffuse?: number;
mapSamples?: number;
mapBrightness?: number;
baseColor?: [number, number, number];
markerColor?: [number, number, number];
glowColor?: [number, number, number];
}
const Earth: React.FC<EarthProps> = ({
className,
theta = 0.25,
dark = 1,
scale = 1.1,
diffuse = 1.2,
mapSamples = 40000,
mapBrightness = 6,
baseColor = [0.4, 0.6509, 1],
markerColor = [1, 0, 0],
glowColor = [0.2745, 0.5765, 0.898],
}) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
useEffect(() => {
let width = 0;
const onResize = () => canvasRef.current && (width = canvasRef.current.offsetWidth);
window.addEventListener('resize', onResize);
onResize();
let phi = 0;
onResize();
const globe = createGlobe(canvasRef.current!, {
devicePixelRatio: 2,
width: width * 2,
height: width * 2,
phi: 0,
theta: theta,
dark: dark,
scale: scale,
diffuse: diffuse,
mapSamples: mapSamples,
mapBrightness: mapBrightness,
baseColor: baseColor,
markerColor: markerColor,
glowColor: glowColor,
opacity: 1,
offset: [0, 0],
markers: [
// longitude latitude
],
onRender: (state: Record<string, any>) => {
// Called on every animation frame.
// `state` will be an empty object, return updated params.\
state.phi = phi;
phi += 0.003;
},
});
return () => {
globe.destroy();
};
}, []);
return (
<div
className={cn(
'flex items-center justify-center z-10 w-full max-w-[350px] mx-auto',
className
)}
>
<canvas
ref={canvasRef}
style={{
width: '100%',
height: '100%',
maxWidth: '100%',
aspectRatio: '1',
}}
/>
</div>
);
};
export default Earth;