在web项目中,用到js来实现图片的放大缩小功能,在这里是通过zoomify来实现,并在这个基础上进行二次改进,已达到更满意的效果。

1.下面是展示的效果:
在这里插入图片描述
通过对zoomifyjs改进,达到上述效果。

2.下面是具体实现的代码:

var currScale=1;
var currRotate=0;
var currScaleX=0;
var currScaleY=0;
;(function($){
	
	// initialization
	Zoomify = function (element, options) {
		var that = this;		
		this._zooming = false;
		this._zoomed  = false;
		this._timeout = null;
		this._percentTimeout=null;
		this.$shadow  = null;
		this.$newImage = null;
		this.$imgPercent=null;
		this.$image   = $(element).addClass('zoomify');
		this.$imageSrc =$(element).attr('src');
		this.options  = $.extend({}, Zoomify.DEFAULTS, this.$image.data(), options);
		
		this.$image.on('click', function () { that.zoom(); });
		$(window).on('resize', function () { that.reposition(); });
		//$(document).on('mousewheel', function () { that.reposition(); });
		$(window).on('keyup', function (e) { 
			if (that._zoomed && e.keyCode == 27) //退出
				that.zoomOut();
		 });
	};
	Zoomify.DEFAULTS = {
		duration: 200,
		easing:   'linear',
		scale:    0.9
	};
	
	// css utilities
	Zoomify.prototype.transition = function ($element, value) {
		$element.css({
			'-webkit-transition': value,
			'-moz-transition': value,
			'-ms-transition': value,
			'-o-transition': value,
			'transition': value
		});
	};
	Zoomify.prototype.addTransition = function ($element) {
		this.transition($element, 'all ' + this.options.duration + 'ms ' + this.options.easing);
	};
	Zoomify.prototype.removeTransition = function ($element, callback) {
		var that = this;
		
		clearTimeout(this._timeout);
		this._timeout = setTimeout(function () {
			that.transition($element, '');
			if ($.isFunction(callback)) callback.call(that);
		}, this.options.duration);
	};
	Zoomify.prototype.transform = function (value) {
		this.$newImage.css({
			'-webkit-transform': value,
			'-moz-transform': value,
			'-ms-transform': value,
			'-o-transform': value,
			'transform': value
		});
	};
	Zoomify.prototype.transformScaleAndTranslate = function (scale, translateX, translateY, callback) {
		this.addTransition(this.$newImage);
		this.transform('scale(' + scale + ')'); //translate(' + translateX + 'px, ' + translateY + 'px)
		this.$newImage.css("width",translateX+"px").css('height',translateY+"px");
		this.removeTransition(this.$newImage, callback);
	};
	
	// zooming functions
	Zoomify.prototype.zoom = function () {
		if (this._zooming) return;
		
		if (this._zoomed) this.zoomOut();
		else this.zoomIn();
	};
	Zoomify.prototype.zoomIn = function () {
		var that      = this;
			//transform = this.$image.css('transform');
		
		
		//this.transition(this.$image, 'none');
		//this.transform('none');
		
		//this.transform(transform);
		that.addImage();
		var $caleImg=$(".scale_img_div").find('img');
		this.$newImage=$caleImg;
		$caleImg.attr('src',this.$imageSrc);
		$caleImg.addClass('zoomed').trigger('zoom-in.zoomify');
		var transform = $caleImg.css('transform');
		this.transform('none');
		
		//var offset     = this.$newImage.offset(),
		
		width      = this.$newImage.outerWidth(),
		height     = this.$newImage.outerHeight(),
		nWidth     = this.$newImage[0].naturalWidth || +Infinity, //无穷大
		nHeight    = this.$newImage[0].naturalHeight || +Infinity,
		wWidth     = $(window).width(),
		wHeight    = $(window).height(),
		scaleX     = Math.min(nWidth, wWidth * this.options.scale) / width,
		scaleY     = Math.min(nHeight, wHeight * this.options.scale) / height,
		scale      = Math.min(scaleX, scaleY);
		
		var translateX,translateY;
		if(wWidth - width>0){
			translateX = ((wWidth - width) / 2) / scale;			
		}else{
			translateX = ((wWidth - width) / 2);
		}
		if(wHeight - height>0){
			translateY = ((wHeight - height) / 2 )/ scale;
		}else{
			translateY = ((wHeight - height) / 2);
		}
		$caleImg.css('margin-top',translateY+'px').css('margin-left',translateX+'px').css("width","0px").css('height',"0px");
		this._zooming = true;
		//this.$image.addClass('zoomed').trigger('zoom-in.zoomify');	
		this.transform(transform);
		setTimeout(function () {
			that.addShadow();
			currScale=scale;
			currScaleX=scale;
			currScaleY=scale;
			that.transformScaleAndTranslate(scale, width, height, function () {
				that._zooming = false;
				//that.$image.trigger('zoom-in-complete.zoomify');
				$caleImg.trigger('zoom-in-complete.zoomify');
			});
			$('body').addClass('open_viewer');
			$('.scale_img_opt_toolbar').show();
			$('.viewer_zoom_in').off('click').on('click',function(){that.enlargeImage()});
			$('.viewer_zoom_out').off('click').on('click',function(){that.reduceImage()});
			$('.viewer_rotate_left').off('click').on('click',function(){that.rotateLeftImage()});
			$('.viewer_rotate_right').off('click').on('click',function(){that.rotateRightImage()});
			$('.viewer_flip_horizontal').off('click').on('click',function(){that.flipHorizontalImage()});
			$('.viewer_flip_vertical').off('click').on('click',function(){that.flipVerticalImage()});
			$('.viewer_one_to_one').off('click').on('click',function(){that.resetImage()});
			that._zoomed = true;
			$('body').off('mousewheel').on('mousewheel',function(event){
				var delta = 0;
				if (!event) event = window.event;
				var wheelEvent = event.wheelDelta ? event.wheelDelta : event.originalEvent.wheelDelta;
				var wheelEventDetail = event.detail ? event.detail : event.originalEvent.detail;
				if (wheelEvent) {//IE、chrome浏览器使用的是wheelDelta,并且值为“正负120”
					delta = wheelEvent/120; 
					if (window.opera) delta = -delta;//因为IE、chrome等向下滚动是负值,FF是正值,为了处理一致性,在此取反处理
				} else if (wheelEventDetail) {//FF浏览器使用的是detail,其值为“正负3”
					delta = -wheelEventDetail/3;
				}
				if (delta){	
					if(delta>0){
						if(currScale>=20){
							return;
						}
						currScale+=0.05;
						if(currScale>20){
							currScale=20;
						}
					}else{
						if(currScale<=0.03){
							return;
						}
						if(currScale<=0.15){
							currScale-=0.02;
						}else{
							currScale-=0.05;
						}		
					}		
					that.imgScale(event);
				}	
			});
		});
	};
	Zoomify.prototype.zoomOut = function () {
		var that = this;
		
		this._zooming = true;
		//this.$image.trigger('zoom-out.zoomify');
		this.$newImage.trigger('zoom-out.zoomify');
		this.transformScaleAndTranslate(1, 0, 0, function () {
			that._zooming = false;
			that.$image.trigger('zoom-out-complete.zoomify');
			that.$newImage.parent().remove();
			that.$newImage=null;
		});
		this.removeShadow();
		if(this.$imgPercent){
			this.$imgPercent.remove();
			this.$imgPercent=null;
		}
		$('.scale_img_opt_toolbar').hide();
		$('body').removeClass('open_viewer');
		this._zoomed = false;
		currScale=1;
		currRotate=0;
		currScaleX=0;
		currScaleY=0;
	};
	
	// page listener callbacks
	Zoomify.prototype.reposition = function () {
		if (this._zoomed) {
			this.transition(this.$newImage, 'none');
			this.zoomIn();
		}
	};
	Zoomify.prototype.imgScale = function (event) {
		if (this._zoomed) {
			//this.transition(this.$newImage, 'none');
			var nWidth     = this.$newImage[0].naturalWidth || +Infinity, //无穷大
			nHeight    = this.$newImage[0].naturalHeight || +Infinity,
			wWidth     = $(window).width(),
			wHeight    = $(window).height(),
			marginLeft,
			marginTop;
			//每次加5%
			var offset     = this.$newImage.offset();
			if(wWidth - nWidth>0){
				marginLeft = ((wWidth - nWidth) / 2); // currScale;			
			}else{
				marginLeft = (wWidth - nWidth) / 2;
			}
			if(wHeight - nHeight>0){
				marginTop = ((wHeight - nHeight) / 2 );// currScale;
			}else{
				marginTop = (wHeight - nHeight) / 2;
			}		
			this.$newImage.css('margin-top',marginTop+'px').css('margin-left',marginLeft+'px');
			if(currScaleX<0 || currScaleY<0){
				currScaleX=currScaleX<0 ? -currScale : currScale;
				currScaleY=currScaleY<0 ? -currScale : currScale;
				if(currRotate==0){
					this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+')');
				}else{
					this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+') rotate('+currRotate+'deg)');
				}
			}else{
				currScaleX=currScale;
				currScaleY=currScale;
				if(currRotate==0){
					this.transform('scale(' + currScale + ')');
				}else{
					this.transform('scale(' + currScale + ') rotate('+currRotate+'deg)');	
				}
			}
			this.addImagePecent();
		}
	};
	Zoomify.prototype.enlargeImage = function () {
		if(currScale>=20){
			return;
		}
		currScale+=0.08;
		if(currScale>20){
			currScale=20;
		}
		this.imgScale(event);
	};
	Zoomify.prototype.reduceImage = function () {
		if(currScale<=0.03){
			return;
		}
		if(currScale<=0.15){
			currScale-=0.02;
		}else{
			currScale-=0.08;
		}	
		this.imgScale(event);
	};
	Zoomify.prototype.rotateLeftImage = function () {
		currRotate-=90;
		if(currRotate==0){
			if(currScaleX<0 || currScaleY<0){
				this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+')');
			}else{
				this.transform('scale(' + currScale + ')');
			}
		}else{
			if(currScaleX<0 || currScaleY<0){
				this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+') rotate('+currRotate+'deg)');
			}else{
				this.transform('scale(' + currScale + ') rotate('+currRotate+'deg)');
			}	
		}		
	};
	Zoomify.prototype.rotateRightImage = function () {
		currRotate+=90;
		if(currRotate==0){
			if(currScaleX<0 || currScaleY<0){
				this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+')');
			}else{
				this.transform('scale(' + currScale + ')');
			}	
		}else{
			if(currScaleX<0 || currScaleY<0){
				this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+') rotate('+currRotate+'deg)');
			}else{
				this.transform('scale(' + currScale + ') rotate('+currRotate+'deg)');
			}		
		}	
	};
	Zoomify.prototype.flipHorizontalImage = function () {
		if(currScaleX==0){
			currScaleX=-currScale;
		}else{
			currScaleX=-currScaleX;
		}
		if(currScaleY==0){
			currScaleY=currScale;
		}
		if(currRotate==0){
			this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+')');
		}else{
			this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+') rotate('+currRotate+'deg)');
		}
	};
	Zoomify.prototype.flipVerticalImage = function () {
		if(currScaleY==0){
			currScaleY=-currScale;
		}else{
			currScaleY=-currScaleY;
		}
		if(currScaleX==0){
			currScaleX=currScale;
		}
		if(currRotate==0){
			this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+')');
		}else{
			this.transform('scaleX(' + currScaleX + ') scaleY('+currScaleY+') rotate('+currRotate+'deg)');
		}
	};
	Zoomify.prototype.resetImage = function () {
		currScale=1;
		this.imgScale(event);
	};
	// shadow background
	Zoomify.prototype.addImage = function () {
		var that = this;
		if (this._zoomed) return;
		
		if (that.$newImage) that.$newImage.remove();
		this.$newImage = $('<div class="scale_img_div"><img class="zoomify"></div>');
		$('body').append(this.$newImage);
		this.$newImage.on('click', function () { that.zoomOut(); })
	};
	Zoomify.prototype.addImagePecent = function () {
		var that = this;
		clearTimeout(this._percentTimeout);
		var currScalePercent=Math.floor(currScale*100);
		if(this.$imgPercent){
			this.$imgPercent.addClass('scale_img_percent_show');
			this.$imgPercent.text(currScalePercent+"%");
		}else{
			this.$imgPercent = $('<div class="scale_img_percent scale_img_percent_show">'+currScalePercent+'%</div>');
			$('body').append(this.$imgPercent);
		}
		this._percentTimeout=setTimeout(function () { that.$imgPercent.removeClass('scale_img_percent_show')}, 700);
	};
	// shadow background
	Zoomify.prototype.addShadow = function () {
		var that = this;
		if (this._zoomed) return;
		
		if (that.$shadow) that.$shadow.remove();
		this.$shadow = $('<div class="zoomify-shadow"></div>');
		$('body').append(this.$shadow);
		this.addTransition(this.$shadow);
		this.$shadow.on('click', function () { that.zoomOut(); })
		
		setTimeout(function () { that.$shadow.addClass('zoomed'); }, 10);
	};
	Zoomify.prototype.removeShadow = function () {
		var that = this;
		if (!this.$shadow) return;
		
		this.addTransition(this.$shadow);
		this.$shadow.removeClass('zoomed');
		this.$image.one('zoom-out-complete.zoomify', function () {
			if (that.$shadow) that.$shadow.remove();
			that.$shadow = null;
		});
	};
	
	// plugin definition
	$.fn.zoomify = function (option) {
		return this.each(function () {
			var $this   = $(this),
				zoomify = $this.data('zoomify');
			
			if (!zoomify) $this.data('zoomify', (zoomify = new Zoomify(this, typeof option == 'object' && option)));
			if (typeof option == 'string' && ['zoom', 'zoomIn', 'zoomOut', 'reposition'].indexOf(option) >= 0) zoomify[option]();
		});
	};
	
})(jQuery);

