Git Product home page Git Product logo

iv-viewer's Introduction

iv-viewer

All Contributors A zooming and panning plugin inspired by google photos for your web images.

Features

  • Smooth dragging and panning of images.
  • Support touch devices.
  • Double tap to zoom in/zoom out.
  • Pinch in/out to control zoom.
  • Snap view for better panning and zooming experience.
  • Allow quick display of loaded image then loading of high quality image progressively.
  • Exposed API to control zoom programmatically.
  • Custom Events to listen for the state changes.

alt tag

Install

Through npm

npm install iv-viewer --save

Or get compiled development and production version (css and js) from ./dist

Usage

Import ImageViewer and it's style.

import ImageViewer from 'iv-viewer';

// or
const ImageViewer = require('iv-viewer').default; 

// Import css
import 'iv-viewer/dist/iv-viewer.css';

You can choose to import css file inside your scss/less files.

You can also use the standalone UMD build by including dist/iv-viewer.js and dist/iv-viewer.css in your page.

<script src="https://unpkg.com/iv-viewer/dist/iv-viewer.js"></script>

<link rel="stylesheet" href="https://unpkg.com/iv-viewer/dist/iv-viewer.css">

Three different modes

Full-Screen Mode

If you want to show images in full screen, with predefined styles. You can use FullScreenViewer.

import { FullScreenViewer } from 'iv-viewer';

const viewer = new FullScreenViewer(options); // check options section for supported options

viewer.show('images/low-res-img', 'images/hi-res-img'); //second option is optional. Check better image loading section

Container Mode

If you have your own container to show images (you might have custom layout or gallery), you can use image-viewer in a container mode.

<div id="image-container"></div>
import ImageViewer from 'iv-viewer';

const container = document.querySelector('#image-container');
const viewer = new ImageViewer(container, options); //check options section for supported options

viewer.load('images/low-res-img', 'images/hi-res-img'); //second option is optional. Check better image loading section

Image Mode

If you just want to add zoom and pan gesture to your images in a image-viewer style, you can use image-viewer in image mode.

<img id="image" src="image.png" data-high-res-src="hi-res-image.png" />
import ImageViewer from 'iv-viewer';

const image = document.querySelector('#image');
const viewer = new ImageViewer(image, options); // check options section for supported options

Options

Option Allowed Value Default Description
zoomValue number in percentage 100 It defines the initial zoom value of the image.
maxZoom number in percentage 500 It defines the max limit for the zoom value of the image.
snapView boolean true If true will show snap view.
refreshOnResize boolean true Defines whether to refresh the viewer on resize of window. This is available only for Container and Image mode. On FullScreen mode it will refresh on window resize by default.
zoomOnMouseWheel boolean true Defines weather to allow zoom with mouse scroll or not.
hasZoomButtons boolean true Defines weather to add zoom buttons or not
zoomStep number 50 The number of which the zoom should increase/decrease when the buttons are clicked
listeners object null multiple useful callbacks that could use in-order to get the current state of the viewer

The Listeners

There are multiple listeners you can register with each viewer instance

import ImageViewer from 'iv-viewer';

const viewer = new ImageViewer(element, { 
  listeners: { 
    onInit: callback(data), // called when the instance is initiated 
    onDestroy: callback(), // called when the instance is destroyed
    onImageLoaded: callback(data), // called on image load
    onZoomChange: callback(data), // called on zoom in/out
  } 
});

Callback Data

The data passed to each callback is very useful, it contains the current instance with more info that you can use to react to the instance state

Option dataType Description
container HTMLElement The current container of the viewer
snapView HTMLElement The snap view element in the viewer
zoomValue Number The current zoom value
reachedMin boolean A boolean value that determine if the zoom value reached the initial zoom.
reachedMax boolean A boolean value that determine if the zoom value reached the maximum zoom.
instance ImageViewer The current instance which contains all other info if needed

API (ImageViewer)

Creating an instance

import ImageViewer from 'iv-viewer';

const viewer = new ImageViewer(element, options);

