OpenSeadragon: Zoomable Image Viewer in JavaScript

Category: Image , Javascript , Recommended | June 20, 2026
Authoropenseadragon
Last UpdateJune 20, 2026
LicenseMIT
Views0 views
OpenSeadragon: Zoomable Image Viewer in JavaScript

OpenSeadragon is a pure JavaScript image viewer that displays high-resolution images with pan, zoom, rotation, overlay, and fullscreen controls.

It supports tiled image formats such as DZI and IIIF, plus standard image files for smaller image viewer projects.

You can use the library for digitized manuscripts, maps, product photography, scientific imagery, image comparison tools, and any interface where a normal <img> element cannot provide enough inspection detail.

Features:

  • Display standard images and tiled deep zoom sources.
  • Support DZI, IIIF, IIP, Zoomify, TMS, OSM, and custom tile sources.
  • Pan images through mouse, touch, pen, and keyboard input.
  • Configurable zoom, rotation, flip, fullscreen, and home controls.
  • Navigator minimap for large image navigation.
  • Position HTML overlays in viewport coordinates.
  • Display image sequences and thumbnail reference strips.
  • Arrange multiple images in collection layouts.
  • WebGL, canvas, HTML, or custom rendering drawers.
  • Tile loading, viewport, canvas, and fullscreen events.
  • Works with plugins for annotations, filters, and WebGL shaders.

Use Cases:

  • Museum and archive sites present scanned paintings, maps, and manuscripts at inspection-level detail.
  • Product-detail pages benefit when texture, engraving, condition, or assembly detail affects a purchase decision.
  • Microscopy and research portals need a browser viewer for datasets too large to publish as static, downscaled images.
  • Annotation workflows place region comments, comparison layers, and measurement tools over a shared high-resolution image.

How To Use It:

Installation

OpenSeadragon works as a browser script and exposes the OpenSeadragon global object.

<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/openseadragon/openseadragon.min.js"></script>

The default navigation buttons use image files from the package. Point prefixUrl to the matching images directory.

<script>
  const viewer = OpenSeadragon({
    id: 'image-viewer',
    prefixUrl: 'https://cdn.jsdelivr.net/npm/[email protected]/build/openseadragon/images/'
  });
</script>

Install the package through npm when your project uses a bundler or CommonJS build process.

npm install openseadragon
const OpenSeadragon = require('openseadragon');

The package exposes a CommonJS entry point and includes TypeScript declaration files.

Basic Usage

A DZI source fits document viewers, maps, and image collections that need fast deep zoom behavior. Give the viewer element a fixed or responsive height before initializing it.

<div id="archive-viewer" class="deep-zoom-viewer"></div>
<style>
  .deep-zoom-viewer {
    width: 100%;
    height: 620px;
    background: #111;
  }
</style>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/openseadragon/openseadragon.min.js"></script>
<script>
  const archiveViewer = OpenSeadragon({
    id: 'archive-viewer',
    prefixUrl: 'https://cdn.jsdelivr.net/npm/[email protected]/build/openseadragon/images/',
    tileSources: '/media/archive/blueprint-page.dzi',
    // Show a minimap for large documents.
    showNavigator: true,
    // Add rotation buttons to the default control set.
    showRotationControl: true,
    // Limit excessive zoom beyond source pixels.
    maxZoomPixelRatio: 2
  });
</script>

Advanced Usages

Open a Standard Image

Standard JPEG and PNG assets do not require a tiled image manifest. The configuration below opens one image through OpenSeadragon’s built-in image tile source.

archiveViewer.open({
  type: 'image',
  url: '/media/products/camera-detail.jpg'
});

A standard image source works for moderate image sizes. DZI or IIIF sources work better when visitors must inspect very large files at deep zoom levels.

Load an IIIF Image

IIIF image services expose source metadata through an info.json endpoint. Pass that endpoint to tileSources and configure CORS when the viewer needs cross-origin image access.

const manuscriptViewer = OpenSeadragon({
  id: 'archive-viewer',
  prefixUrl: 'https://cdn.jsdelivr.net/npm/[email protected]/build/openseadragon/images/',
  tileSources: 'https://images.example.org/iiif/manuscript-144/info.json',
  // Required when your image service supports cross-origin requests.
  crossOriginPolicy: 'Anonymous',
  showNavigator: true,
  showFullPageControl: true
});

