Responsive Feature-rich Photo Viewer In Pure JavaScript

File Size: 308 KB
Views Total: 23822
Last Update:
Publish Date:
Official Website: Go to website
License: MIT
   
Responsive Feature-rich Photo Viewer In Pure JavaScript

A feature-rich photo viewer plugin in pure JavaScript that displays all your images in a responsive, draggable, navigatable, resizable, maximizable dialog window.

More features:

  • keyboard navigation.
  • Image descriptions.
  • Fixed content.
  • Moveable, rotatable, zoomable images.
  • Font Awesome based icons.
  • Multiple languages.
  • Callback functions.

How to use it:

1. Install and import the PhotoViewer as a module.

# NPM
$ npm install photoviewer --save
import PhotoViewer from 'photoviewer';
@import 'photoviewer/dist/photoviewer.css';

2. Or load the PhotoViewer's JavaScript and CSS files from the dist folder.

<link href="css/photoviewer.min.css" rel="stylesheet" />
<script src="js/photoviewer.min.js"></script>

3. Define the image paths and descriptions in a JS array as follows:

var photos = [
    {
      src: '1.jpg',
      title: 'Image Caption 1' 
    },
    {
      src: '2.jpg',
      title: 'Image Caption 2'
    },
    {
      src: '3.jpg',
      title: 'Image Caption 3'
    }
];

4. Initialize the photo viewer and done.

var options = {
    // options here
};

var viewer = new PhotoViewer(photos, options);

5. You can also create a photo viewer from a static image group.

<a data-gallery="example" href="big-1.jpg">
  <img src="small-1.jpg">
</a>
<a data-gallery="example" href="big-2.jpg">
  <img src="small-2.jpg">
</a>
<a data-gallery="example" href="big-3.jpg">
  <img src="small-3.jpg">
</a>
$('[data-gallery=example]').click(function (e) {

  e.preventDefault();

  var items = [],
    options = {
      index: $(this).index()
    };

  $('[data-gallery=manual]').each(function () {
    let src = $(this).attr('href');
    items.push({
      src: src
    });
  });

  new PhotoViewer(items, options);

});

6. To customize the photo viewer, override the options below and pass them to the photoviewer() function on init.

