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);
13 comments:
This works for my image if I have an ID for the image and set the Javascript usage statement in the body to: $('#world_map').zoomable(); (world_map is the ID of my image). I could not get it to work using '.selector'
However what it doesn't do is to preserve the image map. I can also try to refer to the image map's ID as such, $('#world_image_map').zoomable(); where my image map ID is "world_image_map" however the image map does not zoom with the image, so there doesn't seem to be image map support for me.
I'm using jQuery 1.42 minimum and referred to the plugin in its own file called "zoomable.js" which I loaded as src along with jquery.min.js in two separate script statements.
Any suggestions?
This plugin seems to zoom the image map pretty well, but I can't seem to get the dragging part to work. Instead of dragging the image, it applies the browser default and gives me a little image icon that I can drag around.
I tried just applying draggable() instead of zoomable() to my image and discovered that it just doesn't work. Draggable doesn't seem to do very well with image maps. I looked around and found a couple people with similar problems but no good solutions.
It seems like others must have run into this with this plugin. Is this so, and how are you solving it?
Yeh, I've never got dragging on the actual image map to work, but generally clicking on the image map does something else anyway so I don't mind the fact that dragging doesn't work, it might be confusing for the end user anyway.
Having said that, dragging should work on the parts of the image that don't have an image map area over them.
Hey nice post its exactly what i want. but just struggling to make it work. Is there a way you can post the example thanks in advance
I am getting the cords as 0,0,0,0 for this. any suggestions ?
var originalArea = originalMap.areas[i];
var coords = originalArea.coords.split(',');
Saswat
Could be you'll get 0,0,0,0, depends what your image map coordinates are
here is the image map
here is the function i am calling
$(document).ready(function() {
$('#x').zoomable();
});
Problem is the image map resizing always gives cords 0,0,0,0 so imagemap is not getting created.
Hi Saswat
I think the commenting system stripped out the image map. Drop me an email on doogal[at]doogal[dot]co[dot]uk and I'll have a look
Anonymous
There's an example available at
http://www.doogal.co.uk/zoomable.php
Hi, good script, but, what can you do for people that uses laptop and dont have the wheel to zoom in and out? can this be modified to have a pair of buttons to zoom out and in? thanks
good point, I'll add it to my to Do list
scortwo:"However what it doesn't do is to preserve the image map. "
I had the same issue, but after some digging found that if I removed the width and height attributes from the img tag, this solved the problem.
Wonderful. This is what i really need.
Post a Comment