Your IIIF service must send compatible CORS headers when the viewer needs pixel access through canvas or WebGL rendering.

Add an Interactive Image Hotspot

Image annotations need coordinates that remain aligned as the viewport zooms, pans, rotates, or flips. This overlay places a native button in viewport coordinates instead of fixed page coordinates.

const chapterMarker = document.createElement('button');
chapterMarker.type = 'button';
chapterMarker.className = 'image-hotspot';
chapterMarker.textContent = 'Chapter 4';
chapterMarker.addEventListener('click', function () {
  console.log('Open the Chapter 4 details panel.');
});
// x, y, width, and height use viewport coordinates.
archiveViewer.addOverlay(
  chapterMarker,
  new OpenSeadragon.Rect(0.34, 0.22, 0.12, 0.05)
);

Use outline instead of border for overlays that must align precisely with image content. Borders affect the overlay dimensions.

Create an Image Sequence

Multi-page scans and related image sets work better as one navigable sequence than as separate viewer instances. Enable sequence mode and provide each page as an item in the tileSources array.

const bookViewer = OpenSeadragon({
  id: 'archive-viewer',
  prefixUrl: 'https://cdn.jsdelivr.net/npm/[email protected]/build/openseadragon/images/',
  sequenceMode: true,
  showReferenceStrip: true,
  tileSources: [
    '/media/book/page-01.dzi',
    '/media/book/page-02.dzi',
    '/media/book/page-03.dzi'
  ]
});

Sequence mode provides page navigation controls and supports a thumbnail reference strip.

Configuration Options

Container and Source Options

  • id (string): ID of the element that receives the viewer.
  • element (HTMLElement): DOM element that receives the viewer.
  • tileSources (string | object | array | function): Initial image or tile source configuration.
  • tabIndex (number): Keyboard tab order for the viewer element.
  • overlays (array): Permanent overlay definitions.
  • toolbar (string | HTMLElement): Container for custom navigation controls.
  • xmlPath (string): Deprecated DZI XML path option.
  • prefixUrl (string): Base path for built-in navigation button images.
  • navImages (object): Custom image paths for default navigation buttons.

Rendering Options

  • debugMode (boolean): Shows tile debugging information.
  • debugGridColor (string | array): Colors for tile grids in debug mode.
  • silenceMultiImageWarnings (boolean): Hides coordinate warnings for multi-image viewers.
  • blendTime (number): Tile fade duration in seconds.
  • alwaysBlend (boolean): Forces tile blending during updates.
  • autoHideControls (boolean): Fades default controls after inactivity.
  • immediateRender (boolean): Prioritizes the closest tile level.
  • defaultZoomLevel (number): Initial zoom level after opening an image.
  • drawer (string | constructor | array): Preferred rendering drawer order.
  • drawerOptions (object): Drawer-specific configuration.
  • opacity (number): Default tiled image opacity.
  • preload (boolean): Loads hidden tiled images.
  • compositeOperation (string): Canvas compositing mode for tiled images.
  • imageSmoothingEnabled (boolean): Enables image smoothing where supported.
  • placeholderFillStyle (string | CanvasGradient | CanvasPattern): Fill behind tiles that have not loaded.
  • subPixelRoundingForTransparency (object): Tile rounding behavior for transparent images.
  • degrees (number): Initial image rotation.
  • flipped (boolean): Initial horizontal flip state.
  • overlayPreserveContentDirection (boolean): Keeps overlay text readable after a flip.

Viewport and Resize Options

  • minZoomLevel (number): Minimum permitted zoom level.
  • maxZoomLevel (number): Maximum permitted zoom level.
  • homeFillsViewer (boolean): Crops the image to fill the viewer at home position.
  • panHorizontal (boolean): Enables horizontal panning.
  • panVertical (boolean): Enables vertical panning.
  • constrainDuringPan (boolean): Applies viewport constraints during dragging.
  • wrapHorizontal (boolean): Repeats images horizontally.
  • wrapVertical (boolean): Repeats images vertically.
  • minZoomImageRatio (number): Minimum image-to-viewport ratio.
  • maxZoomPixelRatio (number): Maximum zoom ratio against source pixels.
  • smoothTileEdgesMinZoom (number): Zoom level that activates tile-edge smoothing.
  • iOSDevice (boolean): Overrides automatic iOS detection.
  • autoResize (boolean): Watches for viewer size changes.
  • preserveImageSizeOnResize (boolean): Preserves image size after a viewer resize.
  • viewportMargins (object): Insets for the home viewport region.

