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);