JavaScript image viewer.

Overview

Viewer.js

Downloads Version Gzip Size Dependencies

JavaScript image viewer.

Table of contents

Features

  • Supports 52 options
  • Supports 23 methods
  • Supports 17 events
  • Supports modal and inline modes
  • Supports touch
  • Supports move
  • Supports zoom
  • Supports rotation
  • Supports scale (flip)
  • Supports keyboard
  • Cross-browser support

Main

dist/
├── viewer.css
├── viewer.min.css   (compressed)
├── viewer.js        (UMD)
├── viewer.min.js    (UMD, compressed)
├── viewer.common.js (CommonJS, default)
└── viewer.esm.js    (ES Module)

Getting started

Installation

npm install viewerjs

In browser:

">
<link  href="/path/to/viewer.css" rel="stylesheet">
<script src="/path/to/viewer.js">script>

The cdnjs provides CDN support for Viewer.js's CSS and JavaScript. You can find the links here.

Usage

Syntax

new Viewer(element[, options])
  • element

    • Type: HTMLElement
    • The target image or container of images for viewing.
  • options (optional)

    • Type: Object
    • The options for viewing. Check out the available options.

Example

  • Picture 1
  • Picture 2
  • Picture 3
">

<div>
  <img id="image" src="picture.jpg" alt="Picture">
div>

<div>
  <ul id="images">
    <li><img src="picture-1.jpg" alt="Picture 1">li>
    <li><img src="picture-2.jpg" alt="Picture 2">li>
    <li><img src="picture-3.jpg" alt="Picture 3">li>
  ul>
div>
// You should import the CSS file.
// import 'viewerjs/dist/viewer.css';
import Viewer from 'viewerjs';

// View an image.
const viewer = new Viewer(document.getElementById('image'), {
  inline: true,
  viewed() {
    viewer.zoomTo(1);
  },
});
// Then, show the image by clicking it, or call `viewer.show()`.

// View a list of images.
// Note: All images within the container will be found by calling `element.querySelectorAll('img')`.
const gallery = new Viewer(document.getElementById('images'));
// Then, show one image by click it, or call `gallery.show()`.

Keyboard support

Only available in modal mode.

  • Esc: Exit full screen or close the viewer or exit modal mode or stop play.
  • Space: Stop play.
  • Tab: Switch the focus state on the buttons in the viewer.
  • Enter: Trigger the click event handler on the button.
  • : View the previous image.
  • : View the next image.
  • : Zoom in the image.
  • : Zoom out the image.
  • Ctrl + 0: Zoom out to initial size.
  • Ctrl + 1: Zoom in to natural size.

back to top

Options

You may set viewer options with new Viewer(image, options). If you want to change the global default options, You may use Viewer.setDefaults(options).

backdrop

  • Type: Boolean or String
  • Default: true

Enable the modal backdrop, specify static for the backdrop that will not close the modal on click.

button

  • Type: Boolean
  • Default: true

Show the button on the top-right of the viewer.

navbar

  • Type: Boolean or Number
  • Default: true
  • Options:
    • 0 or false: hide the navbar
    • 1 or true: show the navbar
    • 2: show the navbar only when the screen width is greater than 768 pixels
    • 3: show the navbar only when the screen width is greater than 992 pixels
    • 4: show the navbar only when the screen width is greater than 1200 pixels

Specify the visibility of the navbar.

title

  • Type: Boolean or Number or Function or Array
  • Default: true
  • Options:
    • 0 or false: hide the title
    • 1 or true or Function or Array: show the title
    • 2: show the title only when the screen width is greater than 768 pixels
    • 3: show the title only when the screen width is greater than 992 pixels
    • 4: show the title only when the screen width is greater than 1200 pixels
    • Function: customize the title content
    • [Number, Function]: the first element indicate the visibility, the second element customize the title content

Specify the visibility and the content of the title.

The name comes from the alt attribute of an image element or the image name parsed from its URL.

For example, title: 4 equals to:

new Viewer(image, {
  title: [4, (image, imageData) => `${image.alt} (${imageData.naturalWidth} × ${imageData.naturalHeight})`]
});