Interaction and Animation Options

  • minScrollDeltaTime (number): Minimum time between wheel zoom events.
  • rotationIncrement (number): Rotation angle for rotation controls.
  • maxTilesPerFrame (number): Maximum number of tile loads per frame.
  • pixelsPerWheelLine (number): Pixel distance treated as one wheel line.
  • pixelsPerArrowPress (number): Viewport movement for arrow key input.
  • visibilityRatio (number): Minimum image area that remains visible.
  • imageLoaderLimit (number): Maximum concurrent image requests.
  • clickTimeThreshold (number): Maximum duration for a click gesture.
  • clickDistThreshold (number): Maximum movement for a click gesture.
  • dblClickTimeThreshold (number): Maximum duration between double clicks.
  • dblClickDistThreshold (number): Maximum movement between double clicks.
  • springStiffness (number): Viewport animation stiffness.
  • animationTime (number): Viewport animation duration.
  • loadDestinationTilesOnAnimation (boolean): Loads tiles at the animation destination.
  • zoomPerClick (number): Zoom multiplier for click-to-zoom.
  • zoomPerScroll (number): Zoom multiplier for wheel input.
  • zoomPerDblClickDrag (number): Zoom multiplier for double-click drag input.
  • zoomPerSecond (number): Zoom speed for held controls.

Gesture Options

  • gestureSettingsMouse (object): Mouse-specific gesture settings.
  • gestureSettingsTouch (object): Touch-specific gesture settings.
  • gestureSettingsPen (object): Pen-specific gesture settings.
  • gestureSettingsUnknown (object): Fallback gesture settings.

Each gesture configuration accepts these properties:

  • dragToPan (boolean): Enables drag panning.
  • scrollToZoom (boolean): Enables wheel zooming.
  • clickToZoom (boolean): Enables click zooming.
  • dblClickToZoom (boolean): Enables double-click zooming.
  • dblClickDragToZoom (boolean): Enables double-click drag zooming.
  • pinchToZoom (boolean): Enables pinch zooming.
  • zoomToRefPoint (boolean): Zooms around the pointer location.
  • flickEnabled (boolean): Enables flick gestures.
  • flickMinSpeed (number): Minimum flick speed.
  • flickMomentum (number): Flick momentum multiplier.
  • pinchRotate (boolean): Enables touch rotation.

Navigator Options

  • showNavigator (boolean): Displays the navigator minimap.
  • navigatorElement (HTMLElement): Existing element for the navigator.
  • navigatorId (string): ID for the navigator element.
  • navigatorPosition (string): Navigator placement.
  • navigatorSizeRatio (number): Navigator-to-viewer size ratio.
  • navigatorMaintainSizeRatio (boolean): Resizes the navigator with the viewer.
  • navigatorTop (number | string): Navigator top position.
  • navigatorLeft (number | string): Navigator left position.
  • navigatorHeight (number | string): Navigator height.
  • navigatorWidth (number | string): Navigator width.
  • navigatorAutoFade (boolean): Fades the navigator after inactivity.
  • navigatorRotate (boolean): Rotates the navigator with the viewport.
  • navigatorBackground (string): Navigator background color.
  • navigatorOpacity (number): Navigator opacity.
  • navigatorBorderColor (string): Navigator border color.
  • navigatorDisplayRegionColor (string): Current viewport rectangle color.

Tile Loading and Cache Options

  • controlsFadeDelay (number): Delay before control fade begins.
  • controlsFadeLength (number): Duration of control fading.
  • maxImageCacheCount (number): Maximum cached tile images.
  • timeout (number): Tile request timeout.
  • tileRetryMax (number): Maximum tile retry attempts.
  • tileRetryDelay (number): Delay between tile retries.
  • useCanvas (boolean): Deprecated renderer preference.
  • minPixelRatio (number): Minimum pixel ratio for tile selection.
  • crossOriginPolicy (string | false): CORS mode for tile requests.
  • ajaxWithCredentials (boolean): Sends credentials with AJAX tile requests.
  • loadTilesWithAjax (boolean): Loads tiles through AJAX requests.
  • ajaxHeaders (object): Custom headers for tile and tile source requests.
  • splitHashDataForPost (boolean): Treats hash content in a source URL as POST data.
  • callTileLoadedWithCachedData (boolean): Fires tile-loaded events for cached source data.

