reactbits-mcp-server
Version:
MCP Server for React Bits - Access 99+ React components with animations, backgrounds, and UI elements
161 lines (144 loc) • 3.79 kB
JSX
/* eslint-disable react/no-unknown-property */
import { useMemo } from 'react'
import { Canvas, useThree } from '@react-three/fiber'
import { shaderMaterial, useTrailTexture } from '@react-three/drei'
import * as THREE from 'three'
import './PixelTrail.css';
const GooeyFilter = ({
id = "goo-filter",
strength = 10,
}) => {
return (
<svg className='goo-filter-container'>
<defs>
<filter id={id}>
<feGaussianBlur
in="SourceGraphic"
stdDeviation={strength}
result="blur"
/>
<feColorMatrix
in="blur"
type="matrix"
values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9"
result="goo"
/>
<feComposite in="SourceGraphic" in2="goo" operator="atop" />
</filter>
</defs>
</svg>
)
}
const DotMaterial = shaderMaterial(
{
resolution: new THREE.Vector2(),
mouseTrail: null,
gridSize: 100,
pixelColor: new THREE.Color('#ffffff')
},
`
varying vec2 vUv;
void main() {
gl_Position = vec4(position.xy, 0.0, 1.0);
}
`,
`
uniform vec2 resolution;
uniform sampler2D mouseTrail;
uniform float gridSize;
uniform vec3 pixelColor;
vec2 coverUv(vec2 uv) {
vec2 s = resolution.xy / max(resolution.x, resolution.y);
vec2 newUv = (uv - 0.5) * s + 0.5;
return clamp(newUv, 0.0, 1.0);
}
float sdfCircle(vec2 p, float r) {
return length(p - 0.5) - r;
}
void main() {
vec2 screenUv = gl_FragCoord.xy / resolution;
vec2 uv = coverUv(screenUv);
vec2 gridUv = fract(uv * gridSize);
vec2 gridUvCenter = (floor(uv * gridSize) + 0.5) / gridSize;
float trail = texture2D(mouseTrail, gridUvCenter).r;
gl_FragColor = vec4(pixelColor, trail);
}
`
)
function Scene({
gridSize,
trailSize,
maxAge,
interpolate,
easingFunction,
pixelColor
}) {
const size = useThree((s) => s.size)
const viewport = useThree((s) => s.viewport)
const dotMaterial = useMemo(() => new DotMaterial(), [])
dotMaterial.uniforms.pixelColor.value = new THREE.Color(pixelColor)
const [trail, onMove] = useTrailTexture({
size: 512,
radius: trailSize,
maxAge: maxAge,
interpolate: interpolate || 0.1,
ease: easingFunction || ((x) => x)
})
if (trail) {
trail.minFilter = THREE.NearestFilter;
trail.magFilter = THREE.NearestFilter;
trail.wrapS = THREE.ClampToEdgeWrapping;
trail.wrapT = THREE.ClampToEdgeWrapping;
}
const scale = Math.max(viewport.width, viewport.height) / 2
return (
<mesh scale={[scale, scale, 1]} onPointerMove={onMove}>
<planeGeometry args={[2, 2]} />
<primitive
object={dotMaterial}
gridSize={gridSize}
resolution={[size.width * viewport.dpr, size.height * viewport.dpr]}
mouseTrail={trail}
/>
</mesh>
)
}
export default function PixelTrail({
gridSize = 40,
trailSize = 0.1,
maxAge = 250,
interpolate = 5,
easingFunction = (x) => x,
canvasProps = {},
glProps = {
antialias: false,
powerPreference: 'high-performance',
alpha: true
},
gooeyFilter,
color = '#ffffff',
className = ''
}) {
return (
<>
{gooeyFilter && (
<GooeyFilter id={gooeyFilter.id} strength={gooeyFilter.strength} />
)}
<Canvas
{...canvasProps}
gl={glProps}
className={`pixel-canvas ${className}`}
style={gooeyFilter && { filter: `url(#${gooeyFilter.id})` }}
>
<Scene
gridSize={gridSize}
trailSize={trailSize}
maxAge={maxAge}
interpolate={interpolate}
easingFunction={easingFunction}
pixelColor={color}
/>
</Canvas>
</>
)
}