jQuery image panning
Image panning with animation easing that works on mouse movement with css and jQuery.
view demo Example without animation
Multiple instances demo
Multiple instances synchronization example
Multiple instances demo
Multiple instances synchronization example
download Get all files related to post
Image panning with animation easing
The markup
Simple markup: an image inside a div
<div class="content"> <img src="img.jpg" /> </div>
The CSS
.content{ width: 800px; height: 600px; overflow: hidden; } .content img{ opacity: 0; transition: opacity .6s linear .8s; } .content img.loaded{ opacity: 1; } .img-pan-container, .img-pan-container img{ -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .img-pan-container{ position: relative; overflow: hidden; cursor: crosshair; height: 100%; width: 100%; } .img-pan-container img{ -webkit-transform: translateZ(0); -ms-transform: translateZ(0); transform: translateZ(0); position: absolute; top: 0; left: 0; }
The javascript
Can be placed inside the head tag or at the bottom of the document right before the closing body tag
More code, better animation/performance (60 fps)
<!-- jQuery --> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> <!-- JS --> <script> (function($){ $(document).ready(function(){ //call imagePanning fn when DOM is ready $(".content img").imagePanning(); }); //imagePanning fn $.fn.imagePanning=function(){ var init="center", speed=800, //animation/tween speed //custom js tween _tweenTo=function(el,prop,to,duration,easing,overwrite){ if(!el._mTween){el._mTween={top:{},left:{}};} var startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop]; if(prop==="left"){from=el.offsetLeft;} var diff=to-from; if(overwrite!=="none"){_cancelTween();} _startTween(); function _step(){ progress=_getTime()-startTime; _tween(); if(progress>=tobj.time){ tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1; if(tobj.time<progress+1){tobj.time=progress+1;} } if(tobj.time<duration){tobj.id=_request(_step);} } function _tween(){ if(duration>0){ tobj.currVal=_ease(tobj.time,from,diff,duration,easing); elStyle[prop]=Math.round(tobj.currVal)+"px"; }else{ elStyle[prop]=to+"px"; } } function _startTween(){ _delay=1000/60; tobj.time=progress+_delay; _request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame; tobj.id=_request(_step); } function _cancelTween(){ if(tobj.id==null){return;} if(!window.requestAnimationFrame){clearTimeout(tobj.id); }else{window.cancelAnimationFrame(tobj.id);} tobj.id=null; } function _ease(t,b,c,d,type){ var ts=(t/=d)*t,tc=ts*t; return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t); } function _getTime(){ if(window.performance && window.performance.now){ return window.performance.now(); }else{ if(window.performance && window.performance.webkitNow){ return window.performance.webkitNow(); }else{ if(Date.now){return Date.now();}else{return new Date().getTime();} } } } }; return this.each(function(){ var $this=$(this),timer,dest; if($this.data("imagePanning")) return; $this.data("imagePanning",1) //create markup .wrap("<div class='img-pan-container' />") .after("<div class='resize' style='position:absolute; width:auto; height:auto; top:0; right:0; bottom:0; left:0; margin:0; padding:0; overflow:hidden; visibility:hidden; z-index:-1'><iframe style='width:100%; height:0; border:0; visibility:visible; margin:0' /><iframe style='width:0; height:100%; border:0; visibility:visible; margin:0' /></div>") //image loaded fn .one("load",function(){ setTimeout(function(){ $this.addClass("loaded").trigger("mousemove",1); },1); }).each(function(){ //run load fn even if cached if(this.complete) $(this).load(); }) //panning fn .parent().on("mousemove touchmove MSPointerMove pointermove",function(e,p){ var cont=$(this); e.preventDefault(); var contH=cont.height(),contW=cont.width(), isTouch=e.type.indexOf("touch")!==-1,isPointer=e.type.indexOf("pointer")!==-1, evt=isPointer ? e.originalEvent : isTouch ? e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] : e, coords=[ !p ? evt.pageY-cont.offset().top : init==="center" ? contH/2 : 0, !p ? evt.pageX-cont.offset().left : init==="center" ? contW/2 : 0 ]; dest=[Math.round(($this.outerHeight(true)-contH)*(coords[0]/contH)),Math.round(($this.outerWidth(true)-contW)*(coords[1]/contW))]; }) //resize fn .find(".resize iframe").each(function(){ $(this.contentWindow || this).on("resize",function(){ $this.trigger("mousemove",1); }); }); //panning animation 60FPS if(timer) clearInterval(timer); timer=setInterval(function(){ _tweenTo($this[0],"top",-dest[0],speed); _tweenTo($this[0],"left",-dest[1],speed); },16.6); }); } })(jQuery); </script>
The js code above is more than few lines, simply because it includes a vanilla custom javascript tween for much better performance and smoother animations.
Less code, average animation/performance (30 fps)
$.fn.imagePanning=function(){ var init="center", speed=800; //animation/tween speed //add custom easing for jquery animation $.extend($.easing,{ pan:function(x,t,b,c,d){ return -c * ((t=t/d-1)*t*t*t - 1) + b; } }); return this.each(function(){ var $this=$(this),timer,dest; if($this.data("imagePanning")) return; $this.data("imagePanning",1) //create markup .wrap("<div class='img-pan-container' />") .after("<div class='resize' style='position:absolute; width:auto; height:auto; top:0; right:0; bottom:0; left:0; margin:0; padding:0; overflow:hidden; visibility:hidden; z-index:-1'><iframe style='width:100%; height:0; border:0; visibility:visible; margin:0' /><iframe style='width:0; height:100%; border:0; visibility:visible; margin:0' /></div>") //image loaded fn .one("load",function(){ setTimeout(function(){ $this.addClass("loaded").trigger("mousemove",1); },1); }).each(function(){ //run load fn even if cached if(this.complete) $(this).load(); }) //panning fn .parent().on("mousemove touchmove MSPointerMove pointermove",function(e,p){ var cont=$(this); e.preventDefault(); var contH=cont.height(),contW=cont.width(), isTouch=e.type.indexOf("touch")!==-1,isPointer=e.type.indexOf("pointer")!==-1, evt=isPointer ? e.originalEvent : isTouch ? e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] : e, coords=[ !p ? evt.pageY-cont.offset().top : init==="center" ? contH/2 : 0, !p ? evt.pageX-cont.offset().left : init==="center" ? contW/2 : 0 ]; dest=[Math.round(($this.outerHeight(true)-contH)*(coords[0]/contH)),Math.round(($this.outerWidth(true)-contW)*(coords[1]/contW))]; }) //resize fn .find(".resize iframe").each(function(){ $(this.contentWindow || this).on("resize",function(){ $this.trigger("mousemove",1); }); }); //panning animation 30 FPS if(!timer){ timer=setInterval(function(){ $this.stop().animate({"top":-dest[0],"left":-dest[1]},speed,"pan"); },33.3); } }); }
Image panning without animation
imagePanning function
$.fn.imagePanning=function(){ var init="center"; return this.each(function(){ var $this=$(this); if($this.data("imagePanning")) return; $this.data("imagePanning",1) //create markup .wrap("<div class='img-pan-container' />") .after("<div class='resize' style='position:absolute; width:auto; height:auto; top:0; right:0; bottom:0; left:0; margin:0; padding:0; overflow:hidden; visibility:hidden; z-index:-1'><iframe style='width:100%; height:0; border:0; visibility:visible; margin:0' /><iframe style='width:0; height:100%; border:0; visibility:visible; margin:0' /></div>") //image loaded fn .one("load",function(){ setTimeout(function(){ $this.addClass("loaded").trigger("mousemove",1); },1); }).each(function(){ //run load fn even if cached if(this.complete) $(this).load(); }) //panning fn .parent().on("mousemove touchmove MSPointerMove pointermove",function(e,p){ var cont=$(this); e.preventDefault(); var contH=cont.height(),contW=cont.width(), isTouch=e.type.indexOf("touch")!==-1,isPointer=e.type.indexOf("pointer")!==-1, evt=isPointer ? e.originalEvent : isTouch ? e.originalEvent.touches[0] || e.originalEvent.changedTouches[0] : e, coords=[ !p ? evt.pageY-cont.offset().top : init==="center" ? contH/2 : 0, !p ? evt.pageX-cont.offset().left : init==="center" ? contW/2 : 0 ], dest=[Math.round(($this.outerHeight(true)-contH)*(coords[0]/contH)),Math.round(($this.outerWidth(true)-contW)*(coords[1]/contW))]; $this.css({"top":-dest[0],"left":-dest[1]}); }) //resize fn .find(".resize iframe").each(function(){ $(this.contentWindow || this).on("resize",function(){ $this.trigger("mousemove",1); }); }); }); }
As with everything, you can change it, optimize it and pretty much use it anyway and anywhere you like ๐
Hi,
thank’s for this script.
I’ve got a question about panning’s coordinates:
it’s possible remove the natural gesture?
Therefore: if my mouse move to top,
the image moves to top and not to bottom.
Thanks a lot,
regards,
Davide
Yes you can invert the way cursor works. In the script change:
dest=[Math.round((img.outerHeight(true)-contH)*(coords[0]/contH)),Math.round((img.outerWidth(true)-contW)*(coords[1]/contW))];
to:
dest=[Math.round((img.outerHeight(true)-contH)*(Math.abs(coords[0]-contH)/contH)),Math.round((img.outerWidth(true)-contW)*(Math.abs(coords[1]-contW)/contW))];
I think this is what you need
Great code!
I’m doing a horizontal pan for a wide image. Height of image is full screen with text underneath that you have to scroll to with vertical scrollbar – works fine. However, on mobile you can’t scroll down because the vertical scroll targets the image and not the page. Wondering if there is a way to disable the vertical scroll on the image since it’s not needed.
I’me having the same issue.. any solution ?
Hey there!
Thanks for putting this up! Really cool and well made.
I came across this as I’ve been looking for something that I had a while back but can’t seem to find it again. It’s very similar to what you created, the main difference is that the panning was user driven. In the style of CSS sprites but with Javascript. A container with an image 3 times the width (same height) onclick the next section of image would slide in and the next. Once at the end, another click pans the opposite side back to beginning.
Have you heard of something like this or similar? Can your code be adapted for this?
Thanks and keep it up!
Hello,
I’ve created such scripts. I don’t know if you can adapt the following to your needs but see the 3rd example here:
http://manos.malihu.gr/repository/jquery-thumbnail-scroller/demo/examples/single_image_panning_test.html
The above demo is part of “Query thumbnail scroller” plugin, which I think is very similar to what you need (you can customize the scroll/pan amount via the type option).
Hi Buddy, I have customized your code to implement HTML5 video tag instead of using image tag. It works fine in Modern browsers. But in IE 10 and 9 not woks fine. In IE 10 panning animation and video works fine but if we scroll the page Video container get full width. In IE9 panning animation not working for image also. Please help me…any possible things to fix this issue…
Hi Thanks for your GREAT code!!!
(sorry if this is a duplicated post but I had troubles with “chapta”… Anyway,)
Hi!, what a fantastic piece of code!! Thanks really!
I’m trying to use it to set up a photo slideshow to show a mix list of standard and panoramic images.
I think that the logic should be: “if an image has width greater than container allow panning, if not center and block panning”.
Then there is the node of how replace previous image with next one.
I’ve stored the image list in an array
I tried the attached but I have this issues:
– debugging with console.log(), I noticed that every subsequently image is loaded from the .load() routine an increasing number of times (the first one time, the second two times, …, I have hundreds image to show!); no matter if I call next or previos one.
So, my code:
in the css:
img { height: 100%; } /*just to keep images with same heigth of container */
in the html some variations, just to identify/retrieve needed tags:
<div id="theContent" class="content"> <img id="theImage" src="img.jpg" /> </div> <!-- and then some control buttons: //--> <input type="button" value=" Start " onClick="javascript:ChangeImage('start');"> <input type="button" value=" Prev " onClick="javascript:ChangeImage('prev');"> <input type="button" value=" Next " onClick="javascript:ChangeImage('next');">
then my javascript:
// image array: var inum = -1 var arrImages = new Array (); arrImages[inum=inum+1] = "2016-07-01 09'05 D40-DSC_0226e.JPG"; arrImages[inum=inum+1] = "2016-07-01 10'51 D40-DSC_0227.JPG"; arrImages[inum=inum+1] = "2016-07-01 10'53 D40-DSC_0228e.JPG"; arrImages[inum=inum+1] = "2016-07-01 13'14 CP_S2600-DSCN8859e.JPG"; arrImages[inum=inum+1] = "2016-07-02 20'17 [Cava D'Aliga] D40 Pano_1fixed_1enh_1.JPG"; arrImages[inum=inum+1] = "2016-07-03 09'21 [Cava D'Aliga] D40 Pano_1fixed_1enh1.JPG"; arrImages[inum=inum+1] = "2016-07-03 10'13 CP_S2600-DSCN8870.JPG"; arrImages[inum=inum+1] = "2016-07-03 10'13 CP_S2600-DSCN8871.JPG"; arrImages[inum=inum+1] = "2016-07-03 13'11 D40-DSC_0293 Pano 4f.JPG"; arrImages[inum=inum+1] = "2016-07-03 13'11 D40-DSC_0295.JPG"; arrImages[inum=inum+1] = "2016-07-03 21'16 D40-DSC_0299e.JPG"; arrImages[inum=inum+1] = "2016-07-18 09'35 CP_S2600-DSCN9128.JPG"; var drive = "G:/" var icurr = 0 //function to get correct image array index ChangeImage=function(direction){ // "start", "prev", "next" switch (direction) { case "start": icurr = 0; break; case "prev": icurr = icurr - 1; if (icurr < 0) icurr = -1; break; case "next": icurr = icurr + 1; if (icurr > arrImages.length) icurr = arrImages.length; break; } switch (icurr) { case -1: console.log("bot"); break; case (arrImages.length): console.log("top"); break; default: ShowImage(drive + arrImages[icurr]); break; } } // function to replace image var state=1; // to manage image panning (as you suggested in previous comment) ShowImage=function(imgPath){ var w = $("#theContent").width(); $("#theImage").load(function() { // with this I saw multi-load for each subsequently image currImg = $("#theImage").attr('src') console.log("\nloading image..") console.log(currImg) state=1; $("#theImage").trigger("mousemove",1); // get the width of new image var iw = $("#theImage").width(); state = (w > iw) ? 0 : 1; // changing state according with content/image width }).attr('src', imgPath); } // in your code, added (as you suggested in previous comment): .parent().on("mousemove touchmove MSPointerMove pointermove",function(e,p){ if(!state){return;} ...
Hi there,
Im using your code and it works very nice. But i have one question, im using the image panning as fullscreen background image.. But when the image is smaller than the screen the image panning doesnt work. Can i fix this with a quick fix? I would like something like background-size:cover; But then with image panning functionality…
Like to hear from u.
Hello,
Background as cover and image panning are a bit different in the way they work. I’m not sure you can emulate exactly
background-size:cover
functionality but you can easily achieve something like this:http://manos.malihu.gr/repository/jquery-image-panning/tests/fullscreen-cover-test.html
which I think is close enough.
You need to give the
.img-pan-container img
a min-width and min-height equal to the viewport (view source in the demo above):.img-pan-container img{ /* other rules... */ min-width: 100vw; min-height: 100vh; }
Hope this helps
Hi,
I love the smoothness of the script, is it possible to pan the image automatically without the interaction of the user?
Thanks
Hello,
Can you describe the concept? How would the image pan (top, bottom, left, right)?
You could probably just grab the custom tween function and place it out of the
imagePanning
function and call it on your element(s):(function($){ var _tweenTo=function(el,prop,to,duration,easing,overwrite){ .... }; $(document).ready(function(){ _tweenTo($(".content")[0],"left",300,2000); }); })(jQuery);
If you need specific functionality let me know.
i had an issue with this: the zoom was panning outside the viewport on iOs devices…
i had to add those lines before “dest” array gets populated at following line:
dest=[Math.round ...
Then i added…
if (coords[0] < 0) { coords[0] = 0; } if (coords[0] > $(window).height()) { coords[0] = $(window).height(); }
not sure that’s the right fix.
Not sure how this can be replicated… Can you send me a test page or link?
I think it’s probably some CSS property missing… Is the image contained within a div with overflow hidden?
hi, great script! works well. i was wondering if there was a way so that on mouse out, the image could go back to being centered?
Yes but you need to add/trigger the js event. The easiest way would be to just extend the
imagePanning
function call like this://call imagePanning fn when DOM is ready $(".content img").imagePanning().parent().on("mouseleave touchend MSPointerleave pointerleave",function(){ $(this).trigger("mousemove",1); });
Is it possible to see image in thumbnail size and after mouse over it scale and zoom image to real size with animation then start moving, after mouse out it scale to thumbnail size?
Hello,
You could show/hide the large image when hovering a thumbnail. I created a working test here:
http://manos.malihu.gr/repository/jquery-image-panning/tests/thumb-hover-example.html
I’ll try to create a proper tutorial for this but for now, check the example source code as it’s fully working with CSS transitions and alternative code for click event (instead of hover).
Hope this helps
This is great! Quick question: we’re implementing this on a site that used a base image, and a second layer of illustrations placed on top of the main background image. Any specific implementation suggestions to avoid moving the placement of the illustrations on top? Also, will this work well on tablet?
Yes it works with touch devices (it pans the same way on touch/tap move).
About the first question:
If you give the panned image an id, you can call the main function (
imagePanning()
) on this id (instead of the more generic img selector).For example, assuming the following markup:
<div class="content"> <img src="img.jpg" id="panned-image" /> <!-- panned image --> <img src="img.jpg" /> <!-- your non-panned overlay element --> </div>
you could change the script to:
$("#panned-image").imagePanning();
Hope this helps
Hey Mahilu, appreciate the code man!
Your stock script works perfect and solid
I am stuck on this one.. The above script mention is not working for me. My non-panned overlay element does not show.. Do I need to specify additional classes for them? It might be a very stupid question but I am relatively new to coding, so could you clear it up for me mate? Thanks and cheers
Do you get any console errors (in borwser’s dev tools)? Is your non-panned image path correct? I can’t really help unless I see your link or code…
Great code!
I have a question:
how to do if I want to stop it working?
I have some buttons on my website which start transitions (arrows to change from an image to another, with a slide move), but before these transitions start, I need to stop/disable all this panning (and start it again when the new is in place).
How can I do ?
Thank you very much!
You could add a variable in
mousemove
event to check its value and do the panning.For example, add the (global) variable before image panning function:
var state=1; $.fn.imagePanning=function(){...
and add the conditions in
mousemove
event and interval:// ... .parent().on("mousemove touchmove MSPointerMove pointermove",function(e,p){ if(!state){return;} // ... timer=setInterval(function(){ if(!state){return;} // ...
Then in your script(s) you can do:
state=0;
to disable andstate=1;
to enable.Hello buddy,
Thanks for this piece of code it helped me a lot.
Now im wondering if there is a query to after i click a button will place the cursor where i decide within the viewport?
Thanks a lot
You cannot take control user’s cursor with javascript and move it programmatically (it’s not allowed). This is a good thing because it would be chaos if you could ๐
Very true.
There is a way to make it draggable instead of hover? so it can be used on touch devices?
The script as it is, works on touch devices the same way as with the cursor (it pans the image opposite of touch-swipe). If you need an exact touch-drag behavior I’d suggest using a more complex plugin (with more options) like this one (panning demo).
This is nice! Has anyone got it working with the accelerometer in iOS? This would be perfect for a project I am about to start… Thanks ๐
This is a great piece of code! I was wondering would it work with panning only a certain amount of a image? AKA constraining the image pan?
You’d need to pan a div with the image as a background, like this example (check the first one):
http://manos.malihu.gr/repository/jquery-image-panning/demo/image-map-div-panning.html
In this example you could use a combination of div dimensions with background position to do what you need. For example:
.img-pan-container .img-wrapper .img{ /* div panning */ position: relative; /* make panned element smaller than its background image */ width: 1320px; height: 621px; } /* ... */ /* set its background position to get where you want */ <div class="img" style="background:url(img.jpg) no-repeat 70% bottom;">
hi malihu,
this is great โ thanks!
i’m wondering, could it be adapted to pan a div instead of an image? i’d like to pan a map (image or div with a background image), which has markers (divs) absolutely positioned on top of it. i was thinking if i could move the entire div, then those markers would stay in place.
is this something possible? thanks!
Yes you can do it by modifying the script. I’ve made a demo with an image map and nested divs with anchors here:
http://manos.malihu.gr/repository/jquery-image-panning/demo/image-map-div-panning.html
You can check its source/download it and work on it ๐
Hey
First, love your work!
I’m looking for a image panner for a project for the Norwegian Colorlab: http://colorlab.no/. The goal of the project is to have a research tool for image quality assessment and need a panner for large images.
Would it be possible in the demo where there are multiple instances that they move paralell to each other? Meaning if you pan in either boxes/instances the others would move the same?
Thanks in advance.
Best,
Khai
Hello,
It can be done with few minor script mods. I’ll upload an example later today ๐
Made some minor changes to the script and I’ve uploaded a new example here:
http://manos.malihu.gr/repository/jquery-image-panning/demo/multiple-instances-synchronization.html
Easy setup:
1. Add a class to the instances you want to synchronize, e.g. “sync”
<div class="content sync"> <img src="img.jpg" /> </div> <div class="content sync"> <img src="img.jpg" /> </div> <div class="content sync"> <img src="img.jpg" /> </div>
2. Add the class selector to sync variable (in multiple-instances-synchronization.html on line: 84):
sync=".sync"
I’ve added the multiple-instances-synchronization.html example in the demo links at the top of the page, as well as the download archive.
Thank you so much, this is really great and such a fast reply!
Thanks for the code!
Is there a way to position the image within the container so that the top of the image is aligned with the top of the container? I added autopan on window load. I’d like the image to load from top to bottom on window load.
Hello,
I’ve just updated the script. In the updated code, you can change the centering by changing:
var init="center"
to:
var init="0"
Thanks Malihu. I’m too far down the rabbit hole on the old code at this point. I got the image to pan from top to bottom on window load, but now when I include a setTimeout function for the MouseMove function, I can no longer pan the image. Ideas?
What do you need the timeout for? If you can send me your url/code I’ll be able to help.
I needed this code tanx a lot
Nice code, is it works or compatible with touch device like smartphone or tablets?
Love this effects, now trying to make some different position, thanks for the great tips.
Hi,
great code! Thanks dude!
I’ve question: I want the mouse outside of the div for moving the image. I’ve changed this code:
$imagePan.bind("mousemove", function(event){ MouseMove(event); });
to this:
$('body').bind("mousemove", function(event){ MouseMove(event); });
But my change worked not correct. What have I to change?
Thanks for helping.
Hey, nice script
I was wondering if it’s possible to change the code for viewing on smartphones & tablets so that the user can drag instead of hover?
Hi there, great script!
I was wondering if it’s possible to change the code for viewing on smartphones & tablets so that the user can drag instead of hover?
Thanks for a great script it is the perfect answer to what I was looking for.
I have impleted your script on a page of a website of mine to allow users to move a map around. I hope to eventually use it on photographs of mine.
I am trying to understand how I can get the script to work on a page that resizes depending on what size screen the viewer is using and even how to implement it on a page with a header and a footer and the usaual menu buttons.
I take my hat off to people who understand HTML, Java and CSS as I have to rely on WordPress themes and Dreamweaver. Having said that I still can’t get Dreamweaver to do what I want hence the switch to WordPress, apart from the page with the map.
Okay I’m off to the library to get a book on the subject!
Link to map
http://deangale.com/currarong_beach_holiday_map.html
Cheers
Hi! Thank you for this code ๐
i’m using it with outside container fixed at 100% width and 100% height (a fullscreen image zoom) but i’ve a problem on the left side: when mouse reach position 0, the image is shifted on the right of about 200px, instead vertical movements are fine, and i just can’t realize why…
Fix ie6 display Bug:
find line :
var easeType="easeOutCirc";
replace to:
var easeType="easeOutCirc"; if ($.browser.msie && $.browser.version.substr(0,1)<7) {$imagePan_panning.css("margin-left","0px").css("margin-top","0px");}// fix ie6
Hi. Thanks for this great script. I have used it on the Berndt Museum site for a virtual exhibition, using Lasso to build the clickable links by pulling information from the filemaker database. Check it out at http://berndt.uwa.edu.au/panorama.lasso?panID=1. Thanks a million!
Awesome! Thank you for using the script and for your comments Alan ๐
Yes, I’m looking for this wonderful effect, thank you so much, great job.