var options = {

    // Enable modal to drag
    draggable: true,

    // Enable modal to resize
    resizable: true,

    // Enable image to move
    movable: true,

    // Enable keyboard navigation
    keyboard: true,

    // Shows the title
    title: true,

    // Min width of modal
    modalWidth: 320,

    // Min height of modal
    modalHeight: 320,

    // Disable the modal size fixed
    fixedModalSize: false,

    // Disable the image viewer maximized on init
    initMaximized: false,

    // Threshold of modal to browser window
    gapThreshold: 0.02,

    // Threshold of image ratio
    ratioThreshold: 0.1,

    // Min ratio of image when zoom out
    minRatio: 0.05,

    // Max ratio of image when zoom in
    maxRatio: 16,

    // Toolbar options in header
    headerToolbar: ['maximize', 'close'],

    // Toolbar options in footer
    footerToolbar: ['zoomIn', 'zoomOut', 'prev', 'fullscreen', 'next', 'actualSize', 'rotateRight'],

    // Customize button icon
    icons: {
      minimize: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n               <path fill=\"currentColor\" d=\"M20,14H4V10H20\"></path>\n               </svg>",
      maximize: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n               <path fill=\"currentColor\" d=\"M4,4H20V20H4V4M6,8V18H18V8H6Z\"></path>\n               </svg>",
      close: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n            <path fill=\"currentColor\" d=\"M13.46,12L19,17.54V19H17.54L12,13.46\n            L6.46,19H5V17.54L10.54,12L5,6.46V5H6.46L12,10.54L17.54,5H19V6.46\n            L13.46,12Z\"></path>\n            </svg>",
      zoomIn: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n             <path fill=\"currentColor\" d=\"M15.5,14L20.5,19L19,20.5L14,15.5V14.71\n             L13.73,14.43C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,\n             6.5 0 0,1 9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.43,\n             13.73L14.71,14H15.5M9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5C7,5 5,\n             7 5,9.5C5,12 7,14 9.5,14M12,10H10V12H9V10H7V9H9V7H10V9H12V10Z\"></path>\n            </svg>",
      zoomOut: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n              <path fill=\"currentColor\" d=\"M15.5,14H14.71L14.43,13.73C15.41,\n              12.59 16,11.11 16,9.5A6.5,6.5 0 0,0 9.5,3A6.5,6.5 0 0,0 3,9.5A6.5,\n              6.5 0 0,0 9.5,16C11.11,16 12.59,15.41 13.73,14.43L14,14.71V15.5\n              L19,20.5L20.5,19L15.5,14M9.5,14C7,14 5,12 5,9.5C5,7 7,5 9.5,5C12,\n              5 14,7 14,9.5C14,12 12,14 9.5,14M7,9H12V10H7V9Z\"></path>\n              </svg>",
      prev: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n           <path fill=\"currentColor\" d=\"M6,18V6H8V18H6M9.5,12L18,6V18L9.5,12Z\"></path>\n           </svg>",
      next: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n           <path fill=\"currentColor\" d=\"M16,18H18V6H16M6,18L14.5,12L6,6V18Z\"></path>\n           </svg>",
      fullscreen: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n                 <path fill=\"currentColor\" d=\"M8.5,12.5L11,15.5L14.5,11L19,17H5\n                 M23,18V6A2,2 0 0,0 21,4H3A2,2 0 0,0 1,6V18A2,2 0 0,0 3,20H21A2,\n                 2 0 0,0 23,18Z\"></path>\n                 </svg>",
      actualSize: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n                 <path fill=\"currentColor\" d=\"M9.5,13.09L10.91,14.5L6.41,19H10V21\n                 H3V14H5V17.59L9.5,13.09M10.91,9.5L9.5,10.91L5,6.41V10H3V3H10V5\n                 H6.41L10.91,9.5M14.5,13.09L19,17.59V14H21V21H14V19H17.59L13.09,\n                 14.5L14.5,13.09M13.09,9.5L17.59,5H14V3H21V10H19V6.41L14.5,10.91\n                 L13.09,9.5Z\"></path>\n                </svg>",
      rotateLeft: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n                 <path fill=\"currentColor\" d=\"M13,4.07V1L8.45,5.55L13,10V6.09\n                 C15.84,6.57 18,9.03 18,12C18,14.97 15.84,17.43 13,17.91V19.93\n                 C16.95,19.44 20,16.08 20,12C20,7.92 16.95,4.56 13,4.07M7.1,18.32\n                 C8.26,19.22 9.61,19.76 11,19.93V17.9C10.13,17.75 9.29,17.41 8.54,\n                 16.87L7.1,18.32M6.09,13H4.07C4.24,14.39 4.79,15.73 5.69,16.89\n                 L7.1,15.47C6.58,14.72 6.23,13.88 6.09,13M7.11,8.53L5.7,7.11C4.8,\n                 8.27 4.24,9.61 4.07,11H6.09C6.23,10.13 6.58,9.28 7.11,8.53Z\"></path>\n                 </svg>",
      rotateRight: "<svg viewBox=\"0 0 24 24\" class=\"svg-inline-icon\">\n                  <path fill=\"currentColor\" d=\"M16.89,15.5L18.31,16.89C19.21,\n                  15.73 19.76,14.39 19.93,13H17.91C17.77,13.87 17.43,14.72 16.89,\n                  15.5M13,17.9V19.92C14.39,19.75 15.74,19.21 16.9,18.31L15.46,\n                  16.87C14.71,17.41 13.87,17.76 13,17.9M19.93,11C19.76,9.61 19.21,\n                  8.27 18.31,7.11L16.89,8.53C17.43,9.28 17.77,10.13 17.91,11M15.55,\n                  5.55L11,1V4.07C7.06,4.56 4,7.92 4,12C4,16.08 7.05,19.44 11,19.93\n                  V17.91C8.16,17.43 6,14.97 6,12C6,9.03 8.16,6.57 11,6.09V10L15.55,\n                  5.55Z\"></path>\n                  </svg>"
    },

    // Customize language of button title
    i18n: {
      minimize: 'minimize',
      maximize: 'maximize',
      close: 'close',
      zoomIn: 'zoom-in(+)',
      zoomOut: 'zoom-out(-)',
      prev: 'prev(←)',
      next: 'next(→)',
      fullscreen: 'fullscreen',
      actualSize: 'actual-size(Ctrl+Alt+0)',
      rotateLeft: 'rotate-left(Ctrl+,)',
      rotateRight: 'rotate-right(Ctrl+.)'
    },

    // Enable multiple instances
    multiInstances: true,

    // Enable animation
    initAnimation: true,

    // Modal transform animation duration
    animationDuration: 400,

    // Easing function
    animationEasing: 'ease-in-out',

    // Disable modal position fixed when change images
    fixedModalPos: false,

    // Modal z-index
    zIndex: 1090,

    // Selector of drag handler
    dragHandle: false,

    // Start images index
    index: 0,

    // Load the image progressively
    progressiveLoading: true,
    
    // The DOM element to which viewer will be added
    appendTo: 'body',

    // Custom Buttons
    customButtons: {},

    // Whether to set modal css `position: fixed`
    positionFixed: true,
    
    // Init modal position `{top: 0, right: 0, bottom: 0, left: 0}`
    initModalPos: null,

    // Error message when image could not be loaded
    errorMsg: '',
  
});

