在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 = $('');
$('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 = $(''+currScalePercent+'%');
$('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 = $('');
$('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.大家可以去尝试一下。