previous exampleHomeDownload
next example

Create interactive 2D/ 360°/ 3D product presentations / product catalogues with clickable hotspots and hotspot areas using high or ultra resolution images!

Loading, please wait...
About AJAX-ZOOM hotspot editor [Last updated: 2014-04-06]

Flash free online hotspot editor for AJAX-ZOOM 3D/360/2D player. With the help of this editor you can create multiple hotspots or rectangle image areas and setup several click / mouseover actions for them e.g. links, tooltips, popup lightboxes or bind your own JavaScript functions including AJAX-ZOOM API for several events. The default example is a 360 degrees image set. You can however load any other images like catalogue pages or fotoalbums and create hotspots on single (2D) images as well.

As a result the hotspot editor returns a JSON object with all settings including the positions of the hotspots and / or rectangle image areas. Among other considerable possibilities this JSON object can be saved to a JavaScript file and loaded into any other AJAX-ZOOM example later.

6.0+ 2.0+ 2.0+ 1.0+ 9.5+ 2.0+ 4.0+ Pinch zoom, tap zoom,
swipe
How does it work?

  1. Hit the Load content tab and follow the instructions in order to change the image(s) you would like to configure with hotspots. For testing just leave whatever is loaded on default.
  2. Hit the Hotspots -> New Hotspot tab and define new hotspots name. Push "create" button.
  3. Adjust the hotspot position(s) by simply dragging it to the desired place. For 360 we found it more convenient to use arrow keys to spin while adjusting the positions. In order to disable the hotspot at a particular frame you can right click on it or hit the Hotspots -> Action / Delete tab, choose the hotspot in question (it turns red) and press "Disable in this frame" button. The "Enable in this frame" button is also under this tab. For precise positioning enlarge to the max zoom level!
  4. You can change the appearence of your hotspot under Hotspots -> Appearance tab now or later. All the settings applied there e.g. defining a different hotspot image and it's size can be taken over for all hotspots at once.
  5. Define what happens when the user clicks on / goes with mouse over a particular hotspot. Hit the Tooltips / Text tab and select the hotspot, it turns red. Under the Tooltips tab you can define most commonly used options for default tooltip which looks similar to Fancybox (it is not Fancybox). If you do not like the appearance you can always modify its CSS (.axZmToolTipInner, .axZmToolTipOuter, .axZmToolTipTitle) or just set a different class (toolTipTitleCustomClass and toolTipCustomClass options). As an idea - the content of the tooltip can be iFrame with any other different content in it. If nothing helps - you want something completely different, you can define event actions on your own. They are saved as strings in the JSON object and will be instantly evaled when loaded.
  6. Fine-tuning: possibly there are additional options which might not be "visualized" in this hotspot editor release. Under Save / Edit JSON -> Import / Edit you will see the complete JSON object. Any option (property, value) can be customized for each hotspot individually. For a complete description of the options see under Option / Docu tab.
  7. After you have created, positioned and configured your hotspots the JSON should be saved somewhere to be accessed later by the player. This can be done under Save / Edit JSON -> Save JSON to JavaScript file tab. Since AJAX-ZOOM does not utilize any DB we provide only saving to JavaScript file as generic way of saving the work. The file is written into '/pic/hotspotJS' directory (which has to be writeable by PHP); you can change the path to any other directory by editing '/axZm/saveHotspotJS.php'; The password for saving is set inside saveHotspotJS.php as well.
  8. The saved JS file is then called over an AJAX-ZOOM callback when the player is loaded... jQuery.fn.axZm.loadHotspotsFromJsFile('../pic/hotspotJS/eos_1100D.js', cache = false); (If you will use a database you can just link to any other file which will return JavaScript Object with hotspots configuration.)

Notes

  • The Options / Docu tab only refers to the possible configurations of the hotspots and not the AJAX-ZOOM player. AJAX-ZOOM player itself can be configured with hundreds of other options to suit anybody's needs. See AJAX-ZOOM documentation and other examples.
  • The file saveHotspotJS.php is very simple and can be ported to any other language other than PHP within minutes. Due to possible XSS attacks it is not recommended to have this file publicly accessible as it is in this example.
  • For an alternative method of loading hotspots configurations and positions see also under Load content tab.
  • This hotspot editor extension is fairly new and you can expect it to be extended in the nearby future. As usual, Your feedback on usability along with suggestions is much appreciated!
  • Please note that the position object of each hotspot accepts absolute positions of the original image (pixel values) or relative percentage values. So in case you already have the coordinates they can be easily imported in AJAX-ZOOM JSON object.

