说实话Magnify图片查看器插件已经非常强大了,媲美Windows的图片查看器,但是,毕竟是开源插件,用起来简单,就是兼容性等各种bug问题。不过还好能用,自己优化一下就好。
在实际项目中,如果只是在页面简单的实现这个图片预览、放大、翻看等功能,这个插件就很完美了。废话不多说,看看简单的应用。
API应用案例:http://www.jq22.com/jquery-info17547
Git源码:https://github.com/nzbin/magnify
1.首先看页面部分:
1)前端引用:(第一行为图标样式,第二行为默认样式,第三行是我写的自定义样式(可不用))
<link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> <link rel="stylesheet" href="<%=path%>/static/common/magnify/dist/jquery.magnify.min.css" > <link rel="stylesheet" href="<%=path%>/static/common/magnify/docs/css/self-black-theme.css" >
<script type="text/javascript" src="<%=path%>/static/common/magnify/dist/jquery.magnify.js"></script>
放大镜样式:
/*放大镜样式*/ /*Lets create the magnifying glass*/ .magnify-large {width: 132px; height: 132px;position: absolute;border-radius: 100%;z-index: 20;/*Multiple box shadows to achieve the glass effect*/ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.85),0 0 4px 4px rgba(0, 0, 0, 0.25),inset 0 0 10px 2px rgba(0, 0, 0, 0.25);/*Lets load up the large image first*/ /*background: url('./img/1.jpg') no-repeat;*/ /*hide the glass by default*/ display: none; }
2)jsp页面标签引入:(默认在界面插入一个无图显示的图片,data-src存的大图,src存的小图,不过这里大小一样)
<div id="passImg" style="display: none;" ><img data-show="default" data-caption="暂无图片" data-src="<%=path%>/static/images/notExistImg.jpg" src="<%=path%>/static/images/notExistImg.jpg"> </div>
2.js引用部分:
1)初始化图片查看器:
var options = {footToolbar: ['zoomIn','zoomOut','prev',//'fullscreen', 'next',//'actualSize', 'rotateLeft','rotateRight' ],i18n: {maximize: '',close: '',zoomIn: '放大',zoomOut: '缩小',prev: '上图',next: '下图',// fullscreen: '全屏查看', // actualSize: 'actual-size(Ctrl+Alt+0)', rotateLeft: '左旋转',rotateRight: '右旋转' },title: true,resizable: false,multiInstances: false,initEvent: 'click',initAnimation: true,fixedModalPos: false,fixedModalSize:true,showMagnify:true }
$(function() {//初始化图片查看插件 $('#passImg img').magnify(options); });
2)触发查询对应记录的照片路径(支持多张显示,因为初始化查看器的有多张,所以每一张都要放入magnify容器):
//出入车图片弹窗 function getImg(imgUnid,dealerId) {var url =path + "/query/parkRecord/image";//清理原图片缓存 $('[data-show=add]').remove();$.ajax({url : url,data : {"imgUnid" : imgUnid,"dealerId" : dealerId},type : "post",dataType : "json",success : function(returnData) {var imgObjectList=returnData.imgObjectList;if (null != returnData&&imgObjectList.length>0) {for(var i=0,j=1; i<imgObjectList.length;i++,j++){if (null != imgObjectList[i]&&null != imgObjectList[i].imgUrl && "" !=imgObjectList[i].imgUrl && imgObjectList[i].imgUrl != "null") {$("#passImg").append('<img data-show="add" data-caption="图'+j+'(共'+imgObjectList.length+'张)" data-src="'+imgObjectList[i].imgUrl+'" src="'+imgObjectList[i].imgUrl+'" >');}}
//初始化新增的图片对象 $('[data-show=add]').magnify(options);} }, complete : function() { if( $( '[ data-show =add]'). length> 0){ $( '[ data-show =add]'). first(). click(); } else{ $( '#passImg img '). magnify( options); $( '[ data-show =default]'). click(); } } });}
3)完整对jquery.magnify.js进行改造,代码贴出如下:
; (function(factory) {if (typeof define === 'function' && define.amd) {// AMD. Register as anonymous module. define(['jquery'], factory);} else if (typeof exports === 'object') {// Node / CommonJS factory(require('jquery'));} else {// Browser globals. factory(jQuery);} })(function($) {'use strict';/** * Private Static Constants */ var CLICK_EVENT = 'click',RESIZE_EVENT = 'resize',KEYDOWN_EVENT = 'keydown',WHEEL_EVENT = 'wheel mousewheel DOMMouseScroll',TOUCH_START_EVENT = supportTouch() ? 'touchstart' : 'mousedown',TOUCH_MOVE_EVENT = supportTouch() ? 'touchmove' : 'mousemove',TOUCH_END_EVENT = supportTouch() ? 'touchend' : 'mouseup',EVENT_NS = '.magnify';/** * Private Vars */ var $W = $(window),$D = $(document),// plugin default options defaults = {draggable: true,resizable: true,movable: true,keyboard: true,title: true,modalWidth: 320,modalHeight: 320,fixedContent: true,fixedModalSize: false,initMaximized: false,gapThreshold: 0.02,ratioThreshold: 0.1,minRatio: 0.1,maxRatio: 16,headToolbar: ['maximize','close' ],footToolbar: ['zoomIn','zoomOut','prev','fullscreen','next','actualSize','rotateRight' ],icons: {minimize: 'fa fa-window-minimize',maximize: 'fa fa-window-maximize',close: 'fa fa-close',zoomIn: 'fa fa-search-plus',zoomOut: 'fa fa-search-minus',prev: 'fa fa-arrow-left',next: 'fa fa-arrow-right',fullscreen: 'fa fa-photo',actualSize: 'fa fa-arrows-alt',rotateLeft: 'fa fa-rotate-left',rotateRight: 'fa fa-rotate-right',loader: 'fa fa-spinner fa-pulse' },// lang: 'en', i18n: {minimize: 'minimize',maximize: 'maximize',close: 'close',zoomIn: 'zoom-in(+)',zoomOut: 'zoom-out(-)',prev: 'prev(←)',next: 'next(→)',fullscreen: 'fullscreen',actualSize: 'actual-size(Ctrl+Alt+0)',rotateLeft: 'rotate-left(Ctrl+,)',rotateRight: 'rotate-right(Ctrl+.)' },multiInstances: true,initEvent: 'click',initAnimation: true,fixedModalPos: false,showMagnify:false // beforeOpen:$.noop, // afterOpen:$.noop, // beforeClose:$.noop, // afterClose:$.noop },// jquery element of calling plugin jqEl = null,// image moving flag isMoving = false,// modal resizing flag isResizing = false,// modal open flag isOpened = false,// modal maximize flag isMaximized = false,// image rotate 90*(2n+1) flag isRotated = false,// image rotate angle rotateAngle = 0;/** * Magnify Class */ var Magnify = function (el, options) {var self = this;this.options = $.extend(true, {}, defaults, options);if (options && $.isArray(options.footToolbar)) {this.options.footToolbar = options.footToolbar;}if (options && $.isArray(options.headToolbar)) {this.options.headToolbar = options.headToolbar;}// As we have multiple instances, // so every instance has following variables. this.isOpened = false;this.isMaximized = false;this.isRotated = false;this.rotateAngle = 0;// Store image data in every instance this.imageData = {};// Store modal data in every instance this.modalData = {width: null,height: null,left: null,top: null };this.init(el, self.options);};/** * Mangify Prototype */ Magnify.prototype = {init: function (el, options) {// Get image src var imgSrc = this.getImgSrc(el);// Get image group this.groupName = null;var currentGroupName = $(el).attr('data-group'),groupList = $D.find('[data-group="' + currentGroupName + '"]');if (currentGroupName !== undefined) {this.groupName = currentGroupName;this.getImgGroup(groupList, imgSrc);} else {this.getImgGroup(jqEl.not('[data-group]'), imgSrc);}this.open();this.loadImg(imgSrc);//是否显示图片的放大镜效果 supportShowMagnify(!this.options.initMaximized);if (this.options.showMagnify) {this.showMagnify(this.$stage, this.$image);}// draggable & movable & resizable if (this.options.draggable) {this.draggable(this.$magnify, this.$magnify, '.magnify-button');}if (this.options.movable) {this.movable(this.$stage, this.$image);}if (this.options.resizable) {this.resizable(this.$magnify, this.$stage, this.$image, this.options.modalWidth, this.options.modalHeight);}},creatBtns: function (toolbar, btns) {var btnsStr = '';$.each(toolbar, function (index, item) {btnsStr += btns[item];});return btnsStr;},creatTitle: function () {return (this.options.title ? '<div class="magnify-title"></div>' : '');},creatDOM: function () {var btnsTpl = {minimize: '<button class="magnify-button magnify-button-minimize" title="' + this.options.i18n.minimize + '">\ <i class="' + this.options.icons.minimize + '" aria-hidden="true"></i>\ </button>',maximize: '<button class="magnify-button magnify-button-maximize" title="' + this.options.i18n.maximize + '">\ <i class="' + this.options.icons.maximize + '" aria-hidden="true"></i>\ </button>',close: '<button class="magnify-button magnify-button-close" title="' + this.options.i18n.close + '">\ <i class="' + this.options.icons.close + '" aria-hidden="true"></i>\ </button>',zoomIn: '<button class="magnify-button magnify-button-zoom-in" title="' + this.options.i18n.zoomIn + '">\ <i class="' + this.options.icons.zoomIn + '" aria-hidden="true"></i>\ </button>',zoomOut: '<button class="magnify-button magnify-button-zoom-out" title="' + this.options.i18n.zoomOut + '">\ <i class="' + this.options.icons.zoomOut + '" aria-hidden="true"></i>\ </button>',prev: '<button class="magnify-button magnify-button-prev" title="' + this.options.i18n.prev + '">\ <i class="' + this.options.icons.prev + '" aria-hidden="true"></i>\ </button>',next: '<button class="magnify-button magnify-button-next" title="' + this.options.i18n.next + '">\ <i class="' + this.options.icons.next + '" aria-hidden="true"></i>\ </button>',fullscreen: '<button class="magnify-button magnify-button-fullscreen" title="' + this.options.i18n.fullscreen + '">\ <i class="' + this.options.icons.fullscreen + '" aria-hidden="true"></i>\ </button>',actualSize: '<button class="magnify-button magnify-button-actual-size" title="' + this.options.i18n.actualSize + '">\ <i class="' + this.options.icons.actualSize + '" aria-hidden="true"></i>\ </button>',rotateLeft: '<button class="magnify-button magnify-button-rotate-left" title="' + this.options.i18n.rotateLeft + '">\ <i class="' + this.options.icons.rotateLeft + '" aria-hidden="true"></i>\ </button>',rotateRight: '<button class="magnify-button magnify-button-rotate-right" title="' + this.options.i18n.rotateRight + '">\ <i class="' + this.options.icons.rotateRight + '" aria-hidden="true"></i>\ </button>' };// magnify base HTML var magnifyHTML = '<div class="magnify-modal">\ <div class="magnify-header">\ <div class="magnify-toolbar">' + this.creatBtns(this.options.headToolbar, btnsTpl) + '</div>' + this.creatTitle() + '\ </div>\ <div class="magnify-stage">\ <div class="magnify-large"></div>\ <img class="magnify-image" src="" alt="" />\ </div>\ <div class="magnify-footer">\ <div class="magnify-toolbar">' + this.creatBtns(this.options.footToolbar, btnsTpl) + '</div>\ </div>\ </div>';return magnifyHTML;},open: function () {if (!this.options.multiInstances) {$('.magnify-modal').eq(0).remove();}// Fixed modal position bug if (!$('.magnify-modal').length && this.options.fixedContent) {$('html').css({ 'overflow': 'hidden' });if (hasScrollbar()) {var scrollbarWidth = getScrollbarWidth();if (scrollbarWidth) {$('html').css({ 'padding-right': scrollbarWidth });}}}this.build();this.addEvent();this.setModalPos(this.$magnify);},build: function () {// Create magnify HTML string var magnifyHTML = this.creatDOM();// Make magnify HTML string to jQuery element var $magnify = $(magnifyHTML);// Get all magnify element this.$magnify = $magnify;this.$header = $magnify.find('.magnify-header');this.$stage = $magnify.find('.magnify-stage').addClass('stage-ready');this.$title = $magnify.find('.magnify-title');this.$image = $magnify.find('.magnify-image').addClass('image-ready');this.$close = $magnify.find('.magnify-button-close');this.$maximize = $magnify.find('.magnify-button-maximize');this.$minimize = $magnify.find('.magnify-button-minimize');this.$zoomIn = $magnify.find('.magnify-button-zoom-in');this.$zoomOut = $magnify.find('.magnify-button-zoom-out');this.$actualSize = $magnify.find('.magnify-button-actual-size');this.$fullscreen = $magnify.find('.magnify-button-fullscreen');this.$rotateLeft = $magnify.find('.magnify-button-rotate-left');this.$rotateRight = $magnify.find('.magnify-button-rotate-right');this.$prev = $magnify.find('.magnify-button-prev');this.$next = $magnify.find('.magnify-button-next');this.$large = $magnify.find('.magnify-large');$('body').append($magnify);},close: function (el) {// Remove instance this.$magnify.remove();this.isOpened = false;this.isMaximized = false;this.isRotated = false;this.rotateAngle = 0;// Fixed modal position bug if (!$('.magnify-modal').length && this.options.fixedContent) {$('html').css({ 'overflow': '', 'padding-right': '' });}// off events if (!$('.magnify-modal').length) {$D.off(KEYDOWN_EVENT + EVENT_NS);$W.off(RESIZE_EVENT + EVENT_NS);}},setModalPos: function (modal) {var winWidth = $W.width(),winHeight = $W.height(),scrollLeft = $D.scrollLeft(),scrollTop = $D.scrollTop();var modalWidth = this.options.modalWidth,modalHeight = this.options.modalHeight;// Set modal maximized when init if (this.options.initMaximized) {modal.addClass('magnify-maximize');modal.css({width: '100%',height: '100%',left: 0,top: 0 });this.isOpened = true;this.isMaximized = true;} else {// Make the modal in windows center modal.css({width: modalWidth,height: modalHeight,left: (winWidth - modalWidth) / 2 + scrollLeft + 'px',top: (winHeight - modalHeight) / 2 + scrollTop + 'px' });}supportShowMagnify(!this.options.initMaximized);},setModalSize: function (img) {var self = this,winWidth = $W.width(),winHeight = $W.height(),scrollLeft = $D.scrollLeft(),scrollTop = $D.scrollTop();// stage css value var stageCSS = {left: this.$stage.css('left'),right: this.$stage.css('right'),top: this.$stage.css('top'),bottom: this.$stage.css('bottom'),borderLeft: this.$stage.css('border-left-width'),borderRight: this.$stage.css('border-right-width'),borderTop: this.$stage.css('border-top-width'),borderBottom: this.$stage.css('border-bottom-width')};// Modal size should calc with stage css value var modalWidth = img.width + getNumFromCSSValue(stageCSS.left) + getNumFromCSSValue(stageCSS.right) +getNumFromCSSValue(stageCSS.borderLeft) + getNumFromCSSValue(stageCSS.borderRight),modalHeight = img.height + getNumFromCSSValue(stageCSS.top) + getNumFromCSSValue(stageCSS.bottom) +getNumFromCSSValue(stageCSS.borderTop) + getNumFromCSSValue(stageCSS.borderBottom);var gapThreshold = (this.options.gapThreshold > 0 ? this.options.gapThreshold : 0) + 1,// modal scale to window scale = Math.min(winWidth / (modalWidth * gapThreshold), winHeight / (modalHeight * gapThreshold), 1);var minWidth = Math.max(modalWidth * scale, this.options.modalWidth),minHeight = Math.max(modalHeight * scale, this.options.modalHeight);minWidth = this.options.fixedModalSize ? this.options.modalWidth : Math.round(minWidth);minHeight = this.options.fixedModalSize ? this.options.modalHeight : Math.round(minHeight);var modalCSSObj = {width: minWidth + 'px',height: minHeight + 'px',left: (winWidth - minWidth) / 2 + scrollLeft + 'px',top: (winHeight - minHeight) / 2 + scrollTop + 'px' };// Add modal init animation if (this.options.initAnimation) {this.$magnify.animate(modalCSSObj, function () {self.setImageSize(img);});} else {this.$magnify.css(modalCSSObj);this.setImageSize(img);}this.isOpened = true;},setImageSize: function (img) {var stageData = {w: this.$stage.width(),h: this.$stage.height()};// image scale to stage var scale = 1;if (!this.isRotated) {scale = Math.min(stageData.w / img.width, stageData.h / img.height, 1);} else {scale = Math.min(stageData.w / img.height, stageData.h / img.width, 1);}this.$image.css({width: Math.ceil(img.width * scale) + 'px',height: Math.ceil(img.height * scale) + 'px',left: (stageData.w - Math.ceil(img.width * scale)) / 2 + 'px',top: (stageData.h - Math.ceil(img.height * scale)) / 2 + 'px' });// Store image initial data $.extend(this.imageData, {width: img.width * scale,height: img.height * scale,left: (stageData.w - img.width * scale) / 2,top: (stageData.h - img.height * scale) / 2 });// Set grab cursor setGrabCursor({ w: this.$image.width(), h: this.$image.height() },{ w: this.$stage.width(), h: this.$stage.height() },this.$stage,this.isRotated );// loader end this.$magnify.find('.magnify-loader').remove();// Add image init animation if (this.options.initAnimation) {this.$image.fadeIn();}},loadImg: function (imgSrc) {var self = this;var loaderHTML = '<div class="magnify-loader"><i class="' + this.options.icons.loader + '"></i></div>';// loader start this.$magnify.append(loaderHTML);if (this.options.initAnimation) {this.$image.hide();}this.$image.attr('src', imgSrc);preloadImg(imgSrc, function (img) {// Store original data self.imageData = {originalWidth: img.width,originalHeight: img.height };if (self.isMaximized || (self.isOpened && self.options.fixedModalPos)) {self.setImageSize(img);} else {self.setModalSize(img);}self.$stage.removeClass('stage-ready');self.$image.removeClass('image-ready');}, function () {// loader end self.$magnify.find('.magnify-loader').remove();});if (this.options.title) {this.setImgTitle(imgSrc);}},getImgGroup: function (list, imgSrc) {var self = this;self.groupData = [];$(list).each(function (index, item) {var src = self.getImgSrc(this);self.groupData.push({src: src,caption: $(this).attr('data-caption')});// Get image index if (imgSrc === src) {self.groupIndex = index;}});},setImgTitle: function (url) {var index = this.groupIndex,caption = this.groupData[index].caption,caption = caption ? caption : getImageNameFromUrl(url);this.$title.text(caption);},getImgSrc: function (el) {// Get data-src as image src at first var src = $(el).attr('data-src') ? $(el).attr('data-src') : $(el).attr('href');return src;},jump: function (index) {this.groupIndex = this.groupIndex + index;this.jumpTo(this.groupIndex);},jumpTo: function (index) {index = index % this.groupData.length;if (index >= 0) {index = index % this.groupData.length;} else if (index < 0) {index = (this.groupData.length + index) % this.groupData.length;}this.groupIndex = index;this.loadImg(this.groupData[index].src);if (this.isMaximized) {//去除放大镜显示效果 this.$large.removeClass('magnify-large');}else{//给large赋背景图 this.showMagnify(this.$stage, this.$image);}},wheel: function (e) {e.preventDefault();var delta = 1;if (e.originalEvent.deltaY) {delta = e.originalEvent.deltaY > 0 ? 1 : -1;} else if (e.originalEvent.wheelDelta) {delta = -e.originalEvent.wheelDelta / 120;} else if (e.originalEvent.detail) {delta = e.originalEvent.detail > 0 ? 1 : -1;}// ratio threshold var ratio = -delta * this.options.ratioThreshold;// mouse point position relative to stage var pointer = {x: e.originalEvent.clientX - this.$stage.offset().left + $D.scrollLeft(),y: e.originalEvent.clientY - this.$stage.offset().top + $D.scrollTop()};this.zoom(ratio, pointer, e);},zoom: function (ratio, origin, e) {// zoom out & zoom in ratio = ratio < 0 ? (1 / (1 - ratio)) : (1 + ratio);if (ratio > 0.95 && ratio < 1.05) {ratio = 1;}ratio = this.$image.width() / this.imageData.originalWidth * ratio;// min image size ratio = Math.max(ratio, this.options.minRatio);// max image size ratio = Math.min(ratio, this.options.maxRatio);this.zoomTo(ratio, origin, e);},zoomTo: function (ratio, origin, e) {var $image = this.$image,$stage = this.$stage,imgData = {w: this.imageData.width,h: this.imageData.height,x: this.imageData.left,y: this.imageData.top };// image stage position // We will use it to calc the relative position of image var stageData = {w: $stage.width(),h: $stage.height(),x: $stage.offset().left,y: $stage.offset().top };var newWidth = this.imageData.originalWidth * ratio,newHeight = this.imageData.originalHeight * ratio,// Think about it for a while ~~~ newLeft = origin.x - (origin.x - imgData.x) / imgData.w * newWidth,newTop = origin.y - (origin.y - imgData.y) / imgData.h * newHeight;// δ is the difference between image new width and new height var δ = !this.isRotated ? 0 : (newWidth - newHeight) / 2,imgNewWidth = !this.isRotated ? newWidth : newHeight,imgNewHeight = !this.isRotated ? newHeight : newWidth;var offsetX = stageData.w - newWidth,offsetY = stageData.h - newHeight;// zoom out & zoom in condition // It's important and it takes me a lot of time to get it // The conditions with image rotate 90 degree drive me crazy alomst! if (imgNewHeight <= stageData.h) {newTop = (stageData.h - newHeight) / 2;} else {newTop = newTop > δ ? δ : (newTop > (offsetY - δ) ? newTop : (offsetY - δ));}if (imgNewWidth <= stageData.w) {newLeft = (stageData.w - newWidth) / 2;} else {newLeft = newLeft > -δ ? -δ : (newLeft > (offsetX + δ) ? newLeft : (offsetX + δ));}$image.css({width: Math.round(newWidth) + 'px',height: Math.round(newHeight) + 'px',left: Math.round(newLeft) + 'px',top: Math.round(newTop) + 'px' });// Update image initial data $.extend(this.imageData, {width: newWidth,height: newHeight,left: newLeft,top: newTop });// Set grab cursor setGrabCursor({ w: Math.round(imgNewWidth), h: Math.round(imgNewHeight) },{ w: stageData.w, h: stageData.h },this.$stage );},rotate: function (angle) {this.rotateAngle = this.rotateAngle + angle;if ((this.rotateAngle / 90) % 2 === 0) {this.isRotated = false;} else {this.isRotated = true;}this.rotateTo(this.rotateAngle);},rotateTo: function (angle) {var self = this;this.$image.css({transform: 'rotate(' + angle + 'deg)' });this.setImageSize({ width: this.imageData.originalWidth, height: this.imageData.originalHeight });// Remove grab cursor when rotate this.$stage.removeClass('is-grab');},resize: function () {var self = this;var resizeHandler = throttle(function () {if (self.isOpened) {if (self.isMaximized) {self.setImageSize({ width: self.imageData.originalWidth, height: self.imageData.originalHeight });} else {self.setModalSize({ width: self.imageData.originalWidth, height: self.imageData.originalHeight });}}}, 500);return resizeHandler;},maximize: function () {var self = this;if (!this.isMaximized) {//去除放大镜显示效果 this.$large.removeClass('magnify-large');// Store modal data before maximize this.modalData = {width: this.$magnify.width(),height: this.$magnify.height(),left: this.$magnify.offset().left,top: this.$magnify.offset().top };this.$magnify.addClass('magnify-maximize');this.$magnify.css({width: '100%',height: '100%',left: 0,top: 0 });this.isMaximized = true;} else {//增加放大镜显示效果 this.$large.addClass('magnify-large');this.$magnify.removeClass('magnify-maximize');this.$magnify.css({width: this.modalData.width ? this.modalData.width : this.options.modalWidth,height: this.modalData.height ? this.modalData.height : this.options.modalHeight,left: this.modalData.left ? this.modalData.left : ($W.width() - this.options.modalWidth) / 2 + $D.scrollLeft(),top: this.modalData.top ? this.modalData.top : ($W.height() - this.options.modalHeight) / 2 + $D.scrollTop()});this.isMaximized = false;}this.setImageSize({ width: this.imageData.originalWidth, height: this.imageData.originalHeight });},fullscreen: function () {requestFullscreen(this.$magnify[0]);},keydown: function (e) {var self = this;if (!this.options.keyboard) {return false;}var keyCode = e.keyCode || e.which || e.charCode,ctrlKey = e.ctrlKey || e.metaKey,altKey = e.altKey || e.metaKey;switch (keyCode) {// ← case 37:self.jump(-1);break;// → case 39:self.jump(1);break;// + case 187:self.zoom(self.options.ratioThreshold * 3, { x: self.$stage.width() / 2, y: self.$stage.height() / 2 }, e);break;// - case 189:self.zoom(-self.options.ratioThreshold * 3, { x: self.$stage.width() / 2, y: self.$stage.height() / 2 }, e);break;// + Firefox case 61:self.zoom(self.options.ratioThreshold * 3, { x: self.$stage.width() / 2, y: self.$stage.height() / 2 }, e);break;// - Firefox case 173:self.zoom(-self.options.ratioThreshold * 3, { x: self.$stage.width() / 2, y: self.$stage.height() / 2 }, e);break;// ctrl + alt + 0 case 48:if (ctrlKey && altKey) {self.zoomTo(1, { x: self.$stage.width() / 2, y: self.$stage.height() / 2 }, e);}break;// ctrl + , case 188:if (ctrlKey) {self.rotate(-90);}break;// ctrl + . case 190:if (ctrlKey) {self.rotate(90);}break;default:}},addEvent: function () {var self = this;this.$close.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function (e) {self.close();});this.$stage.off(WHEEL_EVENT + EVENT_NS).on(WHEEL_EVENT + EVENT_NS, function (e) {self.wheel(e);});this.$zoomIn.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function (e) {self.zoom(self.options.ratioThreshold * 3, { x: self.$stage.width() / 2, y: self.$stage.height() / 2 }, e);});this.$zoomOut.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function (e) {self.zoom(-self.options.ratioThreshold * 3, { x: self.$stage.width() / 2, y: self.$stage.height() / 2 }, e);});this.$actualSize.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function (e) {self.zoomTo(1, { x: self.$stage.width() / 2, y: self.$stage.height() / 2 }, e);});this.$prev.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function () {self.jump(-1);});this.$fullscreen.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function () {self.fullscreen();});this.$next.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function () {self.jump(1);});this.$rotateLeft.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function () {self.rotate(-90);});this.$rotateRight.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function () {self.rotate(90);});this.$maximize.off(CLICK_EVENT + EVENT_NS).on(CLICK_EVENT + EVENT_NS, function () {self.maximize();});$D.off(KEYDOWN_EVENT + EVENT_NS).on(KEYDOWN_EVENT + EVENT_NS, function (e) {self.keydown(e);});$W.on(RESIZE_EVENT + EVENT_NS, self.resize());}};/** * Public Static Functions */ $.magnify = {instance: Magnify.prototype };$.fn.magnify = function (options) {jqEl = $(this);// Convert a numeric string into a number for (var key in options) {if (typeof (options[key]) === 'string' && !isNaN(options[key])) {options[key] = parseFloat(options[key])}}// Get init event, 'click' or 'dblclick' var opts = $.extend(true, {}, defaults, options);if (typeof options === 'string') {// $(this).data('magnify')[options](); } else {if (opts.initEvent === 'dblclick') {jqEl.off('click' + EVENT_NS).on('click' + EVENT_NS, function (e) {e.preventDefault();// This will stop triggering data-api event e.stopPropagation();});}jqEl.off(opts.initEvent + EVENT_NS).on(opts.initEvent + EVENT_NS, function (e) {e.preventDefault();// This will stop triggering data-api event e.stopPropagation();$(this).data('magnify', new Magnify(this, options));});}return jqEl;};/** * MAGNIFY DATA-API */ $D.on(CLICK_EVENT + EVENT_NS, '[data-magnify]', function (e) {jqEl = $('[data-magnify]');e.preventDefault();$(this).data('magnify', new Magnify(this, {}));});/** * [draggable] * @param {[Object]} modal [the modal element] * @param {[Object]} dragHandle [the handle element when dragging] * @param {[Object]} dragCancel [the cancel element when dragging] */ var draggable = function (modal, dragHandle, dragCancel) {var self = this;var isDragging = false;var startX = 0,startY = 0,left = 0,top = 0;var dragStart = function (e) {var e = e || window.event;// e.preventDefault(); // Get clicked button var elemCancel = $(e.target).closest(dragCancel);// Stop modal moving when click buttons if (elemCancel.length) {return true;}isDragging = true;startX = e.type === 'touchstart' ? e.originalEvent.targetTouches[0].pageX : e.clientX;startY = e.type === 'touchstart' ? e.originalEvent.targetTouches[0].pageY : e.clientY;left = $(modal).offset().left;top = $(modal).offset().top;$D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).on(TOUCH_END_EVENT + EVENT_NS, dragEnd);};var dragMove = function (e) {var e = e || window.event;e.preventDefault();if (isDragging && !isMoving && !isResizing && !self.isMaximized) {var endX = e.type === 'touchmove' ? e.originalEvent.targetTouches[0].pageX : e.clientX,endY = e.type === 'touchmove' ? e.originalEvent.targetTouches[0].pageY : e.clientY,relativeX = endX - startX,relativeY = endY - startY;$(modal).css({left: relativeX + left + 'px',top: relativeY + top + 'px' });}};var dragEnd = function (e) {$D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).off(TOUCH_END_EVENT + EVENT_NS, dragEnd);isDragging = false;};$(dragHandle).on(TOUCH_START_EVENT + EVENT_NS, dragStart);};// Add to Magnify Prototype $.extend(Magnify.prototype, {draggable: draggable });/** * -------------------------------------- * 1.no movable * 2.vertical movable * 3.horizontal movable * 4.vertical & horizontal movable * -------------------------------------- * * [image movable] * @param {[Object]} stage [the stage element] * @param {[Object]} image [the image element] */ var movable = function (stage, image) {var self = this;var isDragging = false;var startX = 0,startY = 0,left = 0,top = 0,widthDiff = 0,heightDiff = 0,δ = 0;var dragStart = function (e) {var e = e || window.event;e.preventDefault();var imageWidth = $(image).width(),imageHeight = $(image).height(),stageWidth = $(stage).width(),stageHeight = $(stage).height();startX = e.type === 'touchstart' ? e.originalEvent.targetTouches[0].pageX : e.clientX;startY = e.type === 'touchstart' ? e.originalEvent.targetTouches[0].pageY : e.clientY;// δ is the difference between image width and height δ = !self.isRotated ? 0 : (imageWidth - imageHeight) / 2;// Width or height difference can be use to limit image right or top position widthDiff = !self.isRotated ? (imageWidth - stageWidth) : (imageHeight - stageWidth);heightDiff = !self.isRotated ? (imageHeight - stageHeight) : (imageWidth - stageHeight);// Modal can be dragging if image is smaller to stage isDragging = (widthDiff > 0 || heightDiff > 0) ? true : false;isMoving = (widthDiff > 0 || heightDiff > 0) ? true : false;// Reclac the element position when mousedown // Fixed the issue of stage with a border left = $(image).position().left - δ;top = $(image).position().top + δ;// Add grabbing cursor if (stage.hasClass('is-grab')) {$('html,body,.magnify-modal,.magnify-stage,.magnify-button,.magnify-resizable-handle').addClass('is-grabbing');}$D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).on(TOUCH_END_EVENT + EVENT_NS, dragEnd);};var dragMove = function (e) {var e = e || window.event;e.preventDefault();if (isDragging) {var endX = e.type === 'touchmove' ? e.originalEvent.targetTouches[0].pageX : e.clientX,endY = e.type === 'touchmove' ? e.originalEvent.targetTouches[0].pageY : e.clientY,relativeX = endX - startX,relativeY = endY - startY,newLeft = relativeX + left,newTop = relativeY + top;// vertical limit if (heightDiff > 0) {if ((relativeY + top) > δ) {newTop = δ;} else if ((relativeY + top) < -heightDiff + δ) {newTop = -heightDiff + δ;}} else {newTop = top;}// horizontal limit if (widthDiff > 0) {if ((relativeX + left) > -δ) {newLeft = -δ;} else if ((relativeX + left) < -widthDiff - δ) {newLeft = -widthDiff - δ;}} else {newLeft = left;}$(image).css({left: newLeft + 'px',top: newTop + 'px' });// Update image initial data $.extend(self.imageData, {left: newLeft,top: newTop });}};var dragEnd = function (e) {$D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).off(TOUCH_END_EVENT + EVENT_NS, dragEnd);isDragging = false;isMoving = false;// Remove grabbing cursor $('html,body,.magnify-modal,.magnify-stage,.magnify-button,.magnify-resizable-handle').removeClass('is-grabbing');};$(stage).on(TOUCH_START_EVENT + EVENT_NS, dragStart);};// Add to Magnify Prototype $.extend(Magnify.prototype, {movable: movable });/** * ------------------------------ * 1.modal resizable * 2.keep image in stage center * 3.~ * ------------------------------ * * [resizable] * @param {[Object]} modal [the modal element] * @param {[Object]} stage [the stage element] * @param {[Object]} image [the image element] * @param {[Number]} minWidth [the option of modalWidth] * @param {[Number]} minHeight [the option of modalHeight] */ var resizable = function (modal, stage, image, minWidth, minHeight) {var self = this;var resizableHandleE = $('<div class="magnify-resizable-handle magnify-resizable-handle-e"></div>'),resizableHandleW = $('<div class="magnify-resizable-handle magnify-resizable-handle-w"></div>'),resizableHandleS = $('<div class="magnify-resizable-handle magnify-resizable-handle-s"></div>'),resizableHandleN = $('<div class="magnify-resizable-handle magnify-resizable-handle-n"></div>'),resizableHandleSE = $('<div class="magnify-resizable-handle magnify-resizable-handle-se"></div>'),resizableHandleSW = $('<div class="magnify-resizable-handle magnify-resizable-handle-sw"></div>'),resizableHandleNE = $('<div class="magnify-resizable-handle magnify-resizable-handle-ne"></div>'),resizableHandleNW = $('<div class="magnify-resizable-handle magnify-resizable-handle-nw"></div>');var resizableHandles = {'e': resizableHandleE,'s': resizableHandleS,'se': resizableHandleSE,'n': resizableHandleN,'w': resizableHandleW,'nw': resizableHandleNW,'ne': resizableHandleNE,'sw': resizableHandleSW };$(modal).append(resizableHandleE, resizableHandleW, resizableHandleS, resizableHandleN, resizableHandleSE, resizableHandleSW, resizableHandleNE, resizableHandleNW );var isDragging = false;var startX = 0,startY = 0,modalData = {w: 0,h: 0,l: 0,t: 0 },stageData = {w: 0,h: 0,l: 0,t: 0 },imageData = {w: 0,h: 0,l: 0,t: 0 },// δ is the difference between image width and height δ = 0,imgWidth = 0,imgHeight = 0,direction = '';// modal CSS options var getModalOpts = function (dir, offsetX, offsetY) {// Modal should not move when its width to the minwidth var modalLeft = (-offsetX + modalData.w) > minWidth ? (offsetX + modalData.l) : (modalData.l + modalData.w - minWidth),modalTop = (-offsetY + modalData.h) > minHeight ? (offsetY + modalData.t) : (modalData.t + modalData.h - minHeight);var opts = {'e': {width: Math.max((offsetX + modalData.w), minWidth) + 'px' },'s': {height: Math.max((offsetY + modalData.h), minHeight) + 'px' },'se': {width: Math.max((offsetX + modalData.w), minWidth) + 'px',height: Math.max((offsetY + modalData.h), minHeight) + 'px' },'w': {width: Math.max((-offsetX + modalData.w), minWidth) + 'px',left: modalLeft + 'px' },'n': {height: Math.max((-offsetY + modalData.h), minHeight) + 'px',top: modalTop + 'px' },'nw': {width: Math.max((-offsetX + modalData.w), minWidth) + 'px',height: Math.max((-offsetY + modalData.h), minHeight) + 'px',top: modalTop + 'px',left: modalLeft + 'px' },'ne': {width: Math.max((offsetX + modalData.w), minWidth) + 'px',height: Math.max((-offsetY + modalData.h), minHeight) + 'px',top: modalTop + 'px' },'sw': {width: Math.max((-offsetX + modalData.w), minWidth) + 'px',height: Math.max((offsetY + modalData.h), minHeight) + 'px',left: modalLeft + 'px' }};return opts[dir];};// image CSS options var getImageOpts = function (dir, offsetX, offsetY) {// Image should not move when modal width to the min width // The minwidth is modal width, so we should clac the stage minwidth var widthDiff = (offsetX + modalData.w) > minWidth ? (stageData.w - imgWidth + offsetX - δ) : (minWidth - (modalData.w - stageData.w) - imgWidth - δ),heightDiff = (offsetY + modalData.h) > minHeight ? (stageData.h - imgHeight + offsetY + δ) : (minHeight - (modalData.h - stageData.h) - imgHeight + δ),widthDiff2 = (-offsetX + modalData.w) > minWidth ? (stageData.w - imgWidth - offsetX - δ) : (minWidth - (modalData.w - stageData.w) - imgWidth - δ),heightDiff2 = (-offsetY + modalData.h) > minHeight ? (stageData.h - imgHeight - offsetY + δ) : (minHeight - (modalData.h - stageData.h) - imgHeight + δ);// Get image position in dragging var imgLeft = $(image).position().left - δ,imgTop = $(image).position().top + δ;var opts = {'e': {left: widthDiff >= -δ ? ((widthDiff - δ) / 2 + 'px') : (imgLeft > widthDiff ? (imgLeft + 'px') : (widthDiff + 'px'))},'s': {top: heightDiff >= δ ? ((heightDiff + δ) / 2 + 'px') : (imgTop > heightDiff ? (imgTop + 'px') : (heightDiff + 'px'))},'se': {top: heightDiff >= δ ? ((heightDiff + δ) / 2 + 'px') : (imgTop > heightDiff ? (imgTop + 'px') : (heightDiff + 'px')),left: widthDiff >= -δ ? ((widthDiff - δ) / 2 + 'px') : (imgLeft > widthDiff ? (imgLeft + 'px') : (widthDiff + 'px'))},'w': {left: widthDiff2 >= -δ ? ((widthDiff2 - δ) / 2 + 'px') : (imgLeft > widthDiff2 ? (imgLeft + 'px') : (widthDiff2 + 'px'))},'n': {top: heightDiff2 >= δ ? ((heightDiff2 + δ) / 2 + 'px') : (imgTop > heightDiff2 ? (imgTop + 'px') : (heightDiff2 + 'px'))},'nw': {top: heightDiff2 >= δ ? ((heightDiff2 + δ) / 2 + 'px') : (imgTop > heightDiff2 ? (imgTop + 'px') : (heightDiff2 + 'px')),left: widthDiff2 >= -δ ? ((widthDiff2 - δ) / 2 + 'px') : (imgLeft > widthDiff2 ? (imgLeft + 'px') : (widthDiff2 + 'px'))},'ne': {top: heightDiff2 >= δ ? ((heightDiff2 + δ) / 2 + 'px') : (imgTop > heightDiff2 ? (imgTop + 'px') : (heightDiff2 + 'px')),left: widthDiff >= -δ ? ((widthDiff - δ) / 2 + 'px') : (imgLeft > widthDiff ? (imgLeft + 'px') : (widthDiff + 'px'))},'sw': {top: heightDiff >= δ ? ((heightDiff + δ) / 2 + 'px') : (imgTop > heightDiff ? (imgTop + 'px') : (heightDiff + 'px')),left: widthDiff2 >= -δ ? ((widthDiff2 - δ) / 2 + 'px') : (imgLeft > widthDiff2 ? (imgLeft + 'px') : (widthDiff2 + 'px'))}};return opts[dir];};var dragStart = function (dir, e) {var e = e || window.event;e.preventDefault();isDragging = true;isResizing = true;startX = e.type === 'touchstart' ? e.originalEvent.targetTouches[0].pageX : e.clientX;startY = e.type === 'touchstart' ? e.originalEvent.targetTouches[0].pageY : e.clientY;// Reclac the modal data when mousedown modalData = {w: $(modal).width(),h: $(modal).height(),l: $(modal).offset().left,t: $(modal).offset().top };stageData = {w: $(stage).width(),h: $(stage).height(),l: $(stage).offset().left,t: $(stage).offset().top };imageData = {w: $(image).width(),h: $(image).height(),l: $(image).position().left,t: $(image).position().top };// δ is the difference between image width and height δ = !self.isRotated ? 0 : (imageData.w - imageData.h) / 2;imgWidth = !self.isRotated ? imageData.w : imageData.h;imgHeight = !self.isRotated ? imageData.h : imageData.w;direction = dir;// Add resizable cursor $('html,body,.magnify-modal,.magnify-stage,.magnify-button').css('cursor', dir + '-resize');$D.on(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).on(TOUCH_END_EVENT + EVENT_NS, dragEnd);};var dragMove = function (e) {var e = e || window.event;e.preventDefault();if (isDragging && !self.isMaximized) {var endX = e.type === 'touchmove' ? e.originalEvent.targetTouches[0].pageX : e.clientX,endY = e.type === 'touchmove' ? e.originalEvent.targetTouches[0].pageY : e.clientY,relativeX = endX - startX,relativeY = endY - startY;var modalOpts = getModalOpts(direction, relativeX, relativeY);$(modal).css(modalOpts);var imageOpts = getImageOpts(direction, relativeX, relativeY);$(image).css(imageOpts);}};var dragEnd = function (e) {$D.off(TOUCH_MOVE_EVENT + EVENT_NS, dragMove).off(TOUCH_END_EVENT + EVENT_NS, dragEnd);// Set grab cursor if (isResizing) {setGrabCursor({ w: imgWidth, h: imgHeight }, { w: $(stage).width(), h: $(stage).height() },stage);}isDragging = false;isResizing = false;// Remove resizable cursor $('html,body,.magnify-modal,.magnify-stage,.magnify-button').css('cursor', '');};$.each(resizableHandles, function (dir, handle) {handle.on(TOUCH_START_EVENT + EVENT_NS, function (e) {dragStart(dir, e);});});};// Add to Magnify Prototype $.extend(Magnify.prototype, {resizable: resizable });/** * Private Functions */ /** * [throttle] * @param {Function} fn [description] * @param {[Number]} delay [description] * @return {Function} [description] */ function throttle(fn, delay) {var timer = null;return function() {var context = this,args = arguments;clearTimeout(timer);timer = setTimeout(function() {fn.apply(context, args);}, delay);};}/** * [preloadImg] * @param {[String]} src [image src] * @param {Function} success [callbacks] * @param {Function} error [callbacks] */ function preloadImg(src, success, error) {var img = new Image();img.onload = function() {success(img);};img.onerror = function() {error(img);};img.src = src;}/** * [requestFullscreen] * @param {[type]} element [description] */ function requestFullscreen(element) {if (element.requestFullscreen) {element.requestFullscreen();} else if (element.mozRequestFullScreen) {element.mozRequestFullScreen();} else if (element.webkitRequestFullscreen) {element.webkitRequestFullscreen();} else if (element.msRequestFullscreen) {element.msRequestFullscreen();} }/** * [exitFullscreen] */ function exitFullscreen() {if (document.exitFullscreen) {document.exitFullscreen();} else if (document.mozCancelFullScreen) {document.mozCancelFullScreen();} else if (document.webkitExitFullscreen) {document.webkitExitFullscreen();} }/** * [getImageNameFromUrl] * @param {[String]} url [description] * @return {[String]} [description] */ function getImageNameFromUrl(url) {var reg = /^.*?\/*([^/?]*)\.[a-z]+(\?.+|$)/ig,txt = url.replace(reg, '$1');return txt; }/** * [getNumFromCSSValue] * @param {[String]} value [description] * @return {[Number]} [description] */ function getNumFromCSSValue(value) {var reg = /\d+/g,arr = value.match(reg),num = parseFloat(arr[0]);return num; }/** * [hasScrollbar] * @return {[Boolean]} [description] */ function hasScrollbar() {return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight); }/** * [getScrollbarWidth] * @return {[Number]} [description] */ function getScrollbarWidth() {var scrollDiv = document.createElement('div');scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';document.body.appendChild(scrollDiv);var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;document.body.removeChild(scrollDiv);return scrollbarWidth;}/** * [setGrabCursor] * @param {[Object]} imageData [description] * @param {[Object]} stageData [description] * @param {[Object]} stage [description] * @param {[Boolean]} isRotate [description] */ function setGrabCursor(imageData, stageData, stage, isRotated) {var imageWidth = !isRotated ? imageData.w : imageData.h,imageHeight = !isRotated ? imageData.h : imageData.w;if (imageHeight > stageData.h || imageWidth > stageData.w) {stage.addClass('is-grab');}if (imageHeight <= stageData.h && imageWidth <= stageData.w) {stage.removeClass('is-grab');} }/** * [supportTouch] * @return {[Boolean]} [description] */ function supportTouch(){return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); }//显示放大镜效果 var showMagnify = function (stage, image) {// The native width and height of the image. var defaults = {scaling: 0.3 };// Combines object defaults and options. var options = $.extend(defaults, options),native_width = 0,native_height = 0,current_width = 0,current_height = 0,$small = stage,$large = $(".magnify-large");//给stage新增一个large的div标签 if($large.length<1){$small.append("<div class='magnify-large'></div>");}var $large = $(".magnify-large");//给large赋背景图 $large.css("background-image","url("+image.attr('src')+")");$large.css("background-repeat","no-repeat");$(".magnify-modal").mousemove(function (e) {/* Act on the event */ if (!native_width && !native_height) {var image_object = new Image();image_object.src = image.attr('src');// Gets the image native height and width. native_height = image_object.height;native_width = image_object.width;// Gets the image current height and width. current_height = $small.height();current_width = $small.width();} else {// Gets .maginfy offset coordinates. var magnify_offset = $(this).offset(),// Gets coordinates within .maginfy. mx = e.pageX - magnify_offset.left,my = e.pageY - magnify_offset.top;// Checks the mouse within .maginfy or not. if (mx < $(this).width() && my < $(this).height() && mx >0 && my > 0) {$large.fadeIn(100);} else {$large.fadeOut(100);} if ($large.is(":visible")) {/* Gets the large image coordinate by ratio small.x / small.width = large.x / large.width small.y / small.height = large.y / large.height then we need to keep pointer in the centre, so deduct the half of .large width and height. */ var rx = Math.round(mx / $small.width() * native_width - $large.width() /2) * -1,ry = Math.round(my / $small.height() * native_height - $large.height()/2 ) * -1,bgp = rx + "px " + ry + "px",px = mx - $large.width() / 2,py = my - $large.height() / 2;$large.css({left: px,top: py,backgroundPosition: bgp });}}});};// Add to Magnify Prototype $.extend(Magnify.prototype, {showMagnify: showMagnify });/*是否显示放大镜效果*/ function supportShowMagnify(flag){$(".magnify-large").css("display",function(flag){return flag ? "":"none";});}});
3.不足之处,目前只对maximize、prev、next三个按钮的操作进行放大镜的优化,其他按钮项目没有使用,各位猿友们用的时候需要优化一下就是放大镜只在小尺寸的界面显示,全屏或放大的时候就不需要用放大镜了,而且插件自带zoomIn,zoomOut,很方便;看一下完成后的效果如下:
