toolbar

  • Type: Boolean or Number or Object
  • Default: true
  • Options:
    • 0 or false: hide the toolbar.
    • 1 or true: show the toolbar.
    • 2: show the toolbar only when the screen width is greater than 768 pixels.
    • 3: show the toolbar only when the screen width is greater than 992 pixels.
    • 4: show the toolbar only when the screen width is greater than 1200 pixels.
    • { key: Boolean | Number }: show or hide the toolbar.
    • { key: String }: customize the size of the button.
    • { key: Function }: customize the click handler of the button.
    • { key: { show: Boolean | Number, size: String, click: Function }: customize each property of the button.
    • Available keys: "zoomIn", "zoomOut", "oneToOne", "reset", "prev", "play", "next", "rotateLeft", "rotateRight", "flipHorizontal" and "flipVertical".
    • Available sizes: "small", "medium" (default) and "large".

Specify the visibility and layout of the toolbar its buttons.

For example, toolbar: 4 equals to:

new Viewer(image, {
  toolbar: {
    zoomIn: 4,
    zoomOut: 4,
    oneToOne: 4,
    reset: 4,
    prev: 4,
    play: {
      show: 4,
      size: 'large',
    },
    next: 4,
    rotateLeft: 4,
    rotateRight: 4,
    flipHorizontal: 4,
    flipVertical: 4,
  },
});

className

  • Type: String
  • Default: ''

Custom class name(s) to add to the viewer's root element.

container

Container to place the viewer in the modal mode.

Only available when the inline option is set to false.

filter

  • Type: Function
  • Default: null

Filter the images for viewing (should return true if the image is viewable, return false to ignore the image).

For example:

new Viewer(image, {
  filter(image) {
    return image.complete;
  },
});

Note that images without the src attribute set will be ignored by default.

fullscreen

Enable to request full screen when play.

Requires the browser supports Fullscreen API.

inheritedAttributes

  • Type: Array
  • Default: ['crossOrigin', 'decoding', 'isMap', 'loading', 'referrerPolicy', 'sizes', 'srcset', 'useMap']

Define the extra attributes to inherit from the original image.

Note that the basic attributes src and alt will always inherit from the original image.

initialViewIndex

  • Type: Number
  • Default: 0

Define the initial index of the image for viewing.

Also used as the default parameter value of the view method.

inline

  • Type: Boolean
  • Default: false

Enable inline mode.

interval

  • Type: Number
  • Default: 5000

The amount of time to delay between automatically cycling an image when playing.

keyboard

  • Type: Boolean
  • Default: true

Enable keyboard support.

focus

  • Type: Boolean
  • Default: true

Focus the active item in the navbar when initialized.

Requires the keyboard option set to true.

loading

  • Type: Boolean
  • Default: true

Indicate if showing a loading spinner when loading the image or not.

loop

  • Type: Boolean
  • Default: true

Indicate if enabling loop viewing or not.

If the current image is the last one, then the next one to view is the first one, and vice versa.

minWidth

  • Type: Number
  • Default: 200

Define the minimum width of the viewer.

Only available in inline mode (set the inline option to true).

minHeight

  • Type: Number
  • Default: 100

Define the minimum height of the viewer.

Only available in inline mode (set the inline option to true).

movable

  • Type: Boolean
  • Default: true

Enable to move the image.

rotatable

  • Type: Boolean
  • Default: true

Enable to rotate the image.

scalable

  • Type: Boolean
  • Default: true

Enable to scale the image.

zoomable

  • Type: Boolean
  • Default: true

Enable to zoom the image.

zoomOnTouch

  • Type: Boolean
  • Default: true

Enable to zoom the current image by dragging on the touch screen.

zoomOnWheel

  • Type: Boolean
  • Default: true

Enable to zoom the image by wheeling the mouse.

slideOnTouch

  • Type: Boolean
  • Default: true

Enable to slide to the next or previous image by swiping on the touch screen.

toggleOnDblclick

  • Type: Boolean
  • Default: true

Indicate if toggle the image size between its natural size and initial size when double click on the image or not.

In other words, call the toggle method automatically when double click on the image.

Requires dblclick event support.

tooltip

  • Type: Boolean
  • Default: true

Show the tooltip with image ratio (percentage) when zooming in or zooming out.

transition

  • Type: Boolean
  • Default: true

Enable CSS3 Transition for some special elements.

zIndex

  • Type: Number
  • Default: 2015

Define the CSS z-index value of the viewer in modal mode.

zIndexInline

  • Type: Number
  • Default: 0

Define the CSS z-index value of the viewer in inline mode.

zoomRatio

  • Type: Number
  • Default: 0.1

Define the ratio when zooming the image by wheeling the mouse.

minZoomRatio

  • Type: Number
  • Default: 0.01

Define the min ratio of the image when zooming out.

maxZoomRatio

  • Type: Number
  • Default: 100

Define the max ratio of the image when zooming in.

url

  • Type: String or Function
  • Default: 'src'

Define where to get the original image URL for viewing.

If it is a string, it should be one of the attributes of each image element. If it is a function, it should return a valid image URL.

For example:

">
<img src="picture.jpg?size=160">
new Viewer(image, {
  url(image) {
    return image.src.replace('?size=160', '');
  },
});

ready

  • Type: Function
  • Default: null

Shortcut of the ready event.

show

  • Type: Function
  • Default: null

Shortcut of the show event.

shown

  • Type: Function
  • Default: null

Shortcut of the shown event.

hide

  • Type: Function
  • Default: null

Shortcut of the hide event.

hidden

  • Type: Function
  • Default: null

Shortcut of the hidden event.

view

  • Type: Function
  • Default: null

Shortcut of the view event.

viewed

  • Type: Function
  • Default: null

Shortcut of the viewed event.

move

  • Type: Function
  • Default: null

Shortcut of the move event.

moved

  • Type: Function
  • Default: null

Shortcut of the moved event.

rotate

  • Type: Function
  • Default: null

Shortcut of the rotate event.

rotated

  • Type: Function
  • Default: null

Shortcut of the rotated event.

scale

  • Type: Function
  • Default: null

Shortcut of the scale event.

scaled

  • Type: Function
  • Default: null

Shortcut of the scaled event.

zoom

  • Type: Function
  • Default: null

Shortcut of the zoom event.

zoomed

  • Type: Function
  • Default: null

Shortcut of the zoomed event.

play

  • Type: Function
  • Default: null

Shortcut of the play event.

stop

  • Type: Function
  • Default: null

Shortcut of the stop event.

back to top

Methods

All methods allow chain composition.

As there are some asynchronous processes when start the viewer, you should call a method only when it is available, see the following lifecycle:

new Viewer(image, {
  ready() {
    // 2 methods are available here: "show" and "destroy".
  },
  shown() {
    // 9 methods are available here: "hide", "view", "prev", "next", "play", "stop", "full", "exit" and "destroy".
  },
  viewed() {
    // All methods are available here except "show".
    this.viewer.zoomTo(1).rotateTo(180);
  }
});

show([immediate])

  • immediate (optional):
    • Type: Boolean
    • Default: false
    • Indicates if show the viewer immediately or not.

Show the viewer.

Only available in modal mode.

hide([immediate])

  • immediate (optional):
    • Type: Boolean
    • Default: false
    • Indicates if hide the viewer immediately or not.

Hide the viewer.

Only available in modal mode.

view([index])

  • index (optional):
    • Type: Number
    • Default: 0 (inherits from the initialViewIndex option)
    • The index of the image for viewing

View one of the images with the image index. If the viewer is hidden, it will be shown first.

viewer.view(1); // View the second image

prev([loop=false])

  • loop (optional):
    • Type: Boolean
    • Default: false
    • Indicate if turn to view the last one when it is the first one at present.

View the previous image.

next([loop=false])

  • loop (optional):
    • Type: Boolean
    • Default: false
    • Indicate if turn to view the first one when it is the last one at present.

View the next image.

move(x[, y = x])

  • x:

    • Type: Number
    • The moving distance in the horizontal direction.
  • y (optional):

    • Type: Number
    • The moving distance in the vertical direction.
    • If not present, its default value is x

Move the image with relative offsets.

viewer.move(1);
viewer.move(-1, 0); // Move left
viewer.move(1, 0);  // Move right
viewer.move(0, -1); // Move up
viewer.move(0, 1);  // Move down

moveTo(x[, y = x])

  • x:

    • Type: Number
    • The new position in the horizontal direction.
  • y (optional):

    • Type: Number
    • The new position in the vertical direction.
    • If not present, its default value is x.

Move the image to an absolute point.

rotate(degree)

  • degree:
    • Type: Number
    • Rotate right: requires a positive number (degree > 0)
    • Rotate left: requires a negative number (degree < 0)

Rotate the image with a relative degree.

viewer.rotate(90);
viewer.rotate(-90);

rotateTo(degree)

  • degree:
    • Type: Number

Rotate the image to an absolute degree.

viewer.rotateTo(0); // Reset to zero degree
viewer.rotateTo(360); // Rotate a full round

scale(scaleX[, scaleY])

  • scaleX:

    • Type: Number
    • Default: 1
    • The scaling factor to apply on the abscissa of the image
    • When equal to 1 it does nothing.
  • scaleY (optional):

    • Type: Number
    • The scaling factor to apply on the ordinate of the image
    • If not present, its default value is scaleX.

Scale the image.

viewer.scale(-1); // Flip both horizontal and vertical
viewer.scale(-1, 1); // Flip horizontal
viewer.scale(1, -1); // Flip vertical

scaleX(scaleX)

  • scaleX:
    • Type: Number
    • Default: 1
    • The scaling factor to apply on the abscissa of the image
    • When equal to 1 it does nothing

Scale the abscissa of the image.

viewer.scaleX(-1); // Flip horizontal

scaleY(scaleY)

  • scaleY:
    • Type: Number
    • Default: 1
    • The scaling factor to apply on the ordinate of the image
    • When equal to 1 it does nothing

Scale the ordinate of the image.

viewer.scaleY(-1); // Flip vertical

zoom(ratio[, hasTooltip])

  • ratio:

    • Type: Number
    • Zoom in: requires a positive number (ratio > 0)
    • Zoom out: requires a negative number (ratio < 0)
  • hasTooltip (optional):

    • Type: Boolean
    • Default: false
    • Show tooltip

Zoom the image with a relative ratio

viewer.zoom(0.1);
viewer.zoom(-0.1);

zoomTo(ratio[, hasTooltip])

  • ratio:

    • Type: Number
    • Requires a positive number (ratio > 0)
  • hasTooltip (optional):

    • Type: Boolean
    • Default: false
    • Show tooltip

Zoom the image to an absolute ratio.

viewer.zoomTo(0); // Zoom to zero size (0%)
viewer.zoomTo(1); // Zoom to natural size (100%)

play([fullscreen])

  • fullscreen (optional):
    • Type: Boolean or FullscreenOptions
    • Default: false
    • Indicate if request fullscreen or not.

Play the images.

stop()

Stop play.

full()

Enter the modal mode.

Only available in inline mode.

exit()

Exit the modal mode.

Only available in inline mode.

tooltip()

Show the current ratio of the image by percentage.

Requires the tooltip option set to true.

toggle()

Toggle the image size between its current size and natural size.

Used by the toggleOnDblclick option.

reset()

Reset the image to its initial state.

update()

Update the viewer instance when the source images changed (added, removed, or sorted).

If you load images dynamically (with XMLHTTPRequest), you can use this method to add the new images to the viewer instance.

destroy()

Destroy the viewer and remove the instance.

back to top

Events

All events can access the viewer instance with this.viewer in its handler.

Be careful to use these events with other components which have the same event names, e.g.: Bootstrap's modal.

let viewer;

image.addEventListener('viewed', function () {
  console.log(this.viewer === viewer);
  // > true
});

viewer = new Viewer(image);

ready

  • event.bubbles: true
  • event.cancelable: true
  • event.detail: null

This event fires when a viewer instance is ready for viewing.

In modal mode, this event will not be triggered until you click on one of the images.

show

  • event.bubbles: true
  • event.cancelable: true
  • event.detail: null

This event fires when the viewer modal starts to show.

Only available in modal mode.

shown

  • event.bubbles: true
  • event.cancelable: true
  • event.detail: null

This event fires when the viewer modal has shown.

Only available in modal mode.

hide

  • event.bubbles: true
  • event.cancelable: true
  • event.detail: null

This event fires when the viewer modal starts to hide.

Only available in modal mode.

hidden

  • event.bubbles: true
  • event.cancelable: false
  • event.detail: null

This event fires when the viewer modal has hidden.

Only available in modal mode.

view

  • event.bubbles: true
  • event.cancelable: true
  • event.detail.index:
    • Type: Number
    • The index of the original image.
  • event.detail.image:
    • Type: HTMLImageElement
    • The current image (a clone of the original image).
  • event.detail.originalImage:
    • Type: HTMLImageElement
    • The original image.

This event fires when a viewer starts to show (view) an image.

viewed

  • event.bubbles: true
  • event.cancelable: false
  • event.detail: the same as the view event.

This event fires when a viewer has shown (viewed) an image.

move

  • event.bubbles: true
  • event.cancelable: true
  • event.detail.x:
    • Type: Number
    • The new position in the horizontal direction.
  • event.detail.y:
    • Type: Number
    • The new position in the vertical direction.
  • event.detail.oldX:
    • Type: Number
    • The old position in the horizontal direction.
  • event.detail.oldY:
    • Type: Number
    • The old position in the vertical direction.
  • event.detail.originalEvent:
    • Type: Event or null
    • Options: pointermove, touchmove, and mousemove.

This event fires when a viewer starts to move an image.

moved

  • event.bubbles: true
  • event.cancelable: false
  • event.detail: the same as the move event.

This event fires when a viewer has moved an image.

rotate

  • event.bubbles: true
  • event.cancelable: true
  • event.detail.degree:
    • Type: Number
    • The new rotation degrees.
  • event.detail.oldDegree:
    • Type: Number
    • The old rotation degrees.

This event fires when a viewer starts to rotate an image.

rotated

  • event.bubbles: true
  • event.cancelable: false
  • event.detail: the same as the rotate event.

This event fires when a viewer has rotated an image.

scale

  • event.bubbles: true
  • event.cancelable: true
  • event.detail.scaleX:
    • Type: Number
    • The new scaling factor in the horizontal direction.
  • event.detail.scaleY:
    • Type: Number
    • The new scaling factor in the vertical direction.
  • event.detail.oldScaleX:
    • Type: Number
    • The old scaling factor in the horizontal direction.
  • event.detail.oldScaleY:
    • Type: Number
    • The old scaling factor in the vertical direction.

This event fires when a viewer starts to scale an image.

scaled

  • event.bubbles: true
  • event.cancelable: false
  • event.detail: the same as the scale event.

This event fires when a viewer has scaled an image.

zoom

  • event.bubbles: true
  • event.cancelable: true
  • event.detail.ratio:
    • Type: Number
    • The new (next) ratio of the image (imageData.width / imageData.naturalWidth).
  • event.detail.oldRatio:
    • Type: Number
    • The old (current) ratio of the image.
  • event.detail.originalEvent:
    • Type: Event or null
    • Options: wheel, pointermove, touchmove, and mousemove.

This event fires when a viewer starts to zoom (in or out) an image.

zoomed

  • event.bubbles: true
  • event.cancelable: false
  • event.detail: the same as the zoom event.

This event fires when a viewer has zoomed (in or out) an image.

play

  • event.bubbles: true
  • event.cancelable: true
  • event.detail: null

This event fires when the viewer starts to play.

You can abort the playing process by calling event.preventDefault().

stop

  • event.bubbles: true
  • event.cancelable: true
  • event.detail: null

This event fires when the viewer starts to stop.

You can abort the stopping process by calling event.preventDefault().

back to top

No conflict

If you have to use another viewer with the same namespace, call the Viewer.noConflict static method to revert to it.

">
<script src="other-viewer.js">script>
<script src="viewer.js">script>
<script>
  Viewer.noConflict();
  // Code that uses other `Viewer` can follow here.
script>

Browser support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Opera (latest)
  • Edge (latest)
  • Internet Explorer 9+

Contributing

Please read through our contributing guidelines.

Versioning

Maintained under the Semantic Versioning guidelines.

License

MIT © Chen Fengyuan

back to top

Comments
  • Sliding not works on devices with iOS

    Sliding not works on devices with iOS

    I found a bug, which I reproduced on several mobile Apple's devices (iPhone 6, iPhone 7 Plus, both iOS 11.2) in Safari.

    How to reproduce: It easy to reproduce using this demo: https://fengyuanchen.github.io/viewerjs/

    Just open an image and then swipe to the left or to the right. First swipe is ok, but at the second it starts to zoom image instead of switching to the next image.

    If I disable zoom, nothing happens, sliding just not works.

    It was reproduced using the latest release: https://github.com/fengyuanchen/viewerjs/releases/tag/v1.0.0-beta.1

    Here a video how it looks: https://youtu.be/SVo3y-tJCVk Let's me know if you need more details.

    bug 
    opened by Stafox 15
  • 动态加载图片

    动态加载图片

    你好,请教一下,现在的需求是点击缩略图时请求原图数据,成功后显示原图,但是请求数据成功后,使用update无效,第二次点击的时候才显示原图。 其中代码如下: if (data.success == true) { $("#img" + AnnotationId).attr('data-original', "data:image/png;base64," + data.data.DocumentBody); $("#ImgList" + workid).viewer('update'); }

    opened by mysea 12
  • Image not shown until mouse over toolbar.

    Image not shown until mouse over toolbar.

    In my local dev environment, it works fine. But it got a problem when deployed online - when the thumb's clicked, there's no image shown, just the shade and the toolbar buttons below. When you put your mouse onto the toolbar buttons, the image shows finally. I checked the HTML element and found that the viewer-canvas was empty initially, until mouse over the toolbar and the img was inserted. This is a very strange circumstance. Please help.

    help wanted 
    opened by jasonlam-swatow 9
  • 在预览开启的情况下,ajax返回的图片无法添加到预览图中,通过update()也没有效果

    在预览开启的情况下,ajax返回的图片无法添加到预览图中,通过update()也没有效果

    Version:1.3.6 Desc:在预览开启的情况下,ajax返回的图片无法添加到预览图中,通过update()也没有效果

    初始化方式: const viewer = new Viewer(DOM, { toolbar: true, url: 'data-original', show() { viewer.update() } }) 在ajax请求图片的回调中,同时也主动调用了viewer.update(),预览图还是无法更新,需要重新关闭打开才能看到新增的图片。

    请问如何解决这个问题呢?

    opened by zhixiaotong 7
  • Pinch zoom not working in some phone browsers

    Pinch zoom not working in some phone browsers

    When I try to pinch zoom in some phone browsers nothing happens. Moving the picture is also not working unless you tap the picture multiple times, which causes the picture to move just a little.

    I've tested this in both my own project and in your demo page: https://fengyuanchen.github.io/viewerjs. It seems to be working fine if I use the Chrome browser on my phone.

    Tested operating systems: Android 6.0.1(Samsung s7) and iOS 8.3(iPhone 6) Tested browsers: Internet, version 4.0.20 and Safari

    opened by kristianjohansson 7
  • AJAX添加的图片,update出错。

    AJAX添加的图片,update出错。

    初始化时

    <ul id="images">
    </ul>
    
    var viewer = new Viewer(document.getElementById('images'), options);
    

    然后通过AJAX请求图片,之后update

    viewer.update();
    

    JS报错, update方法里面的 _this.images 为 undefined.

    PS:我为什么不在Ajax请求后new Viewer()?因为这个是对话页面,Ajax轮循获取消息,不保证每次请求都有返回,不保证每次返回都是图片消息。所以只能先初始化。

    opened by icyflash 7
  • refactor: Update index.d.ts

    refactor: Update index.d.ts

    Summary

    What kind of change does this PR introduce? (check at least one)

    • [ ] Bugfix
    • [ ] Feature
    • [x] Code style update
    • [ ] Refactor
    • [ ] Docs
    • [ ] Build-related changes
    • [ ] Other, please describe:

    If changing the UI of default theme, please provide the before/after screenshot:

    Does this PR introduce a breaking change? (check one)

    • [ ] Yes
    • [x] No

    If yes, please describe the impact and migration path for existing applications:

    The PR fulfills these requirements:

    • [ ] When resolving a specific issue, it's referenced in the PR's title #440

    You have tested in the following browsers: (Providing a detailed version will be better.)

    • [x] Chrome
    • [ ] Firefox
    • [ ] Safari
    • [ ] Edge
    • [ ] IE

    If adding a new feature, the PR's description includes:

    • [ ] A convincing reason for adding this feature
    • [ ] Related documents have been updated
    • [ ] Related tests have been updated

    To avoid wasting your time, it's best to open a feature request issue first and wait for approval before working on it.

    Other information:

    opened by seahindeniz 6
  • [Help]可以动态添加多张图片吗?

    [Help]可以动态添加多张图片吗?

    官方给了动态添加单张图片的示例,想知道如何动态添加多张图片list

    var image = new Image();
    image.src = 'pic.jpg';
    
    var viewer = new Viewer(image, {
        hidden: function () {
            viewer.destroy();
        }
    });
    
    viewer.show();
    
    opened by Exrick 6
  • Code review of assignment to innerHTML

    Code review of assignment to innerHTML

    Describe the bug The Firefox Add-ons has a security check for every extension package, and reports warnings for code like .innerHTML = render(...), with an only exception of .innerHTML = "a-string-literal".

    So, because my webextension Vimium C includes this project, I always got such warnings when I published new versions.

    Expected behavior

    There're 2 solutions to avoid such security warnings:

    1. replace all assignment code to innerHTML with document.createElement(...) and DOM manipulations.
    2. or, use DOMParser: var div = new DOMParser().parseFromString(html, "text/html").body.firstElementChild.

    Considering that DOMParser does not exist on IE 9, and parseFromString does not exist before Firefox 12, or Chrome 31, I recommend the first method, although it will increase the JavaScript file size for about tens to hundreds of bytes.

    Warned Places

    There're 2 sources of Firefox Add-ons' warnings: https://github.com/fengyuanchen/viewerjs/blob/d1964646d1f1ef0aa653734b2946f21b27c2e9c3/src/js/render.js#L88-L95 and https://github.com/fengyuanchen/viewerjs/blob/d1964646d1f1ef0aa653734b2946f21b27c2e9c3/src/js/methods.js#L265-L268

    I also suggest that, in the second source code .innerHTML = escapeHTMLEntities(...) should be replaced with .textContent = ....

    opened by gdh1995 6
  • 为什么点击两次后才起作用了

    为什么点击两次后才起作用了

    /** * 图片预览 */ $(document).on('click', '.img-style', function () { var current = this; var formId = $(current).attr("data-form-id"); var galley = document.getElementById('form-' + formId); var viewer = new Viewer(galley, { url: 'data-original', toolbar: { oneToOne: true, rotateLeft: 4, rotateRight: 4, prev: function () { viewer.prev(true); }, play: true, next: function () { viewer.next(true); } }, }); });

    opened by xiaojun515688 6
  • [Feature request] Allow disabling the explicit size for the viewer in the .view-container element

    [Feature request] Allow disabling the explicit size for the viewer in the .view-container element

    Related to #138, I request for an option which allows the viewer to not set the width and height explicitly and, instead, allow them to be set in either the user style sheet or even by the browser itself.

    opened by brunoais 6
  • 以最后一次缩放的触摸位置为缩放原点缩放图像

    以最后一次缩放的触摸位置为缩放原点缩放图像

    Is your feature request related to a problem? Please describe. 与#553 相反 用户通过滚轮和触摸事件缩放图像时,缩放原点取决于 mousestart 或 touchstart 事件位置,而使用zoomTo或zoom放大时缩放原点取在图像中心,这样会使得图片在放大过程中发生位移,不能保持在原位置放大 Describe the solution you'd like 为zoomTo添加设置缩放原点的方法或者在添加以最后一次mousestart 或 touchstart 事件位置为缩放原点的配置项

    enhancement 
    opened by rhyryy 0
  • iOS 15 zoom bug

    iOS 15 zoom bug

    In Safari on iOS 15, where the search bar is located at the bottom, there is a problem that when the image is enlarged, this search bar also interacts

    https://drive.google.com/file/d/1ksleS1uZP5LjuKGOktf8EvVwa4qV24S2/view?usp=sharing

    opened by alienwave1 3
  • Enable to force to zoom image at image center

    Enable to force to zoom image at image center

    Is your feature request related to a problem? Please describe. Currently, the library enable users to zoom an image by wheel and touch event, and the zoom origin is depending on the mousestart or touchstart event position. what i need is to force the zoom origin at the image center, ignore the mousestart or touchstart event position.

    Describe the solution you'd like Add a additional config option to force to zoom image at image center, like "zoomAtCenter", and it's default value is "false".

    opened by YaoKaiLun 1
  • 图片行内属性宽高均为 0

    图片行内属性宽高均为 0

    Describe the bug

    偶现异常,图片不显示,请求是成功了的,去掉这2 个行内属性能看到图片,就是尺寸位置可能不太对劲。 image

    To Reproduce

    不能稳定复现

    Expected behavior

    如果宽高计算有问题,能让浏览器默认计算吗,就给个默认宽度或者高度,然后浏览器默认等比计算就行

    Screenshots 见上图

    Desktop (please complete the following information):

    • OS: macos
    • Browser chrome dev
    • Version 105.0.5137.4

    Additional context

    opened by jeff-wangzhen 4
  • 显示1000张图片合集时的性能优化建议和BUG

    显示1000张图片合集时的性能优化建议和BUG

    很好的项目,感谢你的工作

    Describe the bug 当我想要用viewerjs去显示图片合集时(无法预估数量,所以要尝试最大值1000张)。发现性能很差。

    然后就分析了一下,发现,性能差完全是viewerjs设计问题+BUG,而不是我的需求--显示1000张图片不对。

    To Reproduce Steps to reproduce the behavior: 1.创建1000张图片的合集

     <ul id="images" style={{ display: 'none' }}>
    
                      {showlist.map((item) => (
                        <li key={item.fileindex}>
    
                          <img src={item.src} data-src={item.datasource} referrerPolicy="no-referrer" />
    
                        </li>
                      ))}
    
    </ul>
    

    2.初始化viewjs

    this.viewver = new Viewer(document.getElementById('images')!, {...})
    

    3.点击幻灯片播放

    Expected behavior 预期正常展现。实际很差,很卡

    Additional context

    我发现的问题比较多,我没有按照重要程度去排序,所以请耐心看一下。都是为了让Viewer更完美


    问题1: viewerjs强制要求必须用img列表去实例化new Viewer(),带来了不必要的消耗

    在我的用例中,ul>li>img (1000张),它实际上并没有实际意义。因为Viewer在实例化时,是Viewer自己重新创建了1000个新的img并复制原始数据

    //https://github.com/fengyuanchen/viewerjs/blob/main/src/js/render.js  line 82
    forEach(this.images, (image, index) => {
          const { src } = image;
          const alt = image.alt || getImageNameFromURL(src);
          const url = this.getImageURL(image);
    
          if (src || url) {
            const item = document.createElement('li');
            const img = document.createElement('img');
    
            forEach(options.inheritedAttributes, (name) => {
              const value = image.getAttribute(name);
    
              if (value !== null) {
                img.setAttribute(name, value);
              }
            });
    
            img.src = src || url;
            img.alt = alt;
    

    如上,那么最开始创建的ul>li>img (1000张),实际上完全可以创建为 ul>li>span (1000个) 来代替。因为Viewer只是需要读取复制数据,在span上设置这些数据给Viewer读取也是一样的<span src={item.src} data-src={item.datasource} referrerPolicy="no-referrer" />。这样我最开始不需要创建和加载1000个img (导致网络卡)

    这个问题,我自己使用替代图片的方式优化了一下(使用一张很小的固定图片替换了img 的 src)(在Viewer的view: (e: any)事件中还有处理替换回来)

    
     <ul id="images" style={{ display: 'none' }}>
                      {showlist.map((item) => (
                        <li key={item.fileindex}>
    
                           //图片占位符替换
                          <img src="data:image/png;base64,iVBORw0..." data-imgsrc={item.src}  data-src={item.datasource} referrerPolicy="no-referrer" />
    
                        </li>
                      ))}
    </ul>
    

    问题2: Viewer一次性创建了1000个新的img,导致第一次展现时,需要加载1000张图片,网络导致很卡

    还是如上//https://github.com/fengyuanchen/viewerjs/blob/main/src/js/render.js line 82 Viewer一次性创建了1000个新的img,这些img是被用来放在viewer-navbar做导航用的

    //Viewer最终渲染的html
    
    <div class="viewer-container">
    <div class="viewer-navbar">
    <ul class="viewer-list viewer-transition" role="navigation" style="width: 30906px; transform: translateX(307.5px);">
    
    <li data-index="0" data-viewer-action="view" role="button" tabindex="0" class="">
    //1000张小图片
    <img  src="...” />
    </li>
    ......
    </ul>
    </div>
    </div>
    
    

    创建1000个?感觉不合理,因为导航条放不下1000个,应该先创建一部分,当切换下一张图片,导航接近时,再补充、替换一部分。这样循环

    或者,创建1000个img,但是不要复制真实的src,而是在导航接近时,更新需要显示的那些img的src,让导航图片正常显示

    针对这个问题,我是在Viewer的view: (e: any)事件中还有处理替换回来。这样,仅保持几十个img有真实的src,其他的只是占位。可以避免加载1000张图片带来的网络卡顿

    
    viewver = new Viewer(document.getElementById('images')!, {           
                url: 'data-src',
                view: (e: any) => {
                  const nextindex = e.detail.index /** 马上要显示的图片的id */
                  let imagelist = rawimagelist.value
                  let rawimg = imagelist[nextindex]
                 
                  let ul = document.getElementsByClassName('viewer-list viewer-transition')
                  if (ul && ul.length > 0) {
                    let lilist = ul[0].childNodes
                    /** 找到当前显示的图片,更新前后30个li>img 的src */
                    for (let i = Math.max(0, nextindex - 30), maxi = Math.min(nextindex + 30, imagelist.length); i < maxi; i++) {
                      let imgnode = lilist[i].firstChild
                      if (imgnode) {
                        let img = imgnode as Element
                        let src = img.getAttribute('src')
                        let smallurl = imagelist[i].smallurl
                        if (src != smallurl) img.setAttribute('src', smallurl)
                        src = img.getAttribute('data-original-url')
                        let bigurl = imagelist[i].bigurl
                        if (src != bigurl) img.setAttribute('data-original-url', bigurl)
                      }
                    }
                  }
                }
              })
            }
    

    问题3: 点击幻灯片播放时会卡住

    原因是,点击播放时,Viewer会创建1000个大图的img

    这里有个BUG了,因为这1000张大图是放在viewer-player里播放的,但我竟然在body下还有1000个,这应该是BUG了

    <body>
        <div class="viewer-container">
            <div class="viewer-player viewer-show" >
                <img .../>
                ....1000...//应该是放在这里,循环播放的
            </div>
    </div>
    <img .../>
    ....1000...//但是在body下竟然还有1000张?
    </body>
    

    针对这个问题,还是那个思路,当播放时,播放到第几张图片,就同时替换更新邻近的几张图片的src。而不是一点击播放按钮就创建1000张图片并发起1000个网络请求


    总结,Viewer没有对大量图片的情景进行优化。问题3可能是BUG,我没时间翻Viewer的代码仔细看了

    请不要回复一句:这可能需要修改Viewer的架构了。。。。

    其实并不是这样的,最简易的就是使用占位图片。先占位。然后等临近显示时更新替换为正确的图片。这样即使创建1000个img,也不会真的立即联网加载1000张图片,导致网络太卡。

    当然最合理的方式,还是修改一下显示逻辑,仅创建几十个必要的img,然后等临近显示时更新这几十个img的图片地址。这样不需要创建1000个img(现在实际上是创建了3000个img,并且立即一次性加载1000张图片).

    enhancement 
    opened by xiaosongmao123 1
Releases(v1.10.5)
  • v1.10.5(Apr 5, 2022)

  • v1.10.4(Feb 13, 2022)

  • v1.10.3(Feb 2, 2022)

    • Get the pageX/Y properties from the original event when it is an emulated double click in touch devices (#527).
    • Improve the zoom experience on the touch screen (#510).
    Source code(tar.gz)
    Source code(zip)
  • v1.10.2(Oct 22, 2021)

    • Increase title height for avoiding truncation (#509).
    • Fix a TypeError when there are not any images (#504).
    • Remove loading class on image load error (#502).
    Source code(tar.gz)
    Source code(zip)
  • v1.10.1(Aug 1, 2021)

  • v1.10.0(Jun 12, 2021)

    • Enhance fullscreen option and play method to support FullscreenOptions (#482, #483).
    • Refactor the toggle method for toggling image between current/natural ratio (#477).
    • Improve the toggle method for zooming by double-click (#422).
    Source code(tar.gz)
    Source code(zip)
  • v1.9.2(May 29, 2021)

  • v1.9.1(May 22, 2021)

  • v1.9.0(Dec 6, 2020)

    • Add 6 new events: move, moved, rotate, rotated, scale, and scaled.
    • Add an example for limiting the moving range with the help of the move event.
    Source code(tar.gz)
    Source code(zip)
  • v1.8.0(Nov 8, 2020)

    • Add a new option: focus .
    • Add ARIA attributes for better accessibility.
    • Add the Tab and Enter keys to the keyboard support.
    • Check if the pointer object is defined or not for better compatibility (#421).
    Source code(tar.gz)
    Source code(zip)
  • v1.7.1(Sep 29, 2020)

  • v1.7.0(Sep 26, 2020)

    • Add 2 new events: play and stop (#411).
    • Let the viewed, zoomed and hidden events can not be canceled.
    • Improve the TypeScript declarations in the types/index.d.ts file.
    Source code(tar.gz)
    Source code(zip)
  • v1.6.2(Aug 30, 2020)

  • v1.6.1(Jun 14, 2020)

  • v1.6.0(Jun 6, 2020)

    • Add a new options: inheritedAttributes.
    • Ignore images without the src attribute (#326).
    • Improve the hide method for unexpected calling (#367).
    • Reset the padding right of the body element when resizing (#379).
    • Remove unnecessary padding-right: 0px from the body element when close the viewer modal (#394).
    Source code(tar.gz)
    Source code(zip)
  • v1.5.0(Nov 23, 2019)

    • Force reflow element in a new way to avoid side effect (#343).
    • Add a new option: slideOnTouch (#340).
    • Detect if the queried image is existing when update image list (#333).
    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Oct 26, 2019)

  • v1.3.7(Oct 2, 2019)

    • Do nothing if the index value is invalid when call the view method (#312).
    • Ignore invalid element parameter on the class utility functions (#317).
    • Improve event type determining for iOS 13+ (#321).
    Source code(tar.gz)
    Source code(zip)
  • v1.3.6(Jul 4, 2019)

  • v1.3.5(Jun 29, 2019)

  • v1.3.4(Jun 1, 2019)

    • Escape all strings that use in HTML for better security (#269).
    • Fix the missing fade out transition when hiding the viewer (#275).
    • Decode image name when it comes from URL (#282).
    Source code(tar.gz)
    Source code(zip)
  • v1.3.3(Apr 6, 2019)

    • Fix unexpected modal exiting behavior when the mouse is pressed (#255).
    • Abort image downloading when cancel viewing for better performance.
    Source code(tar.gz)
    Source code(zip)
  • v1.3.2(Jan 24, 2019)

  • v1.3.1(Dec 9, 2018)

    • Emulate click (single tap) and double click (double tap) in touch devices to support backdrop and image zooming (#210).
    • Ignore pointer events when not the primary button was pressed (#221).
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Oct 25, 2018)

  • v1.2.1(Oct 20, 2018)

  • v1.2.0(Jul 15, 2018)

    • Add 2 new options: toggleOnDblclick (#173) and initialViewIndex (#183).
    • Enhance the title option to support to customize title content (#54, #185).
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(May 27, 2018)

  • v1.0.1(May 20, 2018)

    • Add namespace to data attribute names (from data-* to data-viewer-*) to avoid side effect.
    • Make sure the image data is a non-null object to avoid unexpected errors.
    • Fix broken zoom feature in iOS browsers (#167).
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Apr 1, 2018)

Image viewer component for vue 3.x, supports rotation, scale, zoom and so on, based on viewer.js

v-viewer Image viewer component for vue, supports rotation, scale, zoom and so on, based on viewer.js v-viewer for vue2 Live demo Quick Example direct

mirari 13 Sep 22, 2022
JavaScript image viewer.

Viewer.js JavaScript image viewer. Website jquery-viewer - A jQuery plugin wrapper for Viewer.js. Table of contents Features Main Getting started Keyb

Fengyuan Chen 6.8k Oct 5, 2022
An Mobile-First image viewer for Vue2 / 一个移动端优先的 Vue2 图片预览插件

img-vuer An Mobile-First image viewer for Vue2 中文 README ??‍♀️ Easy to use ?? Swipe gesture ?? Zoom gesture V0.11.0 Now you can use thumbnail~ V0.13.0

DJJo 260 Sep 20, 2022
A JavaScript Image Browser written in VueJS and styled with TailwindCSS

An Image Browser Component Built with VueJs A JavaScript Image Browser written in VueJS and styled with TailwindCSS. Features Image Upload Local or Re

Akash Mitra 11 Mar 31, 2022
A Vue component for showing loader during image loading https://john015.github.io/vue-load-image/

English | 한국어 Vue-load-image Vue-load-image is 1KB(gzipped size) minimalist Vue component that display loader during image loading and display alterna

Sangwon Lee 59 May 24, 2022
🌈 A Vue image component. Simple realization of image shadow.

?? vue-image-shadow A Vue image component. Simple realization of image shadow. ?? Example Online: https://image-component.github.io/vue-image-shadow/

null 21 Aug 13, 2022
vue-image-markup will provide you to edit uploaded image easily and save it.

Markup Image with Vue.js (customizable) vue-image-markup will provide you to edit uploaded image easily and save it. Installation npm i vue-image-mark

Lionix 91 Sep 26, 2022
Vue-image-loader: image loader for vue js with prevue

Vue-image-loader: image loader for vue js with prevue

null 0 Feb 1, 2020
A Directive for setting fall back image in a vue js application if in case image is not loaded

vue-fall-back-image-directive A Directive for setting fall back image in a vue js application. Installation npm install Run npm install --save vue-fal

Arun sivan 1 Oct 15, 2019
Build a web-based 3D viewer workshop

This repo is a part of the "Build a web-based 3D viewer workshop" conducted as part of AECTech2021. The workshop walks participants through the proces

CORE studio 19 Jun 7, 2022
A Simple and Beautiful 360° Product Viewer built on Vue.js

vue-360 A Simple and Beautiful 360° Product Viewer built on Vue.js Click here for React Version Demo Demo | Documentation Features 360° View Zoom Pan

Rajeev 86 Aug 23, 2022
Panorama viewer for your homepage

VueJS Panorama Viewer Embed panorama into your website VueJS version of JQuery Panorama Viewer Demo Demo Getting started using npm npm install vuejs-p

Mudin Ibrahim 20 Sep 7, 2022
Atropos is a lightweight, free and open-source JavaScript library to create stunning touch-friendly 3D parallax hover effects.

Atropos Atropos is a lightweight, free and open-source JavaScript library to create stunning touch-friendly 3D parallax hover effects. Available for J

Vladimir Kharlampidi 2.2k Oct 5, 2022
A Vue.js (https://github.com/vuejs/vue) plugin that offers a reusable directive to get image from Cloudinary (https://cloudinary.com)

vue-cloudinary A Vue.js plugin that offers a reusable directive to get image from cloudinary Overview This is a port of the angular-cloudinary library

Diego Pamio 25 Dec 5, 2020
Vue progressive image loader plugin like Medium

vue-image-loader Vue progressive image loading plugin Article here : https://www.kevindesousa.me/vue-image-loader/ Installation $ npm install @kevinde

Kevin De Sousa 57 Jul 19, 2022
🙋‍♀️ Image magic animation drawing effect component for Vue 2.x | 图像动态绘制效果

vue-image-painter English | 简体中文 ?? Example Demo Demo Source Code ?? QuickStart Install yarn add vue-image-painter # OR npm i -S vue-image-painter Imp

Komo 26 Sep 19, 2022
A Vue.js 3.0 image lightbox component with Zoom / Drag / Rotate / Switch .

A Vue.js 3.0 image lightbox component with Zoom / Drag / Rotate / Switch .

XiongAmao 250 Sep 30, 2022
Vue image placeholder directive for broken images.

Vue Image Fallback v-img-fallback Vue image placeholder directive for broken images. If you like this project, please give it a star, and consider fol

Joff Tiquez 45 Sep 10, 2022
Imagvue is an image component for Vue.js

Imagvue Imagvue provides basic image processing props(size,blur,contrast,grayscale, etc.). Support image lazy loading. All Attributes can bind with da

Willy Hong 265 Jul 27, 2022