Build Applications

AJAX-ZOOM offers an extended API to handle hotspots in various ways. In fact the entire hotspot editor is built upon this API. The result of the hotspot configurator is a static configuration saved in a file. However you can also build applications which will set hotspots dynamically depending e.g. on users choice. example34 shows such an application, where hotspots are created dynamically and highlight choosen words in the text (saved as image).

If you would like AJAX-ZOOM team to build an application for you, please get in touch with us.

Is it free?

  • The answer is Yes and No. AJAX-ZOOM has it's own License Agreement, please read!
  • Under certain conditions You can use it totally for free!
  • In any case you can and should download and test AJAX-ZOOM without any further obligations. If you like it and would have certain features enabled - You can buy it.
  • In case after all you have any doubts or questions please contact the support.

Comments (1)

william seitz
2013-03-27 01:27:25
william seitz
considering 365 viewer for certain products we sell online

Leave a Comment

Name (required):
Email (required):
Website:
Your comment (no html):
Looking for a place to add a personal image? Visit www.gravatar.com to get Your own gravatar, a globally-recognized avatar. After you're all setup, Your personal image will be attached every time you comment.
The final code example:

The only difference between any other AJAX-ZOOM implementation or example is that the JavaScript file with JSON data produced by this editor is loaded in AJAX-ZOOM onLoad callback with jQuery.fn.axZm.loadHotspotsFromJsFile API, see below...

					<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
					<html xmlns="http://www.w3.org/1999/xhtml">
					<head>
					<!-- jQuery core (>= 1.5), needed! -->
					<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
					
					<!-- AJAX-ZOOM core, needed! -->
					<link href="../axZm/axZm.css" type="text/css" rel="stylesheet" />
					<script type="text/javascript" src="../axZm/jquery.axZm.js"></script>
		
					</head>
					<body>
					
					<div style="min-width: 100px;">
						<div id="abc">
							<!-- Content inside target will be removed -->
							<div style="padding: 20px">Loading, please wait...</div>
						</div>
					</div>
					
					<!-- Init -->
					<script type="text/javascript">
					// Create empty object
					var ajaxZoom = {}; 
					
					// Define callbacks, for complete list check the docs
					ajaxZoom.opt = {
						onBeforeStart: function(){
							// Set backgrounf color, can also be done in css file
							jQuery(".zoomContainer").css({backgroundColor: "#FFFFFF"});		
						},
						onLoad: function(){
							// Some settings can be set inline
							jQuery.axZm.spinReverse = false;
							
							// Load hotspots over this function... 
							// or just define jQuery.axZm.hotspots here and trigger jQuery.fn.axZm.initHotspots(); 
							jQuery.fn.axZm.loadHotspotsFromJsFile("../pic/hotspotJS/eos_1100D.js", false, function(){
								// Do something if you want				
							});
						}
					};
					
					// Define the path to the axZm folder, adjust the path if needed!
					ajaxZoom.path = "../axZm/"; 
					
					// Define your custom parameter query string
					// example=spinIpad has many presets for 360 images
					// You can change them in /axZm/zoomConfig.inc.php after elseif ($_GET['example'] == 'spinIpad')
					// 3dDir - best absolute path to the folder with 360/3D images
					// for 2D you can use zoomData, e.g. zoomData=/your/path/image1.jpg|/your/otherPath/image2.jpg
					ajaxZoom.parameter = "example=spinIpad&3dDir=/pic/zoom3d/Uvex_Occhiali"; 
					
					// The ID of the element where ajax-zoom has to be inserted into
					ajaxZoom.divID = "abc";		
					</script>
					
					<!-- Include the loader file -->
					<script type="text/javascript" src="../axZm/jquery.axZm.loader.js"></script>
					
					</body>
					</html>
					