Navigation Control Options

  • mouseNavEnabled (boolean): Enables mouse and touch navigation.
  • keyboardNavEnabled (boolean): Enables keyboard navigation.
  • showNavigationControl (boolean): Shows default navigation controls.
  • navigationControlAnchor (string): Placement for default navigation controls.
  • showZoomControl (boolean): Shows zoom controls.
  • showHomeControl (boolean): Shows the home button.
  • showFullPageControl (boolean): Shows the full-page button.
  • showRotationControl (boolean): Shows rotation buttons.
  • showFlipControl (boolean): Shows the flip button.
  • showSequenceControl (boolean): Shows sequence navigation buttons.
  • sequenceControlAnchor (string): Placement for sequence controls.
  • navPrevNextWrap (boolean): Wraps previous and next sequence navigation.
  • zoomInButton (string | Element): Custom zoom-in control.
  • zoomOutButton (string | Element): Custom zoom-out control.
  • homeButton (string | Element): Custom home control.
  • fullPageButton (string | Element): Custom full-page control.
  • rotateLeftButton (string | Element): Custom rotate-left control.
  • rotateRightButton (string | Element): Custom rotate-right control.
  • previousButton (string | Element): Custom previous-page control.
  • nextButton (string | Element): Custom next-page control.

Sequence and Collection Options

  • sequenceMode (boolean): Opens tile sources as separate pages.
  • initialPage (number): Initial sequence page index.
  • preserveViewport (boolean): Keeps the viewport position between pages.
  • preserveOverlays (boolean): Keeps added overlays between pages.
  • showReferenceStrip (boolean): Displays a page thumbnail strip.
  • referenceStripScroll (string): Thumbnail strip scroll direction.
  • referenceStripElement (HTMLElement): Existing thumbnail strip container.
  • referenceStripHeight (number): Thumbnail strip height.
  • referenceStripWidth (number): Thumbnail strip width.
  • referenceStripPosition (string): Thumbnail strip placement.
  • referenceStripSizeRatio (number): Thumbnail size ratio.
  • collectionMode (boolean): Arranges multiple images in a collection.
  • collectionRows (number): Number of collection rows.
  • collectionColumns (number): Number of collection columns.
  • collectionLayout (string): Horizontal or vertical collection layout.
  • collectionTileSize (number): Viewport size for collection items.
  • collectionTileMargin (number): Gap between collection items.

Core Viewer API Methods

// Open a DZI, IIIF endpoint, simple image source, or array of sources.
archiveViewer.open('/media/archive/new-map.dzi');
// Close the active image source.
archiveViewer.close();
// Destroy the viewer and remove internal event handlers.
archiveViewer.destroy();
// Add a tiled image to an existing multi-image viewer.
archiveViewer.addTiledImage({
  tileSource: '/media/layers/annotation-layer.dzi',
  opacity: 0.65
});
// Add an HTML overlay in viewport coordinates.
archiveViewer.addOverlay(
  document.querySelector('#map-marker'),
  new OpenSeadragon.Rect(0.25, 0.35, 0.08, 0.06)
);
// Remove an existing overlay.
archiveViewer.removeOverlay('map-marker');
// Update the position or size of an existing overlay.
archiveViewer.updateOverlay(
  'map-marker',
  new OpenSeadragon.Rect(0.42, 0.18, 0.08, 0.06)
);
// Open a specific sequence page.
archiveViewer.goToPage(3);
// Move to adjacent sequence pages.
archiveViewer.goToPreviousPage();
archiveViewer.goToNextPage();
// Enter or leave full-page mode.
archiveViewer.setFullPage(true);
// Enter or leave browser fullscreen mode.
archiveViewer.setFullScreen(true);
// Enable or disable mouse and touch navigation.
archiveViewer.setMouseNavEnabled(false);
// Enable or disable keyboard navigation.
archiveViewer.setKeyboardNavEnabled(true);
// Show or hide the entire viewer.
archiveViewer.setVisible(false);
// Add request headers for secured image services.
archiveViewer.setAjaxHeaders({
  Authorization: 'Bearer example-access-token'
});
// Recalculate viewer dimensions after a layout change.
archiveViewer.forceResize();
// Request a new render frame.
archiveViewer.forceRedraw();
// Run code after tiles for the current viewport finish loading.
archiveViewer.whenFullyLoaded(function () {
  console.log('The current viewport is ready.');
});
// Return the viewport to its home position.
archiveViewer.viewport.goHome();
// Zoom by a multiplier around the current center.
archiveViewer.viewport.zoomBy(1.5);
// Zoom to an exact viewport zoom level.
archiveViewer.viewport.zoomTo(4);
// Pan to a viewport coordinate.
archiveViewer.viewport.panTo(new OpenSeadragon.Point(0.5, 0.4));
// Fit a specific viewport rectangle.
archiveViewer.viewport.fitBounds(
  new OpenSeadragon.Rect(0.2, 0.15, 0.35, 0.25)
);
// Rotate the current viewport.
archiveViewer.viewport.rotateTo(90);
// Toggle horizontal image flip.
archiveViewer.viewport.toggleFlip();

