PDA

View Full Version : Simple Image Panner and Zoomer - possible with percentage width?



Artimidor
03-13-2012, 06:45 PM
1) Script Title: Simple Image Panner and Zoomer

2) Script URL (on DD): http://www.dynamicdrive.com/dynamicindex4/imagepanner.htm

3) Describe problem: Is it possible somehow to use or change the script, so that the div width can be specified with a percentage number?

Or, in other words: I'd like to display a huge map, which should stretch over the whole width of a page, and what cannot be seen on screen the user should then access by moving the map with the help of the script. The examples provided in the script always specify the width and height of the visible section with exact pixel numbers.

The best case scenario for me would be if I could put the div of the script in a table which is defined via percentage widths (e.g. first colum 20%, second 80%) and the size of the visible map area would change when the window is resized...

So yeah: Any chance at all to accomplish this? Thanks in advance for any replies!

Artimidor

vwphillips
03-14-2012, 12:06 PM
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title></title>
<style type="text/css">

/*Default CSS for pan containers*/
.pancontainer{
position:relative; /*keep this intact*/
overflow:hidden; /*keep this intact*/
width:500px;
height:300px;
border:1px solid black;

}

</style>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

<script type="text/javascript" >

/***********************************************
* Simple Image Panner and Zoomer- (c) Dynamic Drive DHTML code library (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit Dynamic Drive at http://www.dynamicdrive.com/ for this script and 100s more
***********************************************/

/* Simple Image Panner and Zoomer (March 11th, 10)
* This notice must stay intact for usage
* Author: Dynamic Drive at http://www.dynamicdrive.com/
* Visit http://www.dynamicdrive.com/ for full source code
*/

// v1.1 (March 25th, 10): Updated with ability to zoom in/out of image

jQuery.noConflict()

