npm package: @johnfmorton/deep-zoom-viewer
Description: A modern TypeScript library for viewing tiled DeepZoom (DZI) images with smooth pan/zoom interactions
Author: johnfmorton
Latest version: 0.1.1

# deep-zoom-viewer

A modern TypeScript library for viewing tiled DeepZoom (DZI) images with smooth pan/zoom interactions.

## Features

- Supports DeepZoom (DZI) and Zoomify tile formats
- Smooth pan and zoom with mouse and touch support
- Optional toolbar with zoom controls and fullscreen toggle
- Navigator minimap showing viewport position
- LRU tile caching for optimal performance
- Tile fade-in transitions
- Center-out tile loading priority
- TypeScript with full type definitions
- Zero runtime dependencies (browser)
- CLI tool for generating DZI tiles from images

## Installation

```bash
npm install @johnfmorton/deep-zoom-viewer
```

## Quick Start

```typescript
import { DeepZoomViewer } from '@johnfmorton/deep-zoom-viewer';

const viewer = new DeepZoomViewer('container', {
  source: '/images/my-image.dzi',
  toolbar: true,
  navigator: true
});

// Listen to events
viewer.on('zoom', ({ zoom }) => console.log('Zoom:', zoom));
viewer.on('click', ({ imageX, imageY }) => console.log('Clicked:', imageX, imageY));

// Programmatic control
viewer.setZoom(0.5);
viewer.panTo(1000, 500);
viewer.reset();

// Cleanup when done
viewer.destroy();
```

## HTML Setup

```html
<div id="container" style="width: 800px; height: 600px;"></div>

<script type="module">
  import { DeepZoomViewer } from '@johnfmorton/deep-zoom-viewer';

  new DeepZoomViewer('container', {
    source: '/images/photo.dzi'
  });
</script>
```

## Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `source` | `string` | required | Path to DZI file or Zoomify directory |
| `tileSource` | `'deepzoom' \| 'zoomify' \| 'auto'` | `'auto'` | Tile format (auto-detected) |
| `minZoom` | `number` | fit-to-view | Minimum zoom level |
| `maxZoom` | `number` | `1.0` | Maximum zoom (1.0 = native resolution) |
| `constrainPan` | `boolean` | `true` | Keep image within viewport |
| `toolbar` | `boolean` | `false` | Show zoom controls |
| `navigator` | `boolean` | `false` | Show minimap |
| `animationDuration` | `number` | `300` | Transition duration (ms) |

## Events

| Event | Data | Description |
|-------|------|-------------|
| `ready` | - | Viewer initialized |
| `zoom` | `{ zoom, source }` | Zoom level changed |
| `pan` | `{ centerX, centerY, source }` | Viewport panned |
| `viewChange` | `{ centerX, centerY, zoom, source }` | Any view change |
| `click` | `{ imageX, imageY, viewportX, viewportY }` | Image clicked/tapped |
| `tileLoad` | `{ tile }` | Tile finished loading |
| `tileError` | `{ tile, error }` | Tile failed to load |
| `tilesLoaded` | - | All visible tiles loaded |
| `fullscreen` | `{ isFullscreen }` | Fullscreen state changed |
| `resize` | `{ width, height }` | Viewport resized |

## API Methods

### View Control

```typescript
// Zoom
viewer.setZoom(0.5);       // Set zoom level
viewer.zoomIn();           // Zoom in by 1.5x
viewer.zoomOut();          // Zoom out by 1.5x
viewer.getZoom();          // Get current zoom

// Pan
viewer.panTo(x, y);        // Pan to image coordinates
viewer.getCenter();        // Get current center { x, y }

// Reset
viewer.reset();            // Reset to fit view
```

### Coordinate Conversion

```typescript
// Convert between viewport and image coordinates
const imgPos = viewer.viewportToImage(viewportX, viewportY);
const vpPos = viewer.imageToViewport(imageX, imageY);
```

### UI Components

```typescript
viewer.setToolbarVisible(true);
viewer.setNavigatorVisible(true);
```

### Utilities

```typescript
viewer.getImageSize();     // { width, height }
viewer.getViewportSize();  // { width, height }
viewer.refresh();          // Force re-render
viewer.destroy();          // Clean up resources
```

## Generating DZI Tiles

Use the CLI tool to convert images to DZI format:

```bash
# Basic usage
npx @johnfmorton/deep-zoom-viewer generate input.jpg output/

# With options
npx @johnfmorton/deep-zoom-viewer generate input.jpg output/ \
  --tile-size 256 \
  --format jpg \
  --quality 85
```

### CLI Options

| Option | Default | Description |
|--------|---------|-------------|
| `-s, --tile-size` | `256` | Tile size in pixels |
| `-o, --overlap` | `0` | Tile overlap in pixels |
| `-f, --format` | `jpg` | Output format (jpg, png, webp) |
| `-q, --quality` | `85` | Output quality (1-100) |

### Output Structure

```
output/
├── image.dzi           # DZI XML descriptor
└── image_files/
    ├── 0/              # Smallest tier
    │   └── 0_0.jpg
    ├── 1/
    │   ├── 0_0.jpg
    │   └── 1_0.jpg
    └── N/              # Full resolution tier
        └── ...
```

## DeepZoom Format

### DZI XML File

```xml
<?xml version="1.0" encoding="UTF-8"?>
<Image TileSize="256" Overlap="0" Format="jpg"
       xmlns="http://schemas.microsoft.com/deepzoom/2008">
  <Size Width="4000" Height="3000"/>
</Image>
```

### Tile Naming

Tiles are named `{column}_{row}.{format}` (e.g., `3_2.jpg`).

## Advanced Usage

### Custom Tile Source

```typescript
import { TileSource, DeepZoomViewer } from '@johnfmorton/deep-zoom-viewer';

class CustomTileSource extends TileSource {
  async load() {
    return {
      width: 4000,
      height: 3000,
      tileSize: 256,
      overlap: 0,
      format: 'jpg'
    };
  }

  getTileUrl(tier, col, row) {
    return `/tiles/${tier}/${col}_${row}.jpg`;
  }

  getType() {
    return 'custom';
  }
}
```

### Accessing Internal Components

```typescript
// For advanced customization
import { Viewport, TilePyramid, TileManager } from '@johnfmorton/deep-zoom-viewer';
```

## Browser Support

- Chrome 80+
- Firefox 75+
- Safari 13+
- Edge 80+

## Development

```bash
# Install dependencies
npm install

# Start dev server
npm run dev

# Run tests
npm test

# Build
npm run build

# Generate docs
npm run docs
```

## License

MIT