Here the first argument is the element, which can be container where viewer will be loaded, or it can be a image in which case viewer will be initialized in a image mode.

You can also pass a selector directly instead of a DOM element.

const viewer = new ImageViewer('#element', options);

Second argument is to provide configuration options for the ImageViewer. This argument is optional.

Instance methods

load(imgSrc, highResImg)

Load an image to the viewer. You can pass two different resolution of the image as first and second argument (optional). See why do you need it at better image loading section.

viewer.load('image.png', 'hi-res-image.png');

Note that this is just required for the container mode, as in image mode you can just use src and data-high-res-src attribute and the image will load by itself. See image mode example

zoom(zoomValue, point)

zoomValue: A percentage value to which you want to zoom the image.

point(optional): Point {x, y} is the coordinate of the container which would act as the center for the zoom. If not defined, it will take the center of the container as the zooming point.

viewer.zoom(300, { x: 500, y: 500 });

resetZoom()

Reset zoom to the default or provided initial zoomValue.

viewer.resetZoom();

refresh()

Method to manually refresh the viewer. It will reset the zoom and pan. It will also recalculate the dimension of container, window and image in case if that is changed.

viewer.refresh();

destroy()

Destroys the plugin instance and unbind all events. It will also reset the container or the image(if ImageViewer is used in image mode). It returns null which you should assign to viewer variable to completely free up memory.

viewer = viewer.destroy();

API (FullScreenViewer)

FullScreenViewer is extended from ImageViewer. So it shares the same ImageViewer api along with some FullScreenViewer API.

Creating an instance

import { FullScreenViewer } from 'iv-viewer';

const viewer = new FullScreenViewer(options);

Unlike ImageViewer you don't have to pass container for the viewer as it will be initialized in pre-defined full screen container.

First argument is to provide configuration options for the FullScreenViewer. This argument is optional.

Instance methods (FullScreenViewer)

FullScreenViewer inherits all the instance method of ImageViewer. In additional to that it has following methods.

show(imgSrc, highResImg)

Show the full screen viewer with passed image on the show method. You can pass two different resolution of the image as first and second argument (optional). See why do you need it at better image loading section.

viewer.show('image.png', 'hi-res-image.png');

hide()

Hide/Close the fullScreen viewer.

viewer.hide();

Better image loading

To improve the perceived experience, it is always recommended to show the already loaded image or the low quality image on the viewer and let the ImageViewer load high quality image in parallel.

It will also try to preview the high quality image while it's loading so it will give a progressive loading effect.

ImageViewer provides api to do this. Container mode

viewer.load('image.png', 'hi-res-image.png');

FullScreen mode

viewer.show('image.png', 'hi-res-image.png');

Image Mode

<img id="image" src="image.png" data-high-res-src="hi-res-image.png" />

In all of the above example it will first try to display the first image and then load the second image (if passed) in parallel.

The second image is optional, which you should pass when you feel you can improve the image loading experience by first showing low quality image and then progressively update it with high quality image.

Demo

codesandbox preview link: https://8ypwzryom0.codesandbox.io/

codesandbox link: https://codesandbox.io/s/8ypwzryom0

Like this

⭐ this repo

Major updates

v2.1.0

  • It's a complete rewrite of ImageViewer with no jQuery requirement in ES6.
  • While the options and instance method are same the way you use a ImageViewer and FullScreenView is changed. The v1 API will no longer be supported.
  • Published on the npm. V1 was not available on npm.
  • Changed the package name to iv-viewer. image-viewer name was not available on npm.
  • Added some listeners
  • Added zoom in/out buttons
  • Some SCSS variable for easier overrides.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Ruchika
Ruchika

📖
Sudhanshu Yadav
Sudhanshu Yadav

📖
Amrit Kahlon
Amrit Kahlon

📖
10000
10000

📖

This project follows the all-contributors specification. Contributions of any kind welcome!

iv-viewer's People

Contributors

1e4 avatar amritk avatar dependabot[bot] avatar monajjar1 avatar mvasigh avatar nk521 avatar s-yadav avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

iv-viewer's Issues

