# Grid Distortion

> Image background that breaks into a grid of blocks under the cursor and settles back into place.

An image covers the container without stretching and breaks into a grid of blocks wherever the cursor moves. The blocks drift back into place on their own. Click to send a ring of displaced cells across the image. Modes range from crisp blocks to a liquid warp.

<demo-grid-distortion>



</demo-grid-distortion>

## Installation

```bash
npx shadcn-vue@latest add "https://nxui.geoql.in/r/grid-distortion.json"
```

## Usage

```vue
<script setup lang="ts">
  import GridDistortion from '~/components/ui/grid-distortion/GridDistortion.vue';
</script>

<template>
  <div class="relative h-125 w-full overflow-hidden">
    <GridDistortion
      image-src="https://images.unsplash.com/photo-1419242902214-272b3f66ee7a?w=1920"
      :grid="24"
      :strength="0.25"
      :relaxation="0.95"
      :softness="1"
    />
  </div>
</template>
```

The image is loaded with `crossOrigin="anonymous"`, so remote images must be
served with CORS headers.

## Props

<table>
<thead>
  <tr>
    <th>
      Prop
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        image-src
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      —
    </td>
    
    <td>
      Image to distort. It covers the container.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        grid
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        15
      </code>
    </td>
    
    <td>
      Number of cells across. Rows follow the container so cells stay square.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.18
      </code>
    </td>
    
    <td>
      Reach of the pointer as a fraction of the container width.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        strength
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.15
      </code>
    </td>
    
    <td>
      How far the pointer throws the cells. 0 turns the pointer off.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        relaxation
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.96
      </code>
    </td>
    
    <td>
      How much displacement each cell keeps per frame. Higher values settle more slowly.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mode
      </code>
    </td>
    
    <td>
      <code>
        'drag' | 'push' | 'swirl'
      </code>
    </td>
    
    <td>
      <code>
        'drag'
      </code>
    </td>
    
    <td>
      Drag pulls cells along with the pointer, push throws them outward and swirl spins them around.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        softness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Blends the crisp blocks into a smooth liquid warp, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        chroma
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      Splits the color channels on displaced cells, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        idle
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.3
      </code>
    </td>
    
    <td>
      A slow wandering distortion that keeps the image alive while the pointer rests. 0 turns it off.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        click-ripple
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Sends a ring of displaced cells out from every click.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Scrambles the cells when the image loads and lets them settle into place.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the container.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The canvas is decorative and has `aria-hidden="true"`. If the image carries meaning, describe it in nearby text.
- With `prefers-reduced-motion: reduce`, the intro scramble, idle drift and click ripples are off. The image only moves when you move the cursor.
- The animation stops when the grid has settled and while the container is offscreen.
- Ported from [React Bits](https://reactbits.dev/backgrounds/grid-distortion) by David Haz.