Events

OpenSeadragon uses addHandler() for viewer events. The event API covers image loading, viewport movement, tile rendering, canvas input, overlays, sequence navigation, and fullscreen state changes.

// Fires after a tile source opens successfully.
archiveViewer.addHandler('open', function (event) {
  console.log('Image source opened.', event.source);
});
// Fires when a tile source cannot load.
archiveViewer.addHandler('open-failed', function (event) {
  console.error('Image source failed.', event.message);
});
// Fires after zoom input changes the viewport.
archiveViewer.addHandler('zoom', function (event) {
  console.log('Zoom level changed.', event.zoom);
});
// Fires after viewport panning.
archiveViewer.addHandler('pan', function (event) {
  console.log('Viewport center changed.', event.center);
});
// Fires during viewport updates.
archiveViewer.addHandler('viewport-change', function () {
  console.log('Viewport position changed.');
});
// Fires after viewport animation ends.
archiveViewer.addHandler('animation-finish', function () {
  console.log('Viewer motion completed.');
});
// Fires after a quick primary click inside the viewer.
archiveViewer.addHandler('canvas-click', function (event) {
  if (event.quick) {
    console.log('Viewer click position.', event.position);
  }
});
// Fires after a tile loads.
archiveViewer.addHandler('tile-loaded', function (event) {
  console.log('Tile loaded.', event.tile);
});
// Fires when a tile request fails.
archiveViewer.addHandler('tile-load-failed', function (event) {
  console.error('Tile failed.', event.message);
});
// Fires when a sequence page changes.
archiveViewer.addHandler('page', function (event) {
  console.log('Current page index.', event.page);
});
// Fires after the viewer enters or leaves fullscreen.
archiveViewer.addHandler('full-screen', function (event) {
  console.log('Fullscreen state.', event.fullScreen);
});
// Fires after the viewer enters or leaves full-page mode.
archiveViewer.addHandler('full-page', function (event) {
  console.log('Full-page state.', event.fullPage);
});

Alternatives:

FAQs:

Q: Does OpenSeadragon work with normal JPEG and PNG images?
A: Yes. Open an image source with type: 'image' and a file URL. DZI and IIIF sources provide better deep zoom behavior for very large images.

Q: Why does the viewer area stay blank?
A: Check the container height first. Then confirm that the tile source URL returns valid image data and that prefixUrl points to the control icon directory.

Q: Does OpenSeadragon support IIIF image services?
A: Yes. Pass the IIIF info.json endpoint as a tile source. Your image service needs compatible CORS headers for cross-origin canvas or WebGL use.

Q: Can I add annotations or clickable content over an image?
A: Yes. Use overlays for HTML labels, buttons, and markers that move with the viewport. SVG, canvas, Fabric.js, and annotation plugins support more specialized annotation interfaces.

Q: What is the difference between sequence mode and collection mode?
A: Sequence mode displays one image at a time with navigation controls. Collection mode arranges multiple images in a grid or line within the same viewport.

You Might Be Interested In:


Leave a Reply