All PromptsAll Prompts
animation
Magnet Lines
Анимация сетки линий, вращающихся к курсору, создающих эффект магнитного поля. UI-компонент для интерактивных визуализаций.
by Zhou JasonLive Preview
Prompt
# Magnet Lines
You are given a task to integrate an existing React component in the codebase
~~~/README.md
# Magnet Lines
A grid of lines that rotate to point towards the cursor position, creating a magnetic field effect.
## Usage
```tsx
import MagnetLines from '@/sd-components/679ce99e-18b4-4c5f-a421-c1a3fd1bac4c';
function MyComponent() {
return (
<MagnetLines
rows={9}
columns={9}
containerSize="60vmin"
lineColor="tomato"
lineWidth="0.8vmin"
lineHeight="5vmin"
baseAngle={0}
style={{ margin: "2rem auto" }}
/>
);
}
```
## Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `rows` | `number` | `9` | Number of rows in the grid |
| `columns` | `number` | `9` | Number of columns in the grid |
| `containerSize` | `string` | `'80vmin'` | Width and height of the container |
| `lineColor` | `string` | `'#efefef'` | Color of the lines |
| `lineWidth` | `string` | `'1vmin'` | Width of each line |
| `lineHeight` | `string` | `'6vmin'` | Height of each line |
| `baseAngle` | `number` | `-10` | Initial rotation angle in degrees |
| `className` | `string` | `''` | Additional CSS classes |
| `style` | `CSSProperties` | `{}` | Inline styles |
~~~
~~~/src/App.tsx
import React from 'react';
import MagnetLines from './MagnetLines';
export default function App() {
return (
<div className="min-h-screen bg-[#1A1A1B] flex items-center justify-center p-8">
<div className="relative w-full max-w-2xl aspect-square flex flex-col items-center justify-center p-8 rounded-2xl bg-[#222224] shadow-[0_0_40px_rgba(0,0,0,0.3)] overflow-hidden">
<div className="absolute top-8 left-8 z-10">
<h1 className="text-white text-2xl font-medium tracking-tight font-sans">Magnet Lines</h1>
<p className="text-gray-400 text-sm mt-2">Interactive field animation</p>
</div>
<MagnetLines
rows={12}
columns={12}
containerSize="70vmin"
lineColor="rgba(255, 255, 255, 0.3)"
lineWidth="2px"
lineHeight="40px"
baseAngle={0}
style={{ margin: "0 auto" }}
/>
<div className="absolute bottom-8 right-8 text-xs text-gray-500 font-mono">
MOVE CURSOR
</div>
</div>
</div>
);
}
~~~
~~~/package.json
{
"name": "magnet-lines",
"description": "A grid of lines that rotate to point towards the cursor position",
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0",
"framer-motion": "^10.0.0",
"lucide-react": "^0.200.0"
}
}
~~~
~~~/src/MagnetLines.tsx
import React, { useRef, useEffect, CSSProperties } from 'react';
export interface MagnetLinesProps {
rows?: number;
columns?: number;
containerSize?: string;
lineColor?: string;
lineWidth?: string;
lineHeight?: string;
baseAngle?: number;
className?: string;
style?: CSSProperties;
}
const MagnetLines: React.FC<MagnetLinesProps> = ({
rows = 9,
columns = 9,
containerSize = '80vmin',
lineColor = '#efefef',
lineWidth = '1vmin',
lineHeight = '6vmin',
baseAngle = -10,
className = '',
style = {}
}) => {
const containerRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const container = containerRef.current;
if (!container) return;
const items = container.querySelectorAll<HTMLSpanElement>('span');
const onPointerMove = (pointer: { x: number; y: number }) => {
items.forEach(item => {
const rect = item.getBoundingClientRect();
const centerX = rect.x + rect.width / 2;
const centerY = rect.y + rect.height / 2;
const b = pointer.x - centerX;
const a = pointer.y - centerY;
const c = Math.sqrt(a * a + b * b) || 1;
const r = ((Math.acos(b / c) * 180) / Math.PI) * (pointer.y > centerY ? 1 : -1);
item.style.setProperty('--rotate', `${r}deg`);
});
};
const handlePointerMove = (e: PointerEvent) => {
onPointerMove({ x: e.x, y: e.y });
};
window.addEventListener('pointermove', handlePointerMove);
// Trigger initial calculation
if (items.length) {
const middleIndex = Math.floor(items.length / 2);
const rect = items[middleIndex].getBoundingClientRect();
onPointerMove({ x: rect.x, y: rect.y });
}
return () => {
window.removeEventListener('pointermove', handlePointerMove);
};
}, []);
const total = rows * columns;
// Create spans with inline styles for the base rotation
const spans = Array.from({ length: total }, (_, i) => (
<span
key={i}
className="block origin-center"
style={{
backgroundColor: lineColor,
width: lineWidth,
height: lineHeight,
// @ts-ignore
'--rotate': `${baseAngle}deg`,
transform: 'rotate(var(--rotate))',
willChange: 'transform'
}}
/>
));
return (
<div
ref={containerRef}
className={`grid place-items-center ${className}`}
style={{
gridTemplateColumns: `repeat(${columns}, 1fr)`,
gridTemplateRows: `repeat(${rows}, 1fr)`,
width: containerSize,
height: containerSize,
...style
}}
>
{spans}
</div>
);
};
export default MagnetLines;
~~~
Implementation Guidelines
1. Analyze the component structure, styling, animation implementations
2. Review the component's arguments and state
3. Think through what is the best place to adopt this component/style into the design we are doing
4. Then adopt the component/design to our current system
Help me integrate this into my design