Errors on using ImageViewer()

I tried using this library using a script import as well as a npm dependency, however both times I ran into errors on calling the ImageViewer() function.

When using <script>:
ImageViewer() is not a function

When using npm:
TypeError: Cannot call a class as a function

Missing NPM Package.json

I cannot find this package on NPM. And it doesn't have a package.json file for use with projects built with NPM.

Can we please have both?

Thanks and a few thoughts

Sudhanshu,

Thanks so much for developing the image viewer. I had evaluated quite a few earlier this year and found none then that did what I want, were understandable, or were easy to use. I just found yours today and it is perfect in all those respects, well, almost. And so a few thoughts...

A callback when the image is loaded would be helpful so that I can extinguish a busy indicator. I added a call to my code at the end of the function "refreshView()" but would prefer an officially supported callback as an option.

My images vary widely in size. When I set a zoom that is suitable for the largest it is much to large for the smaller ones. Please consider an optional alternate expression of the zoom factor based on pixel ratios instead of percent. For example a pixel zoom factor of 1:1 would be a suitable maximum for my largest and smallest images.

I love the snap view, makes it very easy to pan around the large images. However, I believe that it should be at a fixed position on the screen and not scroll with the image. Even better, the fixed position could be specified in an option.

The horizontal and vertical scroll bars are always visible on the screen, even when not needed. I tried briefly to work around this by placing my image in a division which was slightly smaller than the outside container but that was not effective. I suggest that you only show the scroll bars when zooming, not for the original image view.

You can view my use of ImageViewer on the "Asmt Map" or "PClass Map" tabs at my site:

https://pogodata.wrwetzel.com

By the time you get to view it I may have combined the tabs into one "Static Maps" or just "Maps" tab as your library makes it possible to work with multiple images. That saves real estate on the tabs bar.

Thanks again,
Bill Wetzel

Container Mode

Is there a way, in the container mode, to use HTML for the source of the images?
The way it is used for the Full screen mode.

Can't centre images in "Image Mode"

Test 1

  1. Create a container with both width and height set at 100%
  2. Append an img containing a small image
  3. Apply ImageViewer to the image (Image Mode)

The image sits top left instead of being centred

Test 2

  1. Create the same setup as above
  2. Set both width and height of iv-container at 100% in hope it will keep all the sub-divs centred

Images are now centred, but they're stretched to fill the screen

event api?

I'd love to be able to handle an event when the full-screen viewer closes.

I can see that there's an events array in the code, but I can't find any reference to accessing it externally without modifications.

Even an onClose callback option would be fine, but I'm sure other people would have use for other behaviors, too.

Can I upgrade from v1.1.0 to v2 safely?

I am currently in the process of updating our jQuery version (from 1.7 to 3+), and in the JQMigrate process they suggest upgrading any plugins as well. We are currently using ImageViewer v 1.1.0, but am not sure if I can safely upgrade to the new 2.0 version?

Thank you in advance!

What is the minimum size for the initial image?

I tried using a small image, 102x132 pixels for the small image and a larger image 884x1151 for the larger image, and the zoom/pan did not work. Or, it was not visible?

Are there optimum sizes for the two images?

Is there a necessary relationship between the two image sizes that needs to be maintained for the plugin to work optimally?

Thanks!

Mark

Close button background

Hi, firstly many thanks for this great viewer!

It is possible to add a gray or shaded backgorund
to the close button? like this:
https://www.freeiconspng.com/uploads/silver-close-button-png-15.png
I use ImageViewer for mostly white background documents
and hard to find a white button on the white.

Other thing: on Android smartphones the close button is
very small. It is possible to make it larger?

And the tird: It is possible to assign browser back button and
Android back button to close the viewer instead default history_back?

Thanks a lot,
Peter

image coordinates in percentages

Thank you for a great library!

I would like to know, how can I obtain the zoom position in percentages?

Lets say when I zoom to particular rect, how can I get the position, like width, height,x, y regarding to that original image?