Documentation of the the hotspot configuration object options

These options below are only about possible hotspot settings and not the AJAX-ZOOM player itself. AJAX-ZOOM player can be configured with hundreds of other options to suit anybody's needs. See AJAX-ZOOM documentation and other examples.

ValueDefaultDescription
shape'point'Shape of the hotspot. Possible values "point" or "rect", added Ver. 4.0.5; Type: bool
enabledtrueState of defined hotspot. Possible values true and false, added Ver. 4.0.5; Type: bool
width32Width of the hotspot image, only applied if shape value is "point". Type: integer
height32Height of the hotspot image, only applied if shape value is "point". Type: integer
gravity'center'Hotspot gravity relative to its position. Possible values: 'center', 'topLeft', 'top', 'topRight', 'right', 'bottomRight', 'bottom', 'bottomLeft', 'left'. Only applied if shape value is "point". Type: string
offsetX0Adjustment of hotspots horizontal visual position. Only applied if shape value is "point". Type: integer
offsetY0Adjustment of hotspots vertical visual position. Only applied if shape value is "point". Type: integer
padding0Padding of the box with hotspot image and/or text. Type: integer
opacity1Default opacity, disabled in IE < 9; Type: float <= 1.0
opacityOnHover1Opacity on mouse hover, disabled in IE < 9; Type: float <= 1.0
backColor'none'Background color, added Ver. 4.0.5; Type: string
zIndex1zIndex of the hotspot. Type: integer
borderWidth0CSS border width, added Ver. 4.0.5; Type: integer
borderColor'red'CSS border color, added Ver. 4.0.5; Type: string
borderStyle'solid'CSS border style, e.g. 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset' or combinations of them, added Ver. 4.0.5; Type: string
cursor'pointer'Mouse cursor. Type: string
zoomRangeMin0Min zoom level for hotspot to be shown, added Ver. 4.0.6; Type: 0 <= integer <= 100
zoomRangeMax100Max zoom level for hotspot to be shown, added Ver. 4.0.6; Type: 0 <= integer <= 100
hotspotImage'hotspot64_green.png'PNG image for the hotspot located in /axZm/icons directory, only applied if shape value is "point". Ver. 4.0.6+ image can be any absolute path with and without http. Type: string
hotspotImageOnHoverfalsePNG image for the hotspot on mouse hover, only applied if shape value is "point". Ver. 4.0.6+ image can be any absolute path with and without http. Type: string
hotspotTextfalseText puten direct over the hotspot image, can be for example a number if shape value is point; can be also HTML. Type: false or string
hotspotTextFillfalseIf shape value is "rect" the rectange does not capture mouse events like click. Setting this value to true will set the inner box to 100% height capturing all events except mousescroll for zooming. Any css can be overriden with hotspotTextCss option, see below, added Ver. 4.0.5; Type: bool
hotspotTextClassfalseAdditionally to CSS class ".axZmHotspotText" add on ther CSS class to hotspotText layer, added Ver. 4.0.5; Type: false or string
hotspotTextCss{}Additionally to CSS class ".axZmHotspotText" css which is added to hotspotText layer, added Ver. 4.0.5; Type: object
hotspotObjects{}Any number of absolutely positioned layers directly inside the hotspot if shape value is "rect", added Ver. 4.0.5; Type: object
altTitlefalseShow system like tootip by mousehover if main tooltip is triggered on click (toolTipEvent); CSS class: axZmHoverTooltip; Type: false or string
altTitleClassfalseCSS class for altTitle instead of axZmHoverTooltip class, added Ver. 4.0.6; Type: false or string
altTitleAdjustX20Horizontal offset of the altTitle, added Ver. 4.0.6; Type: integer
altTitleAdjustY20Vertical offset of the altTitle, added Ver. 4.0.6; Type: integer
labelTitlefalseSticky label (or tooltip) at any position near a hotspot, accepts HTML, added Ver. 4.0.6; Type: string
labelGravity'left'Label gravity, possible values: 'topLeft', 'topLeftFlag1', 'topLeftFlag2', 'top', 'topRight', 'topRightFlag1', 'topRightFlag2', 'right', 'rightTopFlag1', 'rightTopFlag2', 'rightBottomFlag1', 'rightBottomFlag2', 'bottomRight', 'bottomRightFlag1', 'bottomRightFlag2', 'bottom', 'bottomLeft', 'bottomLeftFlag1', 'bottomLeftFlag2', 'left', 'leftTopFlag1', 'leftTopFlag2', 'leftBottomFlag1', 'leftBottomFlag2', 'center', added Ver. 4.0.6; Type: string
labelBaseOffset5Auto offset in all directions, added Ver. 4.0.6; Type: integer
labelOffsetX0Horizontal offset, added Ver. 4.0.6; Type: integer
labelOffsetY0Vertical offset, added Ver. 4.0.6; Type: integer
labelClassfalseCSS class instead of axZmHotspotLabel, added 4.0.6; Type: false or integer
labelOpacity1Opacity level, added 4.0.6; Type: float <= 1.0
toolTipTitlefalseTitle shown in the tooltip; Type: false or string
toolTipHtmlfalseText or html inside tooltip, as idea it can be also iframe, e.g. <iframe src="http://www.ebay.de" scrolling="no" width="100%" height="100%" frameborder="0"></iframe> Type: false or string
toolTipAjaxUrlfalseUrl for toolTipHtml get from AJAX request (not cross site, for cross site use an iframe inside toolTipHtml); Type: false or string
toolTipWidth250Width of the tooltip, ignored when toolTipGravity is set to fullsize or fullscreen! Type: integer
toolTipHeight120Min height of the tooltip, ignored when toolTipGravity is set to fullsize or fullscreen! Type: integer
toolTipGravity'hover'Tooltip gravity, possible values: 'hover', 'fullsize', 'fullscreen' (added Ver. 4.0.6), 'topLeft', 'top', 'topRight', 'right', 'bottomRight', 'bottom', 'bottomLeft', 'left'. The difference between 'fullsize' and 'fullscreen' is that 'fullsize' refers to players dimensions, whereas 'fullscreen' to window size. Type: string
toolTipGravFixedfalseApplies fixed position to toolTipGravity except 'fullsize', 'hover' turns into centered position. Type: bool
toolTipFullSizeOffset40toolTipGravity fullsize uses maximal available player / window width and height. This is the margin to the edges if e.g. toolTipGravity is 'fullscreen', 'fullsize' or toolTipGravFixed option is set to true, so the fixed position is relative to the player size. Type: integer
toolTipTitleCustomClassfalseUse specific classname instead of axZmToolTipTitle, added Ver. 4.0.5; Type: false or string
toolTipCustomClassfalseUse specific classname instead of axZmToolTipInner. Type: false or string
toolTipAdjustX10Horizontal offset. Type: integer
toolTipAdjustY10Vertical offset; Type: integer
toolTipAutoFliptrueFlip tooltip horizontaly / vertically depending on best fit. Type: bool
toolTipOpacity1.0Opacity of the tooltip. Type: float <= 1.0
toolTipFadefalseFade tooltip time in ms. Type: false or integer
toolTipEvent'click''mouseover' or 'click', defaults to 'click' on touch devices. Type: string
toolTipHideTimout1000If toolTipEvent is 'mouseover' this setting allows to move the cursor to the tooltip within this time. Type: integer
toolTipDraggabletrueSet tooltip to be draggable, toolTipTitle has to be defined because this is the handle, can be an empty div. Type: bool
toolTipCloseIcon'fancy_closebox.png'PNG image for close button located in /axZm/icons directory. Shown if toolTipEvent is 'click' and touch devices. Ver. 4.0.6 can be absolute image path, also with http; Type: string
toolTipCloseIconPosition'topRight'Position of the close icon, possible values are: 'topLeft', 'topRight', 'bottomRight' and 'bottomLeft', added Ver. 4.0.5; Type: string
toolTipCloseIconOffsetfalseOffset / position of the close button icon. If false the offset is set instantly. An integer sets depending on toolTipCloseIconPosition - top, bottom or left, right position to this number. If object, e.g. {"right": 20, "top": 0} toolTipCloseIconPosition is ignored. Changed in Ver. 4.0.5; Type: false, integer or object
toolTipCloseIconMouseOverfalseShow close button also if toolTipEvent is 'mouseover'. Type: bool
toolTipOverlayShowfalseShow overlay when tooltip window pops up, added Ver. 4.0.5; Type: bool
toolTipOverlayOpacity0.75Overlay opacity, added Ver. 4.0.5; Type: float <= 1
toolTipOverlayColor'#000000'Overlay color, added Ver. 4.0.5; Type: integer
toolTipOverlayClickClosefalseClose tooltip by clicking on the overlay, added Ver. 4.0.5; Type: bool
hreffalseSimple link for the hotspot.
hrefTarget'_blank'Target for href (simple link), possible values: _blank (new window), anything else is same window. Type: string
clicknullYour custom click event function, e.g. simple fancybox gallery:
					
