# Topography

> A 3D landscape drawn in glowing contour lines that rises under the cursor, with light pulses on click.

A flat contour map rises into a 3D landscape of glowing lines while the camera glides over it, drawn with raw WebGL2 and a soft bloom. Move the cursor to lift the land under it (or trace and light its contour) and lean the camera toward it, and click to send a pulse of light rolling across the terrain or to raise a new peak. No extra dependencies.

<demo-topography>



</demo-topography>

## Installation

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

## Usage

```vue
<script setup lang="ts">
  import Topography from '~/components/ui/topography/Topography.vue';
</script>

<template>
  <div class="relative h-125 w-full overflow-hidden">
    <Topography
      color="#4f7cff"
      :line-count="22"
      :line-width="1.2"
      :elevation="1"
      :tilt="32"
      :speed="0.25"
      :glow="0.6"
      hover-effect="lift"
      click-effect="pulse"
    />
  </div>
</template>
```

Set `:tilt="90"` with `markers="plus"` for a top-down survey map, or `click-effect="peak"` to raise mountains where you click. On light pages pass `light-mode`: the lines draw as crisp ink instead of glowing light.

## Props

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

<tbody>
  <tr>
    <td>
      <code>
        color
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        '#4f7cff'
      </code>
    </td>
    
    <td>
      Color of the contour lines. The brightest lines glow toward white.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        line-count
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        22
      </code>
    </td>
    
    <td>
      How many contour lines stack up the tallest mountain.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        line-width
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1.2
      </code>
    </td>
    
    <td>
      Width of the lines in px. Nearer lines draw a little thicker.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        major-lines
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Draws every fifth line bolder and brighter, like the index lines on a map.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        elevation
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      How tall the mountains rise. 0 lays the map flat.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        foreground
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.2
      </code>
    </td>
    
    <td>
      How much height the land keeps as it reaches the camera. Low values settle it flat so the view stays clear.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        scale
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Size of the landforms. Larger values give broader mountains.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        detail
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.35
      </code>
    </td>
    
    <td>
      Fine wobble in the lines and small rings on the plains, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        tilt
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        32
      </code>
    </td>
    
    <td>
      Camera angle in degrees, from a low view across the land to 90 for straight down.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        speed
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.25
      </code>
    </td>
    
    <td>
      How fast the camera glides over the land.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        direction
      </code>
    </td>
    
    <td>
      <code>
        'forward' | 'backward' | 'left' | 'right'
      </code>
    </td>
    
    <td>
      <code>
        'forward'
      </code>
    </td>
    
    <td>
      Which way the camera travels.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        morph
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.2
      </code>
    </td>
    
    <td>
      How quickly the landforms reshape over time. 0 keeps the terrain still.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glow
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.6
      </code>
    </td>
    
    <td>
      Soft bloom around the lit lines.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        depth-of-field
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.4
      </code>
    </td>
    
    <td>
      Softens lines away from the focus point, which follows the cursor.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        fog
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.35
      </code>
    </td>
    
    <td>
      How quickly the land fades into the distance. 1 leaves only the foreground.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        brightness
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Overall brightness of the lines.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        opacity
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Overall opacity of the effect.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mouse-interaction
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      Lets the cursor light and shape the terrain, and tilts the camera toward it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        hover-effect
      </code>
    </td>
    
    <td>
      <code>
        'lift' | 'trace' | 'light'
      </code>
    </td>
    
    <td>
      <code>
        'lift'
      </code>
    </td>
    
    <td>
      Lift raises the land under the cursor, trace lights the contour at its height, light only lights it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mouse-radius
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        1
      </code>
    </td>
    
    <td>
      Size of the area the cursor affects.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mouse-strength
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.6
      </code>
    </td>
    
    <td>
      How high the land lifts and how brightly it lights.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        trail
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.3
      </code>
    </td>
    
    <td>
      How long the lifted land takes to settle back, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        parallax
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0.5
      </code>
    </td>
    
    <td>
      How far the camera leans toward the cursor, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        click-effect
      </code>
    </td>
    
    <td>
      <code>
        'pulse' | 'peak' | 'none'
      </code>
    </td>
    
    <td>
      <code>
        'pulse'
      </code>
    </td>
    
    <td>
      Pulse sends a ring of light rolling out over the land, peak raises a new mountain.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        markers
      </code>
    </td>
    
    <td>
      <code>
        'none' | 'plus' | 'dots'
      </code>
    </td>
    
    <td>
      <code>
        'none'
      </code>
    </td>
    
    <td>
      Survey markers on a grid across the land. A few blink, and the ones near the cursor get a target frame.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        glitch
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      <code>
        0
      </code>
    </td>
    
    <td>
      How often brief data glitches slice through the lines, from 0 to 1.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        intro
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        true
      </code>
    </td>
    
    <td>
      The map fades in flat and rises into mountains on mount.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        light-mode
      </code>
    </td>
    
    <td>
      <code>
        boolean
      </code>
    </td>
    
    <td>
      <code>
        false
      </code>
    </td>
    
    <td>
      Draws the lines as crisp ink for light backgrounds instead of glowing light.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        dpr
      </code>
    </td>
    
    <td>
      <code>
        number
      </code>
    </td>
    
    <td>
      auto
    </td>
    
    <td>
      Maximum device pixel ratio, capped at 2.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        class
      </code>
    </td>
    
    <td>
      <code>
        string
      </code>
    </td>
    
    <td>
      <code>
        ''
      </code>
    </td>
    
    <td>
      Extra classes for the container. Inline <code>
        style
      </code>
      
       falls through to the container.
    </td>
  </tr>
</tbody>
</table>

## Accessibility

- The canvas is decorative and carries `aria-hidden="true"`. Put real content above it.
- Pointer events are read from the window, so the effect never blocks clicks on content layered over it.
- With `prefers-reduced-motion: reduce` the camera stops gliding, the terrain stops morphing, the intro and glitches are skipped and the camera no longer leans toward the cursor. Hover lighting and click pulses still respond.
- The render loop sleeps when the effect is idle, offscreen or in a hidden tab.
- Ported from [React Bits](https://reactbits.dev/backgrounds/topography) by David Haz.