上述是完整的js实现代码,通过上述代码配合zoomify的css就可以达到图片上的效果了。

@charset "UTF-8";
.zoomify { cursor: pointer; cursor: -webkit-zoom-in; cursor: zoom-in; }
.zoomify.zoomed { cursor: -webkit-zoom-out; cursor: zoom-out; padding: 0; margin: 0; border: none; border-radius: 0; box-shadow: none; position: relative; z-index: 1501; }
.zoomify-shadow { position: fixed; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; display: block; z-index: 1111; background: rgba(0, 0, 0 , .3); opacity: 0; }
.zoomify-shadow.zoomed { opacity: 1; cursor: pointer; cursor: -webkit-zoom-out; cursor: zoom-out; }
.scale_img_percent {position: fixed;background-color: #000;color: #fff;font-size: 11px;border-radius: 10px;margin: auto;left: 0;top: 0;right: 0;bottom: 0;width: 54px;height: 20px;z-index: 1800;text-align: center;line-height: 20px;display: none;}
.scale_img_percent_show {display: block;}
.scale_img_opt_toolbar {
	position: fixed;
	background-color: #000;
	left: 0;
	bottom: 20px;
	right: 0;
	margin: 0 auto;
	display: none;
	text-align: center;
	border-radius: 4px;
	z-index: 1900;
	width: 427px;
	height: 50px;
}
.scale_img_opt_toolbar>ul{
	padding: 9px 8px;
}
.scale_img_opt_toolbar>ul>li{
	cursor: pointer;
	float: left;
	margin: 0 4px;
	border: 1px solid #383838;
	padding: 5px;
	border-radius: 4px;
}
.scale_img_opt_toolbar>ul>li:hover{
	color: #fff;
}
.scale_img_opt_toolbar>ul>li:before {
    color: hsla(0,0%,100%,.65);
}
.scale_img_opt_toolbar>ul>li:hover:before {
	color: #fff;
}
.viewer_counter{
	color: hsla(0,0%,100%,.65);
}
.viewer_zoom_in:before {
    content: "\e777";
}
.viewer_zoom_out:before {
    content: "\e776";
}
.viewer_prev:before {
    content: "\e6de";
}
.viewer_next:before {
    content: "\e6e0";
}
.viewer_rotate_left:before{
	content: "\e6c7";
}
.viewer_rotate_right:before{
	content: "\e6c8";
}
.viewer_flip_horizontal:before{
	content: "\21C4";
}
.viewer_flip_vertical:before{
	content: "\21C5";
}
.viewer_one_to_one{
	background-image: url(/img/icon/one-to-one.svg);
    background-repeat: no-repeat;
    background-position: 50%;
    width: 32px;
    height: 32px;
}
.viewer_counter{
	height: 32px;
	line-height: 1;
}
.viewer_zoom_in:before,.viewer_zoom_out:before,.viewer_prev:before,.viewer_next:before,.viewer_rotate_left:before,.viewer_rotate_right:before,.viewer_flip_horizontal:before,.viewer_flip_vertical:before{
	cursor: pointer;
	font-weight: 400;
	line-height: 1;
	font-family: element-icons !important;
	font-size: 20px;
	display: block;
}

3.大家可以去尝试一下。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