jQuery.fancybox(
[{
	'href': 'http://www.domain.com/your/image1.jpg',
	'title': 'Description of the first image'
},{
	'href': '/path/to/an/other/image2.jpg',
	'title': 'Description of the second image'
}], {
	'padding': 0,
	'transitionIn': 'none',
	'transitionOut': 'none',
	'type': 'image',
	'titlePosition': 'over',
	'changeFade': 0
});
AJAX-ZOOM does not require fancybox, so fancybox JavaScripts and CSS files need to be included in the document. The above code is just an example of a lightbox usage; it can be any other lightbox where you could define images to be displayed in a simmilar way. Please note that toolTip* options e.g. toolTipHtml would produce a popup which looks simmilar to fancybox, but they do not require fancybox JavaScript and CSS files.
onRendernullVer. 4.1.3+ Your custom function when a particlar hotspot is added to the DOM; receives name of the hotspot as argument
mouseovernullYour custom mouseover event function
mouseoutnullYour custom mouseout event function
mouseenternullYour custom mouseenter event function
mouseleavenullYour custom mouseleave event function
mousedownnullYour custom mousedown event function
mouseupnullYour custom mouseup event function
position{}position is a JS object with the positions of a particular hotspot, e.g.
position: {
	1: {left: 1500, top: 720},
	3: {left: 660, top: 710},
	4: {left: 760, top: 510}
}
The keys (1,2,3 ...) can be numbers (starting from 1, not 0) or filenames of particular frames. In case a key is omited the hotspot will not be shown in that particular frame.

