Image Drag
Version 1.00
written by Gerald Holdsworth

This was written for my Repton Resource Page site where a user can go to a level map and zoom in or out to see the map clearer, or the whole thing. I then added the 'Zoom to Fit' and 'Zoom to Actual' buttons to reset the image. Finally, I added the ability to click and drag the map around within the confines of the viewing area.

To use this, you just need to add a control div 'MapCtrl', then within that a div for the image 'MapImg' and one for the toolbar 'MapTool'. Within the MapImg div, this is where you load the image, via an img HTML tag, but add an onLoad attribute for ResizeMap(0), which zooms to fit, and initialise(this.id), which sets it all up.

Within the MapTool div, just add some dummy text, such as 'Tool Bar'. Then, finally, straight after the MapTool div add a call to the Javascript function updateToolbar().

The size, and border, of both elements can be changed, remembering to take into account the border thickness with the width and height, as can the font.

Click here for a demo

Stylesheet for 'Image Drag':
#MapCtrl
{
 width: 450px;
 height: 490px;
 overflow: hidden;
 margin:auto;
}
#MapImg
{
 width: 448px;
 height: 448px;
 overflow: hidden;
 text-align: left;
 border: 1px Solid red;
}
#MapTool
{
 text-align: center;
 width: 448px;
 height: 32px;
 float:left;
 overflow: hidden;
 border: 1px Solid red;
}
#zoom
{
 display: inline;
 overflow: hidden;
 width: 128px;
 height: 32px;
 margin: 4px;
 vertical-align: top;
 font-size: 24pt;
 color: green;
 font-family:Arial,sans serif;
 font-weight: bold;
}
Javascript for 'Image Drag':
function getStyle(el,styleProp)
{
 var y='0';
 if (document.getElementById(el).currentStyle) y=document.getElementById(el).currentStyle[styleProp];
 else if (window.getComputedStyle) y=document.defaultView.getComputedStyle(document.getElementById(el),null).getPropertyValue(styleProp);
 else y=document.getElementById(el).style[styleProp];
 if (y=='undefined') y='0';
 return y;
}
function toNumber(str)
{
 while (isNaN(str)) str=str.substr(0,str.length-1);
 return parseInt(str);
}
function createIMG(src,width,height,id,title)
{
 var btn;
 btn=document.createElement('img');
 btn.setAttribute('src',src);
 btn.setAttribute('width',width);
 btn.setAttribute('height',height);
 btn.setAttribute('id',id);
 btn.name=name;
 btn.title=title;
 return btn;
}
function updateToolbar()
{
 var el_toolbar=document.getElementById('MapTool');
 el_toolbar.innerHTML='';
 var btn;
 btn=createIMG('ZoomIn.png','32px','32px','zoomin','Zoom In');
 btn.onclick=function(){resizeMap(2)};
 el_toolbar.appendChild(btn);
 btn=createIMG('ZoomOut.png','32px','32px','zoomout','Zoom Out');
 btn.onclick=function(){resizeMap(1)};
 el_toolbar.appendChild(btn);
 btn=document.createElement('div');
 btn.setAttribute('id','zoom');
 btn.name='zoom';
 btn.innerHTML='100%';
 el_toolbar.appendChild(btn);
 btn=createIMG('ZoomTo100.png','32px','32px','fullsize','Actual Size');
 btn.onclick=function(){resizeMap(3)};
 el_toolbar.appendChild(btn);
 btn=createIMG('ZoomToFit.png','32px','32px','zoomtofit','Zoom To Fit');
 btn.onclick=function(){resizeMap(0)};
 el_toolbar.appendChild(btn);
}
function resizeMap(zoom)
{
 var el_mapimg=document.getElementById('Map');
 var div_width=toNumber(getStyle('MapImg','width'));
 var div_height=toNumber(getStyle('MapImg','height'));
 switch (zoom)
 {
  case 0: //Zoom To Fit
   var h=el_mapimg.naturalHeight;
   var w=el_mapimg.naturalWidth;
   var r=h/w;
   if (h<div_height && w<div_width)
   {
    w=div_width;
    h=w*r;
   }
   if (h>div_height)
   {
    h=div_height;
    w=h/r;
   }
   if (w>div_width)
   {
    w=div_width;
    h=w*r;
   }
   el_mapimg.style.width=w.toFixed()+'px';
   el_mapimg.style.height=h.toFixed()+'px';
   break;
  case 1: //Zoom Out
   el_mapimg.style.width=(el_mapimg.width/1.1)+'px';
   el_mapimg.style.height=(el_mapimg.height/1.1)+'px';
   break;
  case 2: //Zoom In
   el_mapimg.style.width=(el_mapimg.width*1.1)+'px';
   el_mapimg.style.height=(el_mapimg.height*1.1)+'px';
   break;
  case 3: //Full Size
   el_mapimg.style.width=el_mapimg.naturalWidth+'px';
   el_mapimg.style.height=el_mapimg.naturalHeight+'px';
   break;
 }
 centralise(el_mapimg,div_width,div_height);
 var percent=Math.round((el_mapimg.width/el_mapimg.naturalWidth)*100);
 if (percent=='Infinity')
  document.getElementById('zoom').innerHTML='100%';
 else
  document.getElementById('zoom').innerHTML=pad(percent,3)+'%';
}
function centralise(el_mapimg,div_width,div_height)
{
 if (el_mapimg.height<=div_height)
  el_mapimg.style.top=(div_height-el_mapimg.height)/2+'px';
 else
 {
  var t=toNumber(el_mapimg.style.top);
  if (t>0) el_mapimg.style.top='0px';
 }
 if (el_mapimg.width<=div_width)
  el_mapimg.style.left=(div_width-el_mapimg.width)/2+'px';
 else
 {
  var l=toNumber(el_mapimg.style.left);
  if (l>0) el_mapimg.style.left='0px';
 }
}
function pad(number,length)
{
 var str=''+number;
 while (str.length<length)
 {
  str=' '+str;
 }
 return str;
}
function hasTouch()
{
return 'ontouchstart' in document.documentElement;
}
function initialise(image)
{
img_ele=null;
container=document.getElementById(image).parentNode.id;
event_start=hasTouch()?'touchstart':'mousedown';
event_move=hasTouch()?'touchmove':'mousemove';
event_end=hasTouch()?'touchend':'mouseup';
document.getElementById(image).addEventListener(event_start, start_drag);
document.getElementById(image).style.position='relative';
document.getElementById(image).onDragStart="return false"; 
document.getElementById(container).addEventListener(event_move, while_drag);
document.getElementById(container).addEventListener(event_end, stop_drag);
}
function start_drag(event)
{
var x_cursor=hasTouch()?event.changedTouches[0].clientX:event.clientX;
var y_cursor=hasTouch()?event.changedTouches[0].clientY:event.clientY;
img_ele=this;
x_img_ele=x_cursor;
y_img_ele=y_cursor;
 img_ele.style.cursor='move';
 event.preventDefault();
}
function stop_drag()
{
 if (img_ele!==null)
  img_ele.style.cursor='auto';
 img_ele = null;
}
function while_drag(event)
{
var x_cursor=hasTouch()?event.changedTouches[0].clientX:event.clientX;
var y_cursor=hasTouch()?event.changedTouches[0].clientY:event.clientY;
 var div_width=toNumber(getStyle(container,'width'));
 var div_height=toNumber(getStyle(container,'height'));
 if (img_ele!==null)
 {
  var movex=(x_cursor-x_img_ele);
  var movey=(y_cursor-y_img_ele);
  var img_width=toNumber(getStyle(img_ele.id,'Width'));
  var img_height=toNumber(getStyle(img_ele.id,'Height'));
  x_img_ele=x_cursor;
  y_img_ele=y_cursor;
  var l=toNumber(getStyle(img_ele.id,'Left'))+movex;
  var t=toNumber(getStyle(img_ele.id,'Top'))+movey;
  var r=(img_width+l)-div_width;
  var b=(img_height+t)-div_height;
  if (l<=0 && r>=0)
   img_ele.style.left=l+'px';
  if (t<=0 && b>=0)
   img_ele.style.top=t+'px';
  if (l>0)
   img_ele.style.left='0px';
  if (t>0)
   img_ele.style.top='0px';
  if (r<0)
   img_ele.style.left=div_width-img_width+'px';
  if (b<0)
   img_ele.style.top=div_height-img_height+'px';
  centralise(img_ele,div_width,div_height);
 }
}
Click here to download.

If you would like to email me, put gerald@ in front of the domain name, insead of www..
©2011-2020 Gerald Holdsworth IT Services