
# React 3D Tag Sphere

A React component for creating interactive 3D tag clouds with images and text. This component uses a canvas to render a visually appealing tag sphere that can be customized to fit various use cases such as skill showcases, image displays, and more.

## Installation

Install the package using npm or yarn:

```bash
npm install react-3d-tag-sphere
# or
yarn add react-3d-tag-sphere
```

## Features

- **3D Sphere Rendering**: Distributes tags evenly using a Fibonacci sphere algorithm.
- **Horizontal Mode**: Optional cylindrical distribution for a horizontal tag cloud layout.
- **Interactive Rotations**: Supports mouse movements for dynamic rotation with inverse tracking (sphere moves opposite to cursor).
- **Pulse Animation**: Optional pulse effect that resets rotation when the mouse leaves the canvas.
- **Customizable Rotation Speed**: Control the speed of automatic rotation.
- **Image-Based Tags**: Each tag can display an image with optional customization.
- **Smooth Animations**: Offers fluid animations and scaling for tags.

## Demo Video

Here is a demo of the project in action:

![Tag Cloud Canvas Video](https://github.com/Bum-Ho12/react-3d-tag-sphere/blob/main/tagCloudCanvasVideo.gif)


## Usage

### Import and Setup

```tsx
import React from "react";
import { TagCloudCanvas } from 'react-3d-tag-sphere';

const MyComponent = () => {
  const skills = [
    { src: 'path/to/image1.svg', size: 30 },
    { src: 'path/to/image2.png', size: 40 },
    // Add more tags as needed
  ];

  return (
    <TagCloudCanvas
      tags={skills}
      height={300}
      width={300}
    />
  );
};

export default MyComponent;
```

### Props

| Prop   | Type     | Required | Default | Description                                          |
|--------|----------|----------|---------|------------------------------------------------------|
| `tags` | `Tag[]`  | Yes      | -       | Array of tags to render. See the Tag interface below.|
| `height` | `number` | Yes      | -       | Height of the canvas in pixels.                     |
| `width` | `number` | Yes      | -       | Width of the canvas in pixels.                      |
| `rotationSpeed` | `number` | No | `0.5` | Speed multiplier for rotation (higher = faster).    |
| `enablePulse` | `boolean` | No | `false` | Enables pulse animation and resets rotation on mouse leave. |
| `mode` | `'sphere'` \| `'horizontal'` | No | `'sphere'` | Layout mode: `'sphere'` for 3D sphere or `'horizontal'` for cylindrical layout. |

#### Tag Interface

```ts
interface Tag {
  src: string;       // Image source URL (required)
  size?: number;     // Size of the tag in pixels (auto-calculated based on canvas size if not provided)
  // The following properties are auto-calculated and shouldn't be set manually:
  phi?: number;      // Vertical angle (auto-calculated)
  theta?: number;    // Horizontal angle (auto-calculated)
  x?: number;        // X position on unit sphere (auto-calculated)
  y?: number;        // Y position on unit sphere (auto-calculated)
  z?: number;        // Z position on unit sphere (auto-calculated)
  img?: HTMLImageElement; // Loaded image element (auto-populated)
}
```

### Example Configuration

#### Basic Example
```tsx
const Example = () => {
  const tags = [
    { src: '/images/html.svg', size: 30 },
    { src: '/images/css.svg', size: 40 },
    { src: '/images/javascript.svg', size: 35 },
  ];

  return (
    <TagCloudCanvas
      tags={tags}
      height={500}
      width={500}
    />
  );
};

export default Example;
```

#### Advanced Example with All Props
```tsx
import { useState } from 'react';
import { TagCloudCanvas } from 'react-3d-tag-sphere';

const AdvancedExample = () => {
  const [mode, setMode] = useState<'sphere' | 'horizontal'>('sphere');
  const [enablePulse, setEnablePulse] = useState(false);

  const tags = [
    { src: '/images/react.png', size: 60 },
    { src: '/images/typescript.png', size: 60 },
    { src: '/images/javascript.png', size: 60 },
    { src: '/images/html.png', size: 60 },
    { src: '/images/css.png', size: 60 },
  ];

  return (
    <div>
      <div style={{ marginBottom: '20px' }}>
        <label>
          <input
            type="checkbox"
            checked={enablePulse}
            onChange={(e) => setEnablePulse(e.target.checked)}
          />
          Enable Pulse (Reset on Mouse Leave)
        </label>
        <label style={{ marginLeft: '20px' }}>
          <input
            type="checkbox"
            onChange={(e) => setMode(e.target.checked ? 'horizontal' : 'sphere')}
          />
          Horizontal Mode
        </label>
      </div>
      
      <TagCloudCanvas
        tags={tags}
        height={600}
        width={600}
        rotationSpeed={0.5}
        enablePulse={enablePulse}
        mode={mode}
      />
    </div>
  );
};

export default AdvancedExample;
```

## How It Works

The component:
1. **Distribution**: Distributes tags evenly across a spherical surface using the Fibonacci sphere algorithm (for `'sphere'` mode) or cylindrically around the Y-axis (for `'horizontal'` mode).
2. **Image Loading**: Loads image resources asynchronously for smooth rendering.
3. **Interactive Rotation**: 
   - The sphere/cylinder rotates continuously based on the `rotationSpeed` prop.
   - Mouse movement controls the rotation axis - the cloud moves in the **opposite direction** of the cursor for an intuitive feel.
   - In horizontal mode, mouse rotation is disabled and the cloud rotates around the Y-axis automatically.
4. **Pulse Animation** (optional): When `enablePulse` is enabled, the rotation resets to a default diagonal axis when the mouse leaves the canvas.
5. **Depth Perception**: Tags are scaled and their opacity adjusted dynamically based on their Z-depth to create a realistic 3D effect.
6. **Occlusion**: Tags are rendered in order from back to front for proper visual layering.

## Styling and Customization

### Canvas Styling
The `TagCloudCanvas` component uses a canvas element for rendering. You can style the canvas via the `className` attribute or using CSS directly:

```css
canvas {
  background-color: transparent;
  cursor: move;
}
```

### Tag Size and Rotation Speed
Each tag can have a custom size, and the overall rotation speed is controlled via the `rotationSpeed` prop:

```tsx
const tags = [
  { src: '/images/html.svg', size: 50 },
  { src: '/images/css.svg', size: 40 },
  { src: '/images/javascript.svg', size: 60 },
];

<TagCloudCanvas
  tags={tags}
  height={500}
  width={500}
  rotationSpeed={0.8} // Faster rotation
/>
```

## Development Notes

### Fibonacci Sphere Algorithm
The component uses the Fibonacci sphere algorithm to ensure even tag distribution on a spherical surface. Each tag's position is calculated based on its index in the array.

### Interactivity
- **Sphere Mode**: The sphere rotates in the **opposite direction** of the mouse cursor for intuitive control. The rotation axis is determined by your cursor position relative to the canvas center.
- **Horizontal Mode**: Automatically rotates around the vertical (Y) axis, with mouse interaction disabled for consistent behavior.
- **Auto-Rotation**: Both modes feature continuous auto-rotation at the speed defined by `rotationSpeed`.
- **Pulse Mode**: Enable `enablePulse` to reset the rotation axis to a diagonal when the mouse leaves the canvas area.

### Performance Optimization
To optimize rendering performance:
- Minimize the number of tags.
- Use appropriately sized images to reduce load time.

## License

This project is licensed under the MIT License. See the LICENSE file for more details.

---

Happy coding with `react-3d-tag-sphere`! 🎉
