It is generally used to zoom in to view product pictures. Similar effects are available on Fanke, JD.com, Alibaba, etc.
The advantage is that you can zoom in and view parts of the image near the original image, and you can control the viewing area with the mouse.
I saw the enlargement effect of sohighthesky’s picture a while ago, and I had a sudden impulse to write one myself.
This app has the following features:
1. Supports enlarging the original image or setting a large image with a new image;
2. Before the large image is loaded, use the original image to enlarge instead, reducing the waiting time for the operation;
3. Support mouse scrolling to zoom the large image;
4. You can set the display size by setting the display range or display box size;
5. You can set whether to automatically hide the display box;
6. Support plug-in form Expand to implement more functions (more details in the next article).
Compatible with: ie6/7/8, firefox 3.6.2, opera 10.51, safari 4.0.4, chrome 4.1
Note that the display range is obtained through clientWidth/clientHeight.
If the display box is in a hidden state with display set to none, clientWidth/clientHeight cannot be obtained directly.
2, set it to "block"/"absolute"/"hidden" respectively, which It can be both hidden and occupied;
4, reset it back to the original value and restore the original state.
After getting the display range, you can get the range parameters by matching the proportion.
ps: This is a common method to obtain the size parameters of non-placeholder elements. jquery’s css also uses this method to obtain width/height.
Decimals may be obtained after proportion calculation, but the size can only be integers. The program always uses Math.ceil to round.
After everything is set up, you can execute start to set the trigger program.
The program will automatically execute the start method, which mainly binds the _start program to mouseover/mousemove of the original image object:
$$E. addEvent( image, "mouseover", START );
corresponds to the cases of moving into the original image object and moving on the original image object respectively.
ps: If you use attachEvent, you should also pay attention to the problem of repeatedly binding the same function. The addEvent here does not have this problem.
In order to move out the window To end the magnification effect, bind the _OUT program to the mouseout of the document:
When the mouse moves out of the document, mouseout will be triggered. If the current relatedTarget is null, the execution of _end will be delayed to end the program:
In the _end program, the stop method will be executed first and all possible bound events will be removed. , and then execute the start method to continue waiting for the trigger.
The _move mobile program bound to mousemove is mainly used to realize the function of zooming in wherever the mouse moves.
In order to adapt to more situations (such as other modes in the expansion), it is bound to the document, but therefore the mouseout event cannot be used to trigger the removal process.
The program determines whether the mouse has moved out of the original image object range by comparing the coordinates of the mouse and the original image:
If the mouse moves out of the original If it is a picture object, execute _END to end the magnification effect.
If the mouse moves on the original image object, the coordinates are calculated and converted into the values required for positioning through the _repair program.
Finally, set the left/top positioning of the large image so that the display box displays the part to be enlarged.
ps: I tried using scrollLeft/scrollTop for positioning, but found that it would move like a sawtooth in IE, and the larger it became, the more obvious it became, so I gave up.
If the mouse attribute is set to true, the mouse scrolling and zooming function will be enabled.
During the magnification effect, you can zoom in and out of the large image by rolling the mouse wheel.
In fact, it is to modify the magnification ratio according to changes in the scroll wheel parameters.
Regarding mouse scrolling events, it was also mentioned in slider, but at that time I only analyzed the difference between ie and ff. Let’s analyze it again here.
First of all, IE uses mousewheel to bind events, and uses the wheelDelta of event to obtain the scrolling parameters. < !DOCTYPE html>
Scroll down a bit and you get the following results:
ff: DOMMouseScroll:3_undefined
opera: mousewheel:3_-120
chrome/safari: mousewheel:0_-120
You can see the events For binding, ff only supports DOMMouseScroll, and others only support mousewheel.
As for the acquisition of scrolling parameters, ff only supports detail, opera supports both, and chrome/safari supports wheelDelta.
ps: I don’t understand why the detail of chrome/safari is 0. Is there any other use?
Another difference between DOMMouseScroll and mousewheel is that the former cannot directly bind elements, while the latter can.
That is, elem.onmousewheel is possible, but elem.onDOMMouseScroll is not.
Based on the above analysis, in the _start program, the _mouse program is bound to the scroll event of the document like this:
this.mouse && $$E.addEvent( document, $$B.firefox ? "DOMMouseScroll " : "mousewheel", this._MOUSE );
In the _mouse program, get a new magnification ratio based on the rolling parameters and the customized rate scaling ratio:
this._scale = ( e.wheelDelta ? e.wheelDelta / (-120) : (e.detail || 0) / 3 ) * this.rate;
When the ratio is modified, the program parameters also need to be recalculated.
Since _rangeWidth/_rangeHeight will affect the calculation process, you need to restore it to the custom default value:
var opt = this.options;
this._rangeWidth = opt.rangeWidth;
this. _rangeHeight = opt.rangeHeight;
Then execute _initSize and _initData to reset the size and parameters, and then execute _move to reposition.
Finally, remember to use preventDefault to prevent page scrolling from being triggered.
Usage Tips
[Picture Settings]
The program supports large images, enlarge the original image or use a new large image.
If you use a new large image and the image is relatively large, it is strongly recommended to set the magnification ratio, so that the program will automatically use the original image to enlarge before loading the large image, so you do not have to wait for the large image to be loaded.
Also note that the width and height ratio of the new large image must be consistent with the original image, otherwise the coordinates will be misaligned. This problem will not occur if you use the original image to enlarge it.
[Display frame settings]
There are two methods to set the size of the display frame:
To fix the display range, set rangeWidth/rangeHeight first, and the program will calculate the size of the display frame based on the display range and magnification ratio. ;
To display using the current size of the display box, just do not set rangeWidth/rangeHeight or set it to 0.
【reset】
Due to the many relationships between various attributes and objects, many attributes cannot be modified directly.
The program sets up a reset method specifically for modifying such attributes.
If the style that affects the program calculation is modified after the program is loaded, such as the size of the original image, the size of the display box, etc., you must also perform a reset to reset the parameters and attributes.
【Floating Positioning】
The program does not have the function of setting the floating positioning of the display frame. You can add it yourself if necessary.
For simple positioning, you can refer to the instance method, and be careful about overriding select.
If you want more complex floating positioning, you can refer to the "Floating Positioning Prompt Effect".
【opera bugs】
During testing, two bugs were found in opera 10.10.
Respectively, when the img element is set to be transparent, you will see the background image, and there will be problems in using js to modify the mouse style.
However, these two problems have been fixed in 10.50. If you haven’t upgraded yet, please upgrade as soon as possible.
【maxthon bug】
A problem was found when testing with maxthon 2.5.1. Test the following code:
<script> <br>var t= document.getElementById("t"); <br>t.clientWidth; <br>t.style.display="none"; <br>alert(t.clientWidth); <br></script>
Generally speaking, after hiding with display, clientWidth should be 0, but maxthon does not seem to handle this situation.
This will affect the judgment of clientWidth in the program, but has no impact on general use.
I have submitted this issue, I wonder if it will be dealt with.
Instructions for use
When instantiating, there must be an img element as the original image object and a container as the display box:
var iz = new ImageZoom( "idImage", "idViewer" );
Optional parameters are used to set the default attributes of the system, including:
Attribute: Default value//Description
mode: "simple",//Mode
scale: 0,//Scale (large picture/original Picture)
max: 10,//Maximum ratio
min: 1.5,//Minimum ratio
originPic: "",//Original picture address
zoomPic: "",//Large picture address
rangeWidth: 0,//Display range width
rangeHeight:0,//Display range height
delay: 20,//Delay end time
autoHide: true,//Whether to automatically hide
mouse: false,//Mouse scaling
rate: .2,//Mouse scaling ratio
onLoad: $$.emptyFunction,//Executed when loading is completed
onStart: $$.emptyFunction,// Execute when zooming in
onMove: $$.emptyFunction, //Execute when zooming in and moving
onEnd: $$.emptyFunction//Execute when zooming in ends
The use of modes will be explained in the next expansion article.
After initialization, the attributes scale, max, min, originPic, zoomPic, rangeWidth, and rangeHeight need to be modified using the reset method.
The following methods are also provided:
start: start the amplification program (the program will be executed automatically);
stop: stop the amplification program;
reset: modify the settings;
dispose: destroy the program.
Program source code
var ImageZoom = function(image, viewer, options) {
this._initialize( image, viewer, options );
this._initMode( this.options.mode );
this ._oninit();
this._initLoad();
};
ImageZoom.prototype = {
//Initializer
_initialize: function(image, viewer, options) {
this._image = $$(image);//Original image
this._zoom = document.createElement("img");//Display image
this._viewer = $$(viewer);// Display box
this._viewerWidth = 0;//Display box width
this._viewerHeight = 0;//Display box height
this._preload = new Image();//Preload object
this._rect = null;//Original image coordinates
this._repairLeft = 0;//Display image x coordinate correction
this._repairTop = 0;//Display image y coordinate correction
this._rangeWidth = 0;//Display range width
this._rangeHeight = 0;//Display range height
this._timer = null;//Timer
this._loaded = false;//Whether to load
this._substitute = false;//Whether to replace
var opt = this._setOptions(options);
this._scale = opt.scale;
this._max = opt.max;
this. _min = opt.min;
this._originPic = opt.originPic;
this._zoomPic = opt.zoomPic;
this._rangeWidth = opt.rangeWidth;
this._rangeHeight = opt.rangeHeight;
this.delay = opt.delay;
this.autoHide = opt.autoHide;
this.mouse = opt.mouse;
this.rate = opt.rate;
this.onLoad = opt.onLoad;
this.onStart = opt.onStart;
this.onMove = opt.onMove;
this.onEnd = opt.onEnd;
var oThis = this, END = function( ){ oThis._end(); };
this._END = function(){ oThis._timer = setTimeout( END, oThis.delay ); };
this._START = $$F.bindAsEventListener( this ._start, this );
this._MOVE = $$F.bindAsEventListener( this._move, this );
this._MOUSE = $$F.bindAsEventListener( this._mouse, this );
this ._OUT = $$F.bindAsEventListener( function(e){
if ( !e.relatedTarget ) this._END();
}, this );
},
//Set the default Attribute
_setOptions: function(options) {
this.options = {//Default value
mode: "simple",//Mode
scale: 0,//Scale (large picture/original Picture)
max: 10,//Maximum ratio
min: 1.5,//Minimum ratio
originPic: "",//Original picture address
zoomPic: "",//Large picture address
rangeWidth: 0,//Display range width
rangeHeight:0,//Display range height
delay: 20,//Delay end time
autoHide: true,//Whether to automatically hide
mouse: false,//Mouse scaling
rate: .2,//Mouse scaling ratio
onLoad: $$.emptyFunction,//Executed when loading is completed
onStart: $$.emptyFunction,// Execute when zooming in
onMove: $$.emptyFunction, //Execute when zooming in and moving
onEnd: $$.emptyFunction//Execute when zooming in ends
};
return $$.extend(this .options, options || {});
},
//Initialize function attributes according to mode
_initMode: function(mode) {
mode = $$.extend({
options :{},
init: $$.emptyFunction,
load: $$.emptyFunction,
start: $$.emptyFunction,
end: $$.emptyFunction,
move: $ $.emptyFunction,
dispose:$$.emptyFunction
}, (ImageZoom._MODE || {})[ mode.toLowerCase() ] || {} );
this.options = $$. extend( mode.options, this.options );
this._oninit = mode.init;
this._onload = mode.load;
this._onstart = mode.start;
this._onend = mode.end;
this._onmove = mode.move;
this._ondispose = mode.dispose;
},
//Initial loading
_initLoad: function() {
var image = this._image, originPic = this._originPic,
useOrigin = !this._zoomPic && this._scale,
loadImage = $$F.bind( useOrigin ? this._loadOriginImage : this._loadImage, this );
//Set automatic hiding
if ( this.autoHide ) { this._viewer.style.display = "none"; }
//Load the original image first
if ( originPic && originPic != image.src ) {//Use custom address
image.onload = loadImage;
image.src = originPic;
} else if ( image.src ) {//Use element address
if ( !image.complete ) {//Not finished loading
image.onload = loadImage;
} else {//Already loaded
loadImage();
}
} else {
return;//No original image address
}
//Load large image
if ( !useOrigin ) {
var preload = this._preload, zoomPic = this._zoomPic | | image.src,
loadPreload = $$F.bind( this._loadPreload, this );
if ( zoomPic != preload.src ) {//Reload with new address
preload.onload = loadPreload ;
preload.src = zoomPic;
} else {//Loading
if ( !preload.complete ) {//Not loaded
preload.onload = loadPreload;
} else {//Already loaded
this._loadPreload();
}
}
}
},
//Original image enlargement loader
_loadOriginImage: function( ) {
this._image.onload = null;
this._zoom.src = this._image.src;
this._initLoaded();
},
//Original image loading Program
_loadImage: function() {
this._image.onload = null;
if ( this._loaded ) {//The large image has been loaded
this._initLoaded();
} else {
this._loaded = true;
if ( this._scale ) {//If you have a custom scale, use the original image to enlarge and replace the larger image
this._substitute = true;
this._zoom .src = this._image.src;
this._initLoaded();
}
}
},
//Large image preloader
_loadPreload: function() {
this._preload.onload = null;
this._zoom.src = this._preload.src;
if ( this._loaded ) {//The original image has been loaded
// No substitution is used
if ( !this._substitute ) { this._initLoaded(); }
} else {
this._loaded = true;
}
},
//Initialize loading settings
_initLoaded: function(src) {
//Initialize display image
this._initSize();
//Initialize the display box
this._initViewer();
//Initialize data
this._initData();
//Start execution
this._onload();
this .onLoad();
this.start();
},
//Initialize the display image size
_initSize: function() {
var zoom = this._zoom, image = this ._image, scale = this._scale;
if ( !scale ) { scale = this._preload.width / image.width; }
this._scale = scale = Math.min( Math.max( this. _min, scale ), this._max );
//Set the display size proportionally
zoom.width = Math.ceil( image.width * scale );
zoom.height = Math.ceil( image.height * scale );
},
//Initialize the display box
_initViewer: function() {
var zoom = this._zoom, viewer = this._viewer;
// Set style
var styles = { padding: 0, overflow: "hidden" }, p = $$D.getStyle( viewer, "position" );
if ( p != "relative" && p != "absolute" ){ styles.position = "relative"; };
$$D.setStyle( viewer, styles );
zoom.style.position = "absolute";
//Insert display image
if ( !$$D.contains( viewer, zoom ) ){ viewer.appendChild( zoom ); }
},
//Initialization data
_initData: function() {
var zoom = this._zoom, image = this._image, viewer = this._viewer,
scale = this._scale, rangeWidth = this._rangeWidth, rangeHeight = this._rangeHeight;
//Original image coordinates
this._rect = $$D.rect( image );
//Repair parameters
this._repairLeft = image.clientLeft parseInt($$D.getStyle( image, "padding-left" ));
this._repairTop = image.clientTop parseInt($$D.getStyle( image, "padding-top" ));
//Set range parameters and display box size
if ( rangeWidth > 0 && rangeHeight > 0 ) {
rangeWidth = Math.ceil( rangeWidth );
rangeHeight = Math.ceil( rangeHeight );
this._viewerWidth = Math.ceil( rangeWidth * scale );
this. _viewerHeight = Math.ceil( rangeHeight * scale );
$$D.setStyle( viewer, {
width: this._viewerWidth "px",
height: this._viewerHeight "px"
} );
} else {
var styles;
if ( !viewer.clientWidth ) {//Hide
var style = viewer.style;
styles = {
display: style .display,
position: style.position,
visibility: style.visibility
};
$$D.setStyle( viewer, {
display: "block", position: "absolute ", visibility: "hidden"
});
}
this._viewerWidth = viewer.clientWidth;
this._viewerHeight = viewer.clientHeight;
if ( styles ) { $$D .setStyle( viewer, styles ); }
rangeWidth = Math.ceil( this._viewerWidth / scale );
rangeHeight = Math.ceil( this._viewerHeight / scale );
}
this. _rangeWidth = rangeWidth;
this._rangeHeight = rangeHeight;
},
//Start
_start: function() {
clearTimeout( this._timer );
var viewer = this ._viewer, image = this._image, scale = this._scale;
viewer.style.display = "block";
this._onstart();
this.onStart();
$ $E.removeEvent( image, "mouseover", this._START );
$$E.removeEvent( image, "mousemove", this._START );
$$E.addEvent( document, "mousemove" , this._MOVE );
$$E.addEvent( document, "mouseout", this._OUT );
this.mouse && $$E.addEvent( document, $$B.firefox ? "DOMMouseScroll" : "mousewheel", this._MOUSE );
},
//Move
_move: function(e) {
clearTimeout( this._timer );
var x = e.pageX , y = e.pageY, rect = this._rect;
if ( x < rect.left || x > rect.right || y < rect.top || y > rect.bottom ) {
this._END();//Move out of the original image range
} else {
var zoom = this._zoom,
pos = this._repair(
x - rect.left - this ._repairLeft,
y - rect.top - this._repairTop
);
this._onmove( e, pos );
//Set positioning
zoom.style.left = pos. left "px";
zoom.style.top = pos.top "px";
this.onMove();
}
},
//Correction coordinates
_repair : function(x, y) {
var scale = this._scale, zoom = this._zoom,
viewerWidth = this._viewerWidth,
viewerHeight = this._viewerHeight;
//Correction coordinates
x = Math.ceil( viewerWidth / 2 - x * scale );
y = Math.ceil( viewerHeight / 2 - y * scale );
//Range limit
x = Math.min ( Math.max( x, viewerWidth - zoom.width ), 0 );
y = Math.min( Math.max( y, viewerHeight - zoom.height ), 0 );
return { left: x , top: y };
},
//End
_end: function() {
this._onend();
this.onEnd();
if ( this .autoHide ) { this._viewer.style.display = "none"; }
this.stop();
this.start();
},
//鼠标缩放
_mouse: function(e) {
this._scale = ( e.wheelDelta ? e.wheelDelta / (-120) : (e.detail || 0) / 3 ) * this.rate;
var opt = this.options;
this._rangeWidth = opt.rangeWidth;
this._rangeHeight = opt.rangeHeight;
this._initSize();
this._initData();
this._move(e);
e.preventDefault();
},
//开始
start: function() {
if ( this._viewerWidth && this._viewerHeight ) {
var image = this._image, START = this._START;
$$E.addEvent( image, "mouseover", START );
$$E.addEvent( image, "mousemove", START );
}
},
//停止
stop: function() {
clearTimeout( this._timer );
$$E.removeEvent( this._image, "mouseover", this._START );
$$E.removeEvent( this._image, "mousemove", this._START );
$$E.removeEvent( document, "mousemove", this._MOVE );
$$E.removeEvent( document, "mouseout", this._OUT );
$$E.removeEvent( document, $$B.firefox ? "DOMMouseScroll" : "mousewheel", this._MOUSE );
},
//修改设置
reset: function(options) {
this.stop();
var viewer = this._viewer, zoom = this._zoom;
if ( $$D.contains( viewer, zoom ) ) { viewer.removeChild( zoom ); }
var opt = $$.extend( this.options, options || {} );
this._scale = opt.scale;
this._max = opt.max;
this._min = opt.min;
this._originPic = opt.originPic;
this._zoomPic = opt.zoomPic;
this._rangeWidth = opt.rangeWidth;
this._rangeHeight = opt.rangeHeight;
//重置属性
this._loaded = this._substitute = false;
this._rect = null;
this._repairLeft = this._repairTop =
this._viewerWidth = this._viewerHeight = 0;
this._initLoad();
},
//销毁程序
dispose: function() {
this._ondispose();
this.stop();
if ( $$D.contains( this._viewer, this._zoom ) ) {
this._viewer.removeChild( this._zoom );
}
this._image.onload = this._preload.onload =
this._image = this._preload = this._zoom = this._viewer =
this.onLoad = this.onStart = this.onMove = this.onEnd =
this._START = this._MOVE = this._END = this._OUT = null
}
}
转载请注明出处:http://www.cnblogs.com/cloudgamer/
如有任何建议或疑问,欢迎留言讨论。
打包下载地址