7. Callback functions available.

var options = {
    callbacks: {
      beforeOpen: $$1.noop,
      opened: $$1.noop,
      beforeClose: $$1.noop,
      closed: $$1.noop,
      beforeChange: $$1.noop,
      changed: $$1.noop
    }
};

Changelog:

v3.10.1 (2024-06-06)

  • remove backdrop styles and improve fullscreen styles

v3.10.0 (2024-03-17)

  • add new option errorMsg to customize the error message
  • add image alt as the default error message
  • improve callbacks beforeChange and changed
  • remove redundant codes and improve some classes

v3.9.2 (2023-12-06)

  • fix photoviewer buttons cannot be focused by tab
  • add :focus-visible style for photoviewer modal
  • remove redundant styles

v3.9.1 (2023-12-04)

  • fix appendTo type

v3.9.0 (2023-11-26)

  • use ES module as main entry
  • update domq.js to 0.7.x

v3.8.0 (2023-09-13)

  • add new option animationEasing
  • allow pass empty image array to PhotoViewer
  • rename instance vars (groupData => images, groupIndex => index)
  • remove unused vars and improve some methods

v3.7.3 (2023-09-07)

  • bugfixes

v3.7.2 (2023-07-26)

  • update domq.js to 0.6.8 to fix memory leaks caused by using .remove()
  • add PhotoViewer.instances to manage multiple modals
  • remove redundant .off() methods

v3.7.0 (2023-04-16)

  • support Dart Sass @use-based API

v3.6.6 (2022-12-24)

  • add shortcuts for maximize Alt+X and fullscreen F

v3.6.4 (2022-08-09)

  • fix modal size issue on the start of modal resizing

v3.6.3 (2022-08-08)

  • change the zoom's argument origin to be optional

v3.6.2 (2021-08-04)

  • Fix modal size which has borders or paddings

v3.6.1 (2021-08-01)

  • Fix window width issue

v3.6.0 (2021-07-30)

  • Add new option positionFixed
  • Add new option initModalPos
  • Add new option animationDuration
  • Remove fixedContent (use positionFixed instead)
  • Support embed mode
  • Improve modal position for appendTo option
  • Fix bugs

v3.5.8 (2021-04-07)

  • correct max-width and min-width of image

v3.5.6 (2021-03-18)

  • remove backdrop-filter of css property

v3.5.5 (2021-03-16)

  • fix keyboard events with multiple instances

v3.5.4 (2020-12-19)

  • fix zoom issue after image rotation caused by domq.js

v3.5.3 (2020-09-21)

  • upgrade domq.js to 0.6.4 and fix image size issue on IE 9+

v3.5.2 (2020-09-19)

  • improve custom button context
  • improve function name

v3.5.0 (2020-09-18)

  • rename headToolbar to headerToolbar
  • rename footToolbar to footerToolbar
  • add custom buttons option
  • improve callback function arguments

v3.4.0 (2019-11-25)

  • Add RTL support

v3.3.0 (2019-07-14)

  • Fix the zIndex option issue another way. 
  • Fix the zIndex issue when click close button.
  • Add appendTo option.

v3.2.0/1 (2019-07-13)

  • Fix the zIndex option issue.
  • Add close keydown(Q) event.
  • Modified loader overlay position.

v3.1.1 (2019-05-27)

  • Fix image vertical middle issue.
  • Add overflow to modal inner.
  • Improve image loading code.

v3.1.0 (2019-05-13)

  • Add types file

v3.0.1 (2019-05-13)

  • Fixed animation arguments issue.

v3.0.0 (2019-05-13)

  • Removed jQuery dependency.

v2.2.0 (2018-12-31)

  • chore(fix): image rotated issue when changed

v2.2.0 (2018-12-09)

  • Add image progressive rendering

v2.1.3 (2018-11-26)

  • bugfix

v2.1.2 (2018-11-23)

  • fixed grab cursor issue & beautify code

v2.1.1 (2018-10-28)

  • chore(fix): improved some style at maximized

v2.1.0 (2018-10-21)

  • Added svg icons & removed font-awesome

2018-08-08

  • modified default ui style

2018-07-29

  • v2.0.0

2018-07-21

  • chore(func): modified method in setImgTitle

This awesome jQuery plugin is developed by nzbin. For more Advanced Usages, please check the demo page or visit the official website.