Position is not properly modified when zooming out

  1. Load the official demo
  2. Go to the bottom of the page -> Image mode
  3. Zoom in on the ballerina
  4. Pan to the right
  5. Zoom out

The image is not centred at the same time it's zoomed out and all the sudden, the position is reset.

Disabling infinite images option

Hey i really loved your imageviewr code. I had doubt on how to disable infinite images and enabling mouseover zoom & move option and also how to include a rote option for the images. Thanks a lot for this code it really helped me.

Weird display issue after loading multiple images

This only happens in Chrome, not IE. I don't know if it's being caused by combo w/ other libraries (Knockout.js) for example. But in the screenshot, it's the gray areas. Ignore the white areas, I was trying to hide sensitive data. When you move your mouse around, these gray areas popup briefly then disappear, but it basically makes the app unusable.

Any ideas? We're using the ImageViewer in container mode. Is there maybe code to reinitialize the selected images that I'm not using properly?

My code is below the attachment.

untitled

Code:
capture

data-high-res-src is not working in fullscreen demo

hey, you did a really nice job with this imageviewer, but i found a thing.

so your example code in the html for the fullscreen example is

<img src="images/1.jpg" data-high-res-src="images/1_big.jpg" alt="" class="gallery-items">

but it is loading 1.jpg in fullscreen mode instead of 1_big.jpg

thank you

Rotate button in iv-container

I wanna rotate big picture every time when click the rotatebutton. . How can i add it to the project. pls help me :) (by the way, i never chance the project or codes)

curImageIdx = 0 not handled in Container mode

When the inital image is loaded and prev button is pressed, then index is 0 and it is not handled, just add the below code to handle it. easy!
if(curImageIdx <= 0) curImageIdx = total;
showImage();

Panning does not work on firefox

Panning on desktop firefox causes image to be dragged and dropped instead of panning.
adding estart.preventDefault() to the end of the touchstart/mousedown event fixes the issue.

Save and restore zoom

Hi,

with the "zoom(zoomValue, point)"-method I can set the view - but how can I get the current values (zoomValue and point)?
I'd like to save the current view for the image and restore it later.

Mynock

Image jumps when 1 finger remains after pinch-zooming

When pinch-zooming an image, the image tends to jump up/down/left/right at the end of the pinch.

I can reproduce this on mobile android chrome with all three examples of the demo at https://8ypwzryom0.codesandbox.io/

The issue may affect any touch device.

Problem happens when you are releasing pinch (release 1 of 2 fingers), but a touchmove event is sent before you release second finger. This happens unintentionally often enough with touch devices (and clumsy fingers).

Steps to reproduce :

  1. use zoom at least once so the zoom level is > 100

  2. do a pinch zoom in or out

  3. release one finger

  4. move the remaining finger

I have debugged it around and here is what happens in the code :

  • First touch : imageSlider.startHandler is called, defining sx & sy, and also calling snapSlider.onStart which defines startHandleTop & startHandleLeft

  • Pinch zoom : Slider.moveHandler does nothing because isSliderEnabled() returns false

  • When one finger remains : slider moves using reference values from first touch, which are kinda broken by the zoom.

I have fixed it for my app with the following code, feel free to reuse or make your own proper fix.

  1. _pinchAndZoom endListener
const endListener = (eEnd) => {
    // unbind events
    events.pinchMove();
    events.pinchEnd();
    this._state.zooming = false;
    // properly resume move event if one finger remains
    if ( eEnd.touches.length == 1 )
        this._sliders.imageSlider.startHandler(eEnd);
};
  1. I also had to adjust that line in Slider.startHandler :
const isTouchEvent = (eStart.type === 'touchstart' || eStart.type === 'touchend');

Panning does not work on mobile chrome

Mobile mediaquery hides the viewFinder. Move logic is under viewFinder code and it uses viewFinder height and width for calculations. When viewFinder is hidden browser gives 0 for width and height -> panning won't work.
Logic need to be changed so that the panning is done on image space and viewFinder is updated (if visible)