var ddimagepanner={

magnifyicons: ['magnify.gif','magnify2.gif', 24,23], //set path to zoom in/out images, plus their dimensions
maxzoom: 4, //set maximum zoom level (from 1x)

init:function($, $img, options){
var s=options
s.imagesize=[$img.width(), $img.height()]
s.oimagesize=[$img.width(), $img.height()] //always remember image's original size
s.pos=(s.pos=="center")? [-(s.imagesize[0]/2-s.wrappersize[0]/2), -(s.imagesize[1]/2-s.wrappersize[1]/2)] : [0, 0] //initial coords of image
s.pos=[Math.floor(s.pos[0]), Math.floor(s.pos[1])]
$img.css({position:'absolute', left:s.pos[0], top:s.pos[1]})
if (s.canzoom=="yes"){ //enable image zooming?
s.dragcheck={h: (s.wrappersize[0]>s.imagesize[0])? false:true, v:(s.wrappersize[1]>s.imagesize[1])? false:true} //check if image should be draggable horizon and vertically
s.$statusdiv=$('<div style="position:absolute;color:white;background:#353535;padding:2px 10px;font-size:12px;visibility:hidden">1x Magnify</div>').appendTo(s.$pancontainer) //create DIV to show current magnify level
s.$statusdiv.css({left:0, top:s.wrappersize[1]-s.$statusdiv.outerHeight(), display:'none', visibility:'visible'})
this.zoomfunct($, $img, s)
}
this.dragimage($, $img, s)
},

dragimage:function($, $img, s){
ddimagepanner.resize(s);
$img.mousedown(function(e){
s.pos=[parseInt($img.css('left')), parseInt($img.css('top'))]
var xypos=[e.clientX, e.clientY]
$img.bind('mousemove.dragstart', function(e){
var pos=s.pos, imagesize=s.imagesize, wrappersize=s.wrappersize
var dx=e.clientX-xypos[0] //distance to move horizontally
var dy=e.clientY-xypos[1] //vertically
s.dragcheck={h: (wrappersize[0]>imagesize[0])? false:true, v:(wrappersize[1]>imagesize[1])? false:true}
if (s.dragcheck.h==true) //allow dragging horizontally?
var newx=(dx>0)? Math.min(0, pos[0]+dx) : Math.max(-imagesize[0]+wrappersize[0], pos[0]+dx) //Set horizonal bonds. dx>0 indicates drag right versus left
if (s.dragcheck.v==true) //allow dragging vertically?
var newy=(dy>0)? Math.min(0, s.pos[1]+dy) : Math.max(-imagesize[1]+wrappersize[1], pos[1]+dy) //Set vertical bonds. dy>0 indicates drag downwards versus up
$img.css({left:(typeof newx!="undefined")? newx : pos[0], top:(typeof newy!="undefined")? newy : pos[1]})
return false //cancel default drag action
})
return false //cancel default drag action
})
$(document).bind('mouseup', function(e){ s.aratio
$img.unbind('mousemove.dragstart')
})
},

resize:function(s){
if (isFinite(s.aratio*1)){
s.wrappersize[0]=s.$pancontainer.width();
s.wrappersize[1]=s.wrappersize[0]*s.aratio;
s.$pancontainer.css({height:s.wrappersize[1]});
if (s.$statusdiv){
s.$statusdiv.css({left:0, top:s.wrappersize[1]-s.$statusdiv.outerHeight(), display:'none', visibility:'visible'})
}
}
},

zoomfunct:function($, $img, s){
var magnifyicons=this.magnifyicons
var $zoomimages=$('<img src="'+magnifyicons[0]+'" /><img src="'+magnifyicons[1]+'" />')
.css({width:magnifyicons[2], height:magnifyicons[3], cursor:'pointer', zIndex:1000, position:'absolute',
top:5, left:magnifyicons[2]-3, opacity:0.7
})
.attr("title", "Zoom Out")
.appendTo(s.$pancontainer)
$zoomimages.eq(0).css({left:parseInt($zoomimages.eq(0).css('left'))-magnifyicons[2]-3, opacity:1}) //position "zoom in" image
.attr("title", "Zoom In")
$zoomimages.click(function(e){ //assign click behavior to zoom images
ddimagepanner.resize(s);
var $zimg=$(this) //reference image clicked on
var curzoom=s.curzoom //get current zoom level
var zoomtype=($zimg.attr("title").indexOf("In")!=-1)? "in" : "out"
if (zoomtype=="in" && s.curzoom==ddimagepanner.maxzoom || zoomtype=="out" && s.curzoom==1) //exit if user at either ends of magnify levels
return
var basepos=[s.pos[0]/curzoom, s.pos[1]/curzoom]
var newzoom=(zoomtype=="out")? Math.max(1, curzoom-1) : Math.min(ddimagepanner.maxzoom, curzoom+1) //get new zoom level
$zoomimages.css("opacity", 1)
if (newzoom==1) //if zoom level is 1x, dim "zoom out" image
$zoomimages.eq(1).css("opacity", 0.7)
else if (newzoom==ddimagepanner.maxzoom) //if zoom level is max level, dim "zoom in" image
$zoomimages.eq(0).css("opacity", 0.7)
clearTimeout(s.statustimer)
s.$statusdiv.html(newzoom+"x Magnify").show() //show current zoom status/level
var nd=[s.oimagesize[0]*newzoom, s.oimagesize[1]*newzoom]
var newpos=[basepos[0]*newzoom, basepos[1]*newzoom]
newpos=[(zoomtype=="in" && s.wrappersize[0]>s.imagesize[0] || zoomtype=="out" && s.wrappersize[0]>nd[0])? s.wrappersize[0]/2-nd[0]/2 : Math.max(-nd[0]+s.wrappersize[0], newpos[0]),
(zoomtype=="in" && s.wrappersize[1]>s.imagesize[1] || zoomtype=="out" && s.wrappersize[1]>nd[1])? s.wrappersize[1]/2-nd[1]/2 : Math.max(-nd[1]+s.wrappersize[1], newpos[1])]
$img.animate({width:nd[0], height:nd[1], left:newpos[0], top:newpos[1]}, function(){
s.statustimer=setTimeout(function(){s.$statusdiv.hide()}, 500)
})
s.imagesize=nd
s.curzoom=newzoom
s.pos=[newpos[0], newpos[1]]
})
}

}


jQuery.fn.imgmover=function(options){
var $=jQuery
return this.each(function(){ //return jQuery obj
if (this.tagName!="IMG")
return true //skip to next matched element
var $imgref=$(this)
if (parseInt(this.style.width)>0 && parseInt(this.style.height)>0) //if image has explicit CSS width/height defined
ddimagepanner.init($, $imgref, options)
else if (this.complete){ //account for IE not firing image.onload
ddimagepanner.init($, $imgref, options)
}
else{
$imgref.bind('load', function(){
ddimagepanner.init($, $imgref, options)
})
}
})
}


jQuery(document).ready(function($){ //By default look for DIVs with class="pancontainer"
var $pancontainer=$('div.pancontainer')
$pancontainer.each(function(){
var $this=$(this).css({position:'relative', overflow:'hidden', cursor:'move'})
var $img=$this.find('img:eq(0)') //image to pan
var options={$pancontainer:$this, pos:$this.attr('data-orient'), curzoom:1, canzoom:$this.attr('data-canzoom'), aratio:$this.attr('data-aspectratio'), wrappersize:[$this.width(), $this.height()]}
ddimagepanner.resize(options);
$(window).bind('resize', function(e){
ddimagepanner.resize(options);
})
$img.imgmover(options)
})
})

</script></head>

<body>
<div class="pancontainer" data-orient="center" data-canzoom="yes" data-aspectratio="0.75" style="width:30%;">
<img src="http://i44.tinypic.com/1hezvm.jpg" style="width:700px; height:525px" />
</div>

</body>

</html>

Artimidor
03-14-2012, 06:46 PM
That was pretty quick and marvelous, vwphillips! Many thanks for that! :D