If shape value is 'rect' each value of position object needs to have 'width' and 'height', e.g.
position: {
	1: {left: 300, top: 720, width: 300, height: 300},
	3: {left: 660, top: 710, width: 200, height: 350},
	4: {left: 760, top: 510, width: 700, height: 220}
}
The 'left', 'top', 'width' and 'height' values can be pixel values related to original size of the image or percentage values (e.g. left: '45.75%', top: '37.3%').
Create new hotspot

Below are only couple settings you can set right away.

- point    - rectangle
- makes most sense for 360 / 3D
- set altTitle same as hotspot name
Left: Top:
The 'left', 'top', 'width' and 'height' values can be pixel values related to original size of the image (e.g. left: 1600, top: 900 or left: '1600px', top: '900px') or they can be percentage values (e.g. left: '45.75%', top: '37.3%').
Delete / disable hotspots
(for 360 and 3D)
Instead of clicking on the "disable in this frame" button below you can also simply right click on any hotspot to disable it in current frame. This right click action is only activated when hotspots are draggable / editable in this editor.
Some API functions
- only for changing positions in the editor
Hotspot appearance
width: px    height: px
Please note, that when a specific hotspot is selected in the editor, the default "hotspotImage" (the red round with plus sign on it) is applied to highlight the selection. This happens only in this hotspot configurator and does not affect your final code. Also the hotspots are only draggable in this configurator.
zoomRangeMin: %    zoomRangeMax: %
   offsetX: px    offsetY: px
px
opacity:    opacityOnHover:
  
  
borderWidth: px    borderColor:    borderStyle:
   - apply for all hotspots