For fast fix I just changed the mediaquery so that viewFinder is always visible but just drawn outside of the view.
@media screen and (max-width: 767px) {
.iv-snap-view {
top: -9999px;
}
}

Distorted images on transition using load function

I use a single container ImageViewer with different images as selected by a user on a web page.
Sometimes the image is distorted... the fault is in the load code.

I made the following changes at the end of of the load function:
/////Critical change RMA 06/26/2018 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// if (imageLoaded(currentImg[0])) {
// refreshView();
// } else {
// $(currentImg[0]).on('load', refreshView);
// }
$(currentImg[0]).on('load', refreshView);
/////Critical change RMA 06/26/2018 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//refreshView();

So - we always refreshView on load, instead of testing imageLoaded(currentImg[0]).
Now, the resultant new image is correct, and not distorted.

I have enclosed the edited ImageViewer 1.1.3 file with my changes in place.

imageviewer_load_fix_113.zip

Distortion?

I have several images that are displayed one by one in a container, Most of the time when naviagting between the images, the viewer.load(lowres,highres) works perfectly... but about 1/0th of the time the new image comes up oddly expended (not physically) and appears distorted.

Going away to another image and then back can help and things are normal again.

I see nothing the the dom to indicate an issue.
Have a look at one.jpg (below) that is how it should look and two.jpg as it appears now and then
one
two

.

Images are not removed

Hello,

first I want to thank for this nice library, but I have one issue:
I have a list of images, which upon clicking on them I load into the image viewer. When loading the second image, it seems that the first one does not get removed. Having a look inot the debugger tools of the browser, it reveals that with every imageViewer.load a new image is added (I am only loading the image with one url, so no hi res image url present).
The images are added with the classes iv-image iv-small-image. Looking into the source code of iv-viewer in the method _loadImages, I can see that only the images with the following classes are removed from the dom iv-snap-image, iv-large-image. I guess thats the reason why the images stay there. Removing the snap image works as expected.

Any advice?

Thx
Markus

Initial zoom is wrong in Container mode

This is a sample setup

<div style="display: block; background-position: -10000px 0px;" id="slideshow">
    <div class="imageContainer iv-container">
        <div style="display: none;" class="iv-loader"></div>
        <div class="iv-snap-view"><div class="iv-snap-image-wrap"><img style="display: inline; width: 150px; height: 150px;" class="iv-snap-image" src="https://localhost:4443/owncloud/index.php/apps/gallery/preview/53455?&amp;width=2600&amp;height=2600&amp"><div style="top: 0%; left: 0%; width: 100%; height: 100%;" class="iv-snap-handle"></div></div><div class="iv-zoom-slider"><div style="left: 0px;" class="iv-zoom-handle"></div></div></div>
        <div class="iv-image-view"><div class="iv-image-wrap"><img style="display: block; width: 918px; height: 918px; left: 164.5px; top: 0px; max-width: none; max-height: none;" class="iv-large-image" src="https://localhost:4443/owncloud/index.php/apps/gallery/preview/53455&amp;width=2600&amp;height=2600&amp"></div></div>
    </div>
</div>

and the code used

var container = $('#slideshow')
var imageContainer = container.find('.imageContainer')
var viewer = ImageViewer(imageContainer );
viewer.load(image.src);

The slideshow CSS

#slideshow {
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    z-index: 100000;
    display: none;
    background-color: black;
    background-position: center center;
}

The large image has the following style applied to it: width: 918px; height: 918px, but the original image is 50x50.

I've tracked it down to this line, which stretches the image to fill the container:
https://github.com/s-yadav/ImageViewer/blob/master/imageviewer.js#L608

I think there should be a limit applied, using the initial zoomValue.

Text link to image view

Excellent viewer. In addition to the thumbnail to full view, is there a way to have the same effect but from a text link - e.g. "Picture of a dog" when clicked on displays the image in the same way as the thumbnail does?

Thanks
Gavin

SnapImage handles

Hello,

I have the issue in Firefox that even whenn zoom is 100% and the snap image is not shown, the cursor changes to a hand at the places where the snap image would normally be shown.

Thx
Markus

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.