Works nicely now to stretch the whole picture over the whole size of the page, and resizes like a charm!

Follow-up question in case you still have an answer for that one at hand: How would I embed the script in a table with a fixed image to the left (e.g. an overview map) and a relative area to the right (detailed map), and that second area should resize with the page?

Theoretically I thought it might work like this:

<table border="1" width="90%" bordercolorlight="#000000" bordercolordark="#666666" cellpadding="0" height="400">
<tr>
<td width="388" height="400">
<img src="../maps/provinces/manthria/manthria_duchies_small.jpg" width="388" height="400" />
</td>
<td height="400">
<div class="pancontainer" data-orient="center" data-canzoom="yes" data-aspectratio="0.75" style="width:100%;">
<img src="../maps/provinces/manthria/manthria.jpg" style="width:2036px; height:2112px"" />
</div>
</td>
</tr>
</table>

Alas, no such luck... :cool: Maybe it's not possible for some reason to embed the script that way though, as what happens is that the full picture is displayed in the column in this case. Any idea in this regard perhaps?

vwphillips
03-15-2012, 12:46 PM
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title></title>
<style type="text/css">
/*<![CDATA[*/
.pancontainer {
position:relative;overflow:hidden;width:30%;height:200px;border:solid red 1px;

}

/*]]>*/
</style></head>

<body>
<img id="img" src="http://www.vicsjavascripts.org.uk/StdImages/Listening.jpg" style="width:200px; height:150px;cursor:move;" />
<div id="pan" class="pancontainer" >
<img src="http://www.vicsjavascripts.org.uk/StdImages/Listening.jpg" style="width:700px; height:525px" />
</div>

<script type="text/javascript">
/*<![CDATA[*/

zxcPan={

init:function(imgid,panid){
var img=document.getElementById(imgid),pan=document.getElementById(panid),pimg=pan.getElementsByTagName('IMG')[0],ar=img.height/img.width,obj;
pimg.style.position='absolute';
obj={img:img,pan:pan,pimg:pimg,ar:ar,xy:false};
this.addevt(img,'mousedown','msedown',obj);
this.addevt(img,'mousemove','msemove',obj);
this.addevt(document,'mouseup','mseup',obj);
this.addevt(window,'resize','resize',obj);
this.resize(null,obj);
},

msedown:function(e,obj){
obj.xy=[e.clientX,e.clientY];
obj.pxy=[parseInt(parseInt(obj.pimg.style.left)),parseInt(obj.pimg.style.top)];
this.rtn(e);
},

msemove:function(e,obj){
if (obj.xy){
var mse=[e.clientX,e.clientY],xy=obj.xy,ar=obj.pan.offsetWidth/obj.img.width;
obj.pimg.style.left=Math.max(Math.min(obj.pxy[0]-(mse[0]-xy[0])/ar,0),obj.pan.offsetWidth-obj.pimg.width)+'px';
obj.pimg.style.top=Math.max(Math.min(obj.pxy[1]-(mse[1]-xy[1])/ar,0),obj.pan.offsetHeight-obj.pimg.height)+'px';
}
this.rtn(e);
},

resize:function(e,obj){
var w=obj.pan.offsetWidth;
obj.pan.style.height=w*obj.ar+'px';
obj.pimg.style.left=(w-obj.pimg.width)/2+'px';
obj.pimg.style.top=(w*obj.ar-obj.pimg.height)/2+'px';
},

mseup:function(e,obj){
obj.xy=false;
},

rtn:function(e){
if(e.stopPropagation){
e.stopPropagation();
}
if (!window.event){
e.preventDefault();
}
e.cancelBubble=true;
e.cancel=true;
e.returnValue=false;
return false;
},


addevt:function(o,t,f,p){
var oop=this;
if (o.addEventListener) o.addEventListener(t,function(e){ return oop[f](e,p);}, false);
else if (o.attachEvent) o.attachEvent('on'+t,function(e){ return oop[f](e,p); });
}


}

zxcPan.init('img','pan');
/*]]>*/
</script>

</div>

</body>

</html>

Artimidor
03-15-2012, 01:44 PM
Thanks for the answer, vwphillips - but this script is not the one I need.

The intention would be to use the first script, because it has everything else perfectly in place - I just cannot use it in a table as described above: first column with fixed size (I would use an entire different overview pic there with district borders etc.), second column resizing with the window, containing the area with the script.

So the question is: Is there a way to make the first script work with these parameters?

Artimidor
03-15-2012, 02:12 PM
Sorry for double posting - just wanted to add the example page I'm working on which makes the problem very obvious:

Map Problem (http://www.santharia.com/places/overview_manthria.htm)

I've noticed BTW that the script I currently use behaves differently on IE8 and Firefox or Opera. IE8 always displays the full image while Firefox and Opera stretch the table height when the window is resized - at these browsers the width of the table is fine, but the picture with the script doesn't resize properly, thus the problem with the height.