In the past I fiddled around with the moozoom plugin to add support for image maps and on a new project I needed the same thing. But this new project uses a lot of jQuery stuff and jQuery and mootools don’t play together particularly well. Although there are a lot of image zooming plugins available for jQuery, none of them did exactly what I needed. I just wanted image zooming, panning and support for image maps. Anyway, this is what I came up with. This is my first adventure in the world of jQuery plugins, so it may not be a perfect implementation but it works for me…
Usage is pretty simple
$('.selector').zoomable();
where .selector is the selector for your image. View an example here (that page will also be the place I put all new versions of this code). You can now also programmatically zoom in and out using $('.selector').zoomable('zoomIn'); and $('.selector').zoomable('zoomOut'); which you can hook up to buttons for users without a mouse wheel
Here’s the code (requires jQuery and jQuery UI)
(function ($) {
$.fn.zoomable = function (method) {
return this.each(function (index, value) {
// restore data, if there is any for this element
var zoomData;
if ($(this).data('zoomData') == null) {
zoomData = {
busy: false,
x_fact: 1.2,
currentZoom: 1,
originalMap: null,
currentX: 0,
currentY: 0
};
$(this).data('zoomData', zoomData);
}
else
zoomData = $(this).data('zoomData');
var init = function() {
if (value.useMap != "") {
var tempOriginalMap = document.getElementById(value.useMap.substring(1));
zoomData.originalMap = tempOriginalMap.cloneNode(true);
// for IE6, we need to manually copy the areas' coords
for (var i = 0; i < zoomData.originalMap.areas.length; i++)
zoomData.originalMap.areas[i].coords = tempOriginalMap.areas[i].coords;
}
$(value).css('position', 'relative').css('left', '0').css('top', 0).css('margin', '0');
$(value).draggable();
// jquery mousewheel not working in FireFox for some reason
if ($.browser.mozilla) {
value.addEventListener('DOMMouseScroll', function (e) {
e.preventDefault();
zoomMouse(-e.detail);
}, false);
if (value.useMap != "") {
$(value.useMap)[0].addEventListener('DOMMouseScroll', function (e) {
e.preventDefault();
zoomMouse(-e.detail);
}, false);
}
}
else {
$(value).bind('mousewheel', function (e) {
e.preventDefault();
zoomMouse(e.wheelDelta);
});
if (value.useMap != "") {
$(value.useMap).bind('mousewheel', function (e) {
e.preventDefault();
zoomMouse(e.wheelDelta);
});
}
}
$(value).bind('mousemove', function (e) {
zoomData.currentX = e.pageX;
zoomData.currentY = e.pageY;
});
};
var left = function() {
return parseInt($(value).css('left'));
};
var top = function() {
return parseInt($(value).css('top'));
}
var zoomIn = function() {
// zoom as if mouse is in centre of image
var parent = $(value).parent()[0];
zoom(zoomData.x_fact, left()+parent.offsetLeft+(value.width/2), top()+parent.offsetTop+(value.height/2));
};
var zoomOut = function() {
// zoom as if mouse is in centre of image
var yi = parseInt($(value).css('top'));
var parent = $(value).parent()[0];
zoom(1 / zoomData.x_fact, left()+parent.offsetLeft+(value.width/2), top()+parent.offsetTop+(value.height/2));
};
var zoomMouse = function (delta) {
// zoom out ---------------
if (delta < 0) {
zoom(1 / zoomData.x_fact, zoomData.currentX, zoomData.currentY);
}
// zoom in -----------
else if (delta > 0) {
zoom(zoomData.x_fact, zoomData.currentX, zoomData.currentY);
}
};
var zoomMap = function () {
// resize image map
var map = document.getElementById(value.useMap.substring(1));
if (map != null) {
for (var i = 0; i < map.areas.length; i++) {
var area = map.areas[i];
var originalArea = zoomData.originalMap.areas[i];
var coords = originalArea.coords.split(',');
for (var j = 0; j < coords.length; j++) {
coords[j] = Math.round(coords[j] * zoomData.currentZoom);
}
var coordsString = "";
for (var k = 0; k < coords.length; k++) {
if (k > 0)
coordsString += ",";
coordsString += coords[k];
}
area.coords = coordsString;
}
}
};
var zoom = function (fact, mouseX, mouseY) {
if (!zoomData.busy) {
zoomData.busy = true;
var xi = left();
var yi = top();
var new_h = (value.height * fact);
var new_w = (value.width * fact);
zoomData.currentZoom = zoomData.currentZoom * fact;
// calculate new X and y based on mouse position
var parent = $(value).parent()[0];
mouseX = mouseX - parent.offsetLeft
var newImageX = (mouseX - xi) * fact;
xi = mouseX - newImageX;
mouseY = mouseY - parent.offsetTop
var newImageY = (mouseY - yi) * fact;
yi = mouseY - newImageY;
$(value).animate({
left: xi,
top: yi,
height: new_h,
width: new_w
}, 100, function () {
zoomData.busy = false;
});
zoomMap();
}
};
if (method == "zoomIn")
zoomIn();
else if (method == "zoomOut")
zoomOut();
else
init();
});
};
})(jQuery);