图片放大镜效果是一种不错的效果,多应用于电子商务、图片展示等网站,给用户带来更好的体验。实现这种效果的代码不少,今天要给大家介绍的是 Cloud Zoom,它是 jQuery 的一个插件。和其他产品相比,Cloud Zoom 具有代码少、功能多、兼容性好等特点,并且支持 Tint、 Soft Focus 和 Inner 三种放大镜模式。
官方地址:http://www.professorcloud.com/mainsite/cloud-zoom.htm
放大镜参数设置
参数 | 描述 | 默认值 |
---|---|---|
zoomWidth | 放大镜窗口的宽度,如果是默认值,则和小图片一样。不需要单位,有单位会出错 | 'auto' |
zoomHeight | 放大镜窗口的高度,如果是默认值,则和小图片一样。不需要单位,有单位会出错 | 'auto' |
position | 放大镜窗口的位置,可选 left 、 right 、 top 、 bottom ,也可以指定某个 ID,如 position: 'element1' | 'right' |
adjustX | 距离小图片的水平位置。不需要单位,有单位会出错 | 0 |
adjustY | 距离小图片的垂直位置。不需要单位,有单位会出错 | 0 |
tint | 非放大区域的颜色,必须是十六进制颜色,如 '#aa00aa',不能和 softFocus 一起使用 | false |
tintOpacity | 不透明度,0 是完全透明,1 是完全不透明 | 0.5 |
lensOpacity | 镜头鼠标指针不透明度,0 是完全透明,1 是完全不透明,在 tint 和 softFocus 模式下始终透明 | 0.5 |
softFocus | 微微的模糊效果,可选 true 或 false,不能和 tint 一起使用 | false |
smoothMove | 放大区域图片移动的平滑度,数字越高越平滑,为 1 则不平滑 | 3 |
showTitle | 显示图片标题,可选 true 或 false | true |
titleOpacity | 标题不透明度,0 是完全透明,1 是完全不透明 | 0.5 |
通过rel给js传值输出不同的放大镜控制代码
常用写法:赋值 class="cloud-zoom"
Inner写法:rel="position:'inside',showTitle: false"
需注意:
- rel 属性中涉及到数值的都不要单位,否则插件则运行不了
- rel 的最后一个属性值后面不要逗号,否则 IE6 、IE7 下插件运行不了
插件代码:
////////////////////////////////////////////////////////////////////////////////// // Cloud Zoom V1.0.2 // (c) 2010 by R Cecco. <http://www.professorcloud.com> // MIT License // // Please retain this copyright header in all versions of the software ////////////////////////////////////////////////////////////////////////////////// (function ($) { $(document).ready(function () { $('.cloud-zoom, .cloud-zoom-gallery').CloudZoom(); }); function format(str) { for (var i = 1; i < arguments.length; i++) { str = str.replace('%' + (i - 1), arguments[i]); } return str; } function CloudZoom(jWin, opts) { var sImg = $('img', jWin); var img1; var img2; var zoomDiv = null; var $mouseTrap = null; var lens = null; var $tint = null; var softFocus = null; var $ie6Fix = null; var zoomImage; var controlTimer = 0; var cw, ch; var destU = 0; var destV = 0; var currV = 0; var currU = 0; var filesLoaded = 0; var mx, my; var ctx = this, zw; // Display an image loading message. This message gets deleted when the images have loaded and the zoom init function is called. // We add a small delay before the message is displayed to avoid the message flicking on then off again virtually immediately if the // images load really fast, e.g. from the cache. //var ctx = this; setTimeout(function () { // <img src="http://images.cnblogs.com/loading.gif"/> if ($mouseTrap === null) { var w = jWin.width(); jWin.parent().append(format('<div style="%0px;position:absolute;top:75%;left:%1px;text-align:center" class="cloud-zoom-loading" >Loading...</div>', w / 3, (w / 2) - (w / 6))).find(':last').css('opacity', 0.5); } }, 200); var ie6FixRemove = function () { if ($ie6Fix !== null) { $ie6Fix.remove(); $ie6Fix = null; } }; // Removes cursor, tint layer, blur layer etc. this.removeBits = function () { //$mouseTrap.unbind(); if (lens) { lens.remove(); lens = null; } if ($tint) { $tint.remove(); $tint = null; } if (softFocus) { softFocus.remove(); softFocus = null; } ie6FixRemove(); $('.cloud-zoom-loading', jWin.parent()).remove(); }; this.destroy = function () { jWin.data('zoom', null); if ($mouseTrap) { $mouseTrap.unbind(); $mouseTrap.remove(); $mouseTrap = null; } if (zoomDiv) { zoomDiv.remove(); zoomDiv = null; } //ie6FixRemove(); this.removeBits(); // DON'T FORGET TO REMOVE JQUERY 'DATA' VALUES }; // This is called when the zoom window has faded out so it can be removed. this.fadedOut = function () { if (zoomDiv) { zoomDiv.remove(); zoomDiv = null; } this.removeBits(); //ie6FixRemove(); }; this.controlLoop = function () { if (lens) { var x = (mx - sImg.offset().left - (cw * 0.5)) >> 0; var y = (my - sImg.offset().top - (ch * 0.5)) >> 0; if (x < 0) { x = 0; } else if (x > (sImg.outerWidth() - cw)) { x = (sImg.outerWidth() - cw); } if (y < 0) { y = 0; } else if (y > (sImg.outerHeight() - ch)) { y = (sImg.outerHeight() - ch); } lens.css({ left: x, top: y }); lens.css('background-position', (-x) + 'px ' + (-y) + 'px'); destU = (((x) / sImg.outerWidth()) * zoomImage.width) >> 0; destV = (((y) / sImg.outerHeight()) * zoomImage.height) >> 0; currU += (destU - currU) / opts.smoothMove; currV += (destV - currV) / opts.smoothMove; zoomDiv.css('background-position', (-(currU >> 0) + 'px ') + (-(currV >> 0) + 'px')); } controlTimer = setTimeout(function () { ctx.controlLoop(); }, 30); }; this.init2 = function (img, id) { filesLoaded++; //console.log(img.src + ' ' + id + ' ' + img.width); if (id === 1) { zoomImage = img; } //this.images[id] = img; if (filesLoaded === 2) { this.init(); } }; /* Init function start. */ this.init = function () { // Remove loading message (if present); $('.cloud-zoom-loading', jWin.parent()).remove(); /* Add a box (mouseTrap) over the small image to trap mouse events. It has priority over zoom window to avoid issues with inner zoom. We need the dummy background image as IE does not trap mouse events on transparent parts of a div. */ $mouseTrap = jWin.parent().append(format("<div class='mousetrap' style='background-image:url(\".\");z-index:999;position:absolute;%0px;height:%1px;left:%2px;top:%3px;\'></div>", sImg.outerWidth(), sImg.outerHeight(), 0, 0)).find(':last'); ////////////////////////////////////////////////////////////////////// /* Do as little as possible in mousemove event to prevent slowdown. */ $mouseTrap.bind('mousemove', this, function (event) { // Just update the mouse position mx = event.pageX; my = event.pageY; }); ////////////////////////////////////////////////////////////////////// $mouseTrap.bind('mouseleave', this, function (event) { clearTimeout(controlTimer); //event.data.removeBits(); if(lens) { lens.fadeOut(299); } if($tint) { $tint.fadeOut(299); } if(softFocus) { softFocus.fadeOut(299); } zoomDiv.fadeOut(300, function () { ctx.fadedOut(); }); return false; }); ////////////////////////////////////////////////////////////////////// $mouseTrap.bind('mouseenter', this, function (event) { mx = event.pageX; my = event.pageY; zw = event.data; if (zoomDiv) { zoomDiv.stop(true, false); zoomDiv.remove(); } var xPos = opts.adjustX, yPos = opts.adjustY; var siw = sImg.outerWidth(); var sih = sImg.outerHeight(); var w = opts.zoomWidth; var h = opts.zoomHeight; if (opts.zoomWidth == 'auto') { w = siw; } if (opts.zoomHeight == 'auto') { h = sih; } //$('#info').text( xPos + ' ' + yPos + ' ' + siw + ' ' + sih ); var appendTo = jWin.parent(); // attach to the wrapper switch (opts.position) { case 'top': yPos -= h; // + opts.adjustY; break; case 'right': xPos += siw; // + opts.adjustX; break; case 'bottom': yPos += sih; // + opts.adjustY; break; case 'left': xPos -= w; // + opts.adjustX; break; case 'inside': w = siw; h = sih; break; // All other values, try and find an id in the dom to attach to. default: appendTo = $('#' + opts.position); // If dom element doesn't exit, just use 'right' position as default. if (!appendTo.length) { appendTo = jWin; xPos += siw; //+ opts.adjustX; yPos += sih; // + opts.adjustY; } else { w = appendTo.innerWidth(); h = appendTo.innerHeight(); } } zoomDiv = appendTo.append(format('<div id="cloud-zoom-big" class="cloud-zoom-big" style="display:none;position:absolute;left:%0px;top:%1px;%2px;height:%3px;background-image:url(\'%4\');z-index:99;"></div>', xPos, yPos, w, h, zoomImage.src)).find(':last'); // Add the title from title tag. if (sImg.attr('title') && opts.showTitle) { zoomDiv.append(format('<div class="cloud-zoom-title">%0</div>', sImg.attr('title'))).find(':last').css('opacity', opts.titleOpacity); } // Fix ie6 select elements wrong z-index bug. Placing an iFrame over the select element solves the issue... if ($.browser.msie && $.browser.version < 7) { $ie6Fix = $('<iframe frameborder="0" src="#"></iframe>').css({ position: "absolute", left: xPos, top: yPos, zIndex: 99, w, height: h }).insertBefore(zoomDiv); } zoomDiv.fadeIn(500); if (lens) { lens.remove(); lens = null; } /* Work out size of cursor */ cw = (sImg.outerWidth() / zoomImage.width) * zoomDiv.width(); ch = (sImg.outerHeight() / zoomImage.height) * zoomDiv.height(); // Attach mouse, initially invisible to prevent first frame glitch lens = jWin.append(format("<div class = 'cloud-zoom-lens' style='display:none;z-index:98;position:absolute;%0px;height:%1px;'></div>", cw, ch)).find(':last'); $mouseTrap.css('cursor', lens.css('cursor')); var noTrans = false; // Init tint layer if needed. (Not relevant if using inside mode) if (opts.tint) { lens.css('background', 'url("' + sImg.attr('src') + '")'); $tint = jWin.append(format('<div style="display:none;position:absolute; left:0px; top:0px; %0px; height:%1px; background-color:%2;" />', sImg.outerWidth(), sImg.outerHeight(), opts.tint)).find(':last'); $tint.css('opacity', opts.tintOpacity); noTrans = true; $tint.fadeIn(500); } if (opts.softFocus) { lens.css('background', 'url("' + sImg.attr('src') + '")'); softFocus = jWin.append(format('<div style="position:absolute;display:none;top:2px; left:2px; %0px; height:%1px;" />', sImg.outerWidth() - 2, sImg.outerHeight() - 2, opts.tint)).find(':last'); softFocus.css('background', 'url("' + sImg.attr('src') + '")'); softFocus.css('opacity', 0.5); noTrans = true; softFocus.fadeIn(500); } if (!noTrans) { lens.css('opacity', opts.lensOpacity); } if ( opts.position !== 'inside' ) { lens.fadeIn(500); } // Start processing. zw.controlLoop(); return; // Don't return false here otherwise opera will not detect change of the mouse pointer type. }); }; img1 = new Image(); $(img1).load(function () { ctx.init2(this, 0); }); img1.src = sImg.attr('src'); img2 = new Image(); $(img2).load(function () { ctx.init2(this, 1); }); img2.src = jWin.attr('href'); } $.fn.CloudZoom = function (options) { // IE6 background image flicker fix try { document.execCommand("BackgroundImageCache", false, true); } catch (e) {} this.each(function () { var relOpts, opts; // Hmm...eval...slap on wrist. eval('var a = {' + $(this).attr('rel') + '}'); relOpts = a; if ($(this).is('.cloud-zoom')) { $(this).css({ 'position': 'relative', 'display': 'block' }); $('img', $(this)).css({ 'display': 'block' }); // Wrap an outer div around the link so we can attach things without them becoming part of the link. // But not if wrap already exists. if ($(this).parent().attr('id') != 'wrap') { $(this).wrap('<div id="wrap" style="top:0px;z-index:9999;position:relative;"></div>'); } opts = $.extend({}, $.fn.CloudZoom.defaults, options); opts = $.extend({}, opts, relOpts); $(this).data('zoom', new CloudZoom($(this), opts)); } else if ($(this).is('.cloud-zoom-gallery')) { opts = $.extend({}, relOpts, options); $(this).data('relOpts', opts); $(this).bind('click', $(this), function (event) { var data = event.data.data('relOpts'); // Destroy the previous zoom $('#' + data.useZoom).data('zoom').destroy(); // Change the biglink to point to the new big image. $('#' + data.useZoom).attr('href', event.data.attr('href')); // Change the small image to point to the new small image. $('#' + data.useZoom + ' img').attr('src', event.data.data('relOpts').smallImage); // Init a new zoom with the new images. $('#' + event.data.data('relOpts').useZoom).CloudZoom(); return false; }); } }); return this; }; $.fn.CloudZoom.defaults = { zoomWidth: 'auto', zoomHeight: 'auto', position: 'right', tint: false, tintOpacity: 0.5, lensOpacity: 0.5, softFocus: false, smoothMove: 3, showTitle: true, titleOpacity: 0.5, adjustX: 0, adjustY: 0 }; })(jQuery);
代码分析中
IE6中有小BUG,显示的位置会被白色div遮住。
解决中...