Alt title
Left (altTitleAdjustX): px    Top (altTitleAdjustY): px
Sticky label
px
Left (labelOffsetX): px    Top (labelOffsetY): px
Default popup contents
Do not use " (double quotation marks) in html tags. Use ' instead!
Size and look
Width (toolTipWidth): px    Height (toolTipHeight): px
  fixed position (toolTipGravFixed)   autoflip (toolTipAutoFlip)
Left (toolTipAdjustX): px    Top (toolTipAdjustY): px
px - from all edges
- click    - mouseover    - hide time if mouseover (toolTipHideTimout)
e.g. axZmToolTipTitleCustom (try it)
e.g. axZmToolTipInnerCustom (try it)
(use transparent PNG in toolTipCustomClass for only backgound opacity)
- title needs to be defined too (title div is handle)
Close icon and overlay
   offset (toolTipCloseIconOffset):
Show: (toolTipOverlayShow):    Close on click (toolTipOverlayClickClose):
Opacity (toolTipOverlayOpacity):    Color (toolTipOverlayColor):
Mainly for rectangles
Do not use " (double quotation marks) in html tags. Use ' instead! set Lorem
e.g. axZmHotspotTextCustom (try it)
e.g. {"color":"black","height":"100%","width":"100%"}
Link and other events (JavaScript)
Load a different 2D / 360 or 3D content
You do not need to edit html of this file in order to load a different 2D / 360 or 3D content into the editor. Just enter a path into one of the fields below and press "LOAD" button. Press "GET" button to see what is currently loaded.
or
(optional)
  
How does it work:
    • For 2D (single image or gallery with more images) please enter local path(s) to the image(s), e.g.
      "/pic/zoom/animals/test_animals1.png"
      or image set with image paths separated with vertical dash e.g.
      "/pic/zoom/animals/test_animals1.png|/pic/zoom/animals/test_animals2.png"
      If you want to load all images from a folder please just enter the path to this folder e.g.
      "/pic/zoom/animals"
    • For 360 (single row 360 object) please enter only the path to the folder where your 360 images are located e.g.
      "/pic/zoom3d/Uvex_Occhiali";
    • For 3D (multi row turnable object) please enter the path to the folder where subfolders with each row of 3D are located.
      On http://www.ajax-zoom.com/examples/example33.php this could be
      "/pic/zoomVR/nike"
      (not provided with the download package)
    • Hotspot file path is the path to the file with hotspot configurations and positions, e.g.
      "/pic/hotspotJS/eos_1100D.js"
      You can create such a file in the previous tab "Save / Edit JSON"
Notes:

When you hit the "LOAD" button the parameters entered are passed to the function "changeAxZmContentPHP" located in "/axZm/extensions/jquery.axZm.hotspotEditor.js", which basically just reloads the player same way it is loaded when the page is opened.

There are also different ways of loading and saving hotspot configuration parameters besides loading a static JavaScript file. For example you could point to /some/dyn_language/file.do?hotspotID=123 which would return the JSON object stored in a database. If you use the API function jQuery.fn.axZm.loadHotspotsFromJsFile then you have to reference jQuery.axZm.hotspots variable to the returned JSON object from your /some/dyn_language/file.do (the return of this file is expected to be JavaScript - without script tags).

Alternatively define jQuery.axZm.hotspots wherever after AJAX-ZOOM is initialized, e.g. onBeforeStart callback (or later at any time) and "manually" init the hotspots with jQuery.fn.initHotspots()

Taking the above one step farther you can also build applications which will set hotspots dynamically depending e.g. on users choice or action. example34 shows such an application, where hotspots are created dynamically and highlight choosen words in the text (saved as image).

Import, edit, apply entire JSON for all hotspots manually
- with defaults - positions as image names - do not format
 

- keep draggable (will not affect final JSON)
Save to JS file
(can be set inside '/axZm/saveHotspotJS.php')
- keep linebreaks, tab stops etc.
- creates backup of the current js file if present with a timestamp in file name (recommended)
- instantly update / import JSON settings before saving
to .js
Saving JSON data to a JavaScript file is one of the possibilities to initialize created hotspots with any other implementation / example over AJAX-ZOOM "onLoad" callback. See also under About -> Code example tab.
Import only coordinates
- positions as image names - do not format
MORE EXAMPLES
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom
javascript picture zoom