PanoJS3 - An interactive JavaScript widget for panning and zooming a panoramic image stitched together dynamically from smaller tiles. This widget can be used for viewing images that are much larger than the available space in the browser viewport. Examples include panoramas, maps or high resolution document scans.

Latest version: 3.0.0

Browser Compatibility

PanoJS3 supports all modern major web browsers:

chrome safari firefox ie opera

Supported platforms

PC iPad iPhone

PanoJS3 supports native navigation on most popular platforms:



PanoJS has gone through a couple of name changes. It was first named GSV2 when it was released as the next generation of the Giant Ass Image Viewer originally developed by Michal Migurski. It was then briefly known as GSIV and finally became PanoJS when it became a Google Code project created by Dan Allen. This third version brings many updates to usability, platform support and ease of use.

Download and contributions

Use GitHub repository for contributing to the project and to see the source code online. You can also download the latest release in a ZIP package:

File Size Description
» 196KB source code

What's new

PanoJS3 1.0.0 (2011-01-14) by Dmitry Fedorov:
    * controls UI works for iPhone, iPad and Android
    * support for more events: scroll wheel for zoom, touch events (zoom, scroll)
    * support multiple instances
    * allow view scale beyond 100%
    * good full window support
    * pre-cache tiles in the first row outside of visible area
    * one line instantiator
    * google maps like controls - zoomin on double click
    * center on one click
    * fixed several problems showing tiles
    * small info text about the state: scale, etc...
    * thumbnail navigation
    * IE is again supported - partially, maybe somebody can help?
    * Use ExtJS for events
    * refactoring JavaScript classes
    * provide tile providers: imgcnv, bisque, zoomify and embedded python script

PanoJS 1.0.2 (2009-01-01) by Dan Allen:
    * renamed project to PanoJS
    * change license to Apache License 2.0
    * move project to Google Code
    * respect max zoom level when scaling to window
    * don't alert if max zoom size is exceeded when message is null

GSIV 1.0.1 (2006-03-16) by Dan Allen:
    * added localization for two warning messages
    * fixed the TileUrlProvider checking in the constructor
    * added GSIV.isInstance to check for an instance of a class
    * fixed python script to allow for missing background color parameter

GSIV 1.0.0 (2006-02-26) by Dan Allen:
    * completely new object-oriented design
    * use json options format
    * optimized performance (both in drag, rendering and zoom)
    * fixed rounding error in tile placement that lead to artifact lines
    * added upper zoom limit
    * added initial pan option
    * added observers that can send viewer events to listeners
    * double-click to recenter
    * smooth motion when repositioning
    * method to position absolutely (recenter on absolute point)
    * method to fit to window (resize)
    * additional options for file names and extensions
    * preloading image tiles (loading animation)
    * prevent from scrolling outside of original image boundary (uses blank	tile)
    * throttle mouse move events to increase performance
    * cross-browser mouse cursor implementation that represent dragging
    * account for scroll offset of page when calculating coordinates
    * keyboard events for movement (initial attempt)
    * new python script, using a cleaner design and additional options

GSV 1.0 (2005) by Michal Migurski


Brief usage description

PanoJS requires image tiles to be stored on a web server somewhere so it could fetch on request. You could use a free cross-platform command line utility Bio-Image Convert to split any image into tiles. It's available for Mac, Windows and Linux and is open source so you sould compile it for any other system. The example command line call is the following:

imgcnv -i MY_INPUT_IMAGE.jpg -o MY_OUT_FOLDER/MY_OUT_BASE_NAME.jpg -t jpeg -tile 256

After this, simply create a web page, copy all the PanoJS code in teh same folder and use something similar to the following JavaScript code to instantiate the viewer:

var viewer = null;

function createViewer( viewer, dom_id, url, prefix, w, h ) {
    if (viewer) return;
    var MY_URL      = url;
    var MY_PREFIX   = prefix;
    var MY_TILESIZE = 256;
    var MY_WIDTH    = w;
    var MY_HEIGHT   = h;
    var myPyramid = new ImgcnvPyramid( MY_WIDTH, MY_HEIGHT, MY_TILESIZE);
    var myProvider = new PanoJS.TileUrlProvider('','','');
    myProvider.assembleUrl = function(xIndex, yIndex, zoom) {
        return MY_URL + '/' + MY_PREFIX + myPyramid.tile_filename( zoom, xIndex, yIndex );
    viewer = new PanoJS(dom_id, {
        tileUrlProvider : myProvider,
        tileSize        : myPyramid.tilesize,
        maxZoom         : myPyramid.getMaxLevel(),
        imageWidth      : myPyramid.width,
        imageHeight     : myPyramid.height,
        blankTile       : 'images/blank.gif',
        loadingTile     : 'images/progress.gif'

    Ext.EventManager.addListener( window, 'resize', callback(viewer, viewer.resize) );

createViewer( viewer, 'viewer', 'IMG_7474-7511', '256_', 16610, 8396 );