Skip to content

Fancybox with fancier product zooming

Product Zooming using FancyboxFancybox is a popular open-source javascript lightboxing library, used in many contexts, including product presentation. I recently had a client request image zooming functionality to be included in their site’s shopping cart. The pages already used Fancybox to show the products, but Fancybox’s default behavior is to open new images and resize them to fit the containing element, whose size is in turn determined by the size of the viewport. The client required a detailed view instead, in a way that would allow the user to navigate around the image. After looking around the internets I did not find a library or addon that satisfied that criteria, but I did manage to extend Fancybox easily, thanks to the decently designed API it offers. Here is how I did it:

Step 1: Overriding default styles

We will redefine a few styles, overriding the default resizing behavior. To avoid screwing up things elsewhere in the application, we will prepend a custom selector in our special zooming lightbox. Thankfully, Fancybox gives us an easy way to do that as you can see in the next section.

/* we want the close icon inside the container */
.productviewer .fancybox-close {top:2px; right:2px;}
/* the transition smooths image navigation, or our eyes would water */
.productviewer .fancybox-image {
  width: auto;
  height: auto;
  cursor:move;
  transition: top 0.2s, left 0.2s;
  -webkit-transition: top 0.2s, left 0.2s;
}
.productviewer .fancybox-inner {overflow: hidden;}

Don’t forget that these styles should be loaded after the default stylesheets, or else the overrides will fail.

Step 2: Customize the javascript call

We will use the afterShow attribute to hook our custom logic to each lightboxed image.

$(document).ready(function() {
  if ($('.my-image-class'.length != 0)) {
    $(".my-image-class").fancybox({
      prevEffect: 'none',
      nextEffect: 'none',
      padding: 0, // padding and curvy borders are, like, so 2009
      margin: 0,
      minWidth: 480, // You may want to tweak this depending on your application
      autoScale: false,
      wrapCSS: 'productviewer', // allows us to use custom styles
      // Initialize extended product view
      afterShow : function() {
        // make image nagivation smaller, takes too much space
        $(".fancybox-next").css('width',40);
        $(".fancybox-prev").css('width',40);
        
        // determine original image size
        var img = $("img.fancybox-image");
        // We determine the actual image size by initializing a new image element
        // and retrieving its dimensions
        var t = new Image();
        t.src = (img.getAttribute ? img.getAttribute("src") : false) || img.src;
        var fullW = img.width();
        var fullH = img.height();
        
        // determine visible container height
        var containerW = $('.fancybox-inner').width();
        var containerH = $('.fancybox-inner').height();
        
        // Position the element in the centre of the container
        img.css({
          position: 'absolute',
          top: -((img.height() / 2)) + (containerH / 2),
          left: -((img.width() / 2)) + (containerW / 2)
        });
        
        
        // Hook up mousemove to scroll the image accordingly
        $(".fancybox-image").mousemove(function(e){
          var mouseX = e.pageX - img.offset().left; 
          var mouseY = e.pageY - img.offset().top;
          // determine the new position based on cursor position
          var posX = (Math.round((mouseX/fullW)*100)/100) *  (fullW-containerW);
          var posY = (Math.round((mouseY/fullH)*100)/100) * (fullHeight-containerH);
          // perform a scroll if we are within bounds.
          if (posX + containerW <= fullW)
            img.css({'left': '-' + posX + 'px'})
          if (posY + containerH <= fullHeight)
            img.css({'top': '-' + posY + 'px'})
        });
      }
    });
  };
});

You can view a working example of this script on this page.

Categories: Code.

Tags: , , ,

Comment Feed

One Response

  1. Awesome. I lost half a day to find a similar solution. Nice coding.

    Only one suggestion, would be nice if you add + / – button for zoom in/zoom out. :)

    Cheers.



Some HTML is OK

or, reply to this post via trackback.