It mainly expands the display mode of the original image and the display frame, and has the following modes:
"follow" follow mode: the display frame can follow the mouse movement effect;
"handle" drag handle mode: there are A drag handle to mark the display range;
"cropper" cutting mode: the original image is opaque to mark the display range, and other parts are displayed in translucent;
"handle-cropper" drag handle cutting mode: drag handle mode and a hybrid version of the cutting mode, while using transparency and drag handles to mark the display range.
Of course, more extensions are waiting for your imagination to explore.
Compatible with: ie6/7/8, firefox 3.6.2, opera 10.51, safari 4.0.4, chrome 4.1
Program description
【 Extension mode]
Last time ImagesLazyLoad used inheritance for extension, this time it uses plug-in for extension.
Let’s take a look at the basic modes first. These modes are saved in ImageZoom._MODE, with a structure similar to this:
ImageZoom._MODE = {
Mode name: {
options: {
...
},
methods: {
init: function() {
...
},
...
}
},
...
}
The mode name is the name of the basic mode, options is the optional parameter extension, and methods is the extension of the program structure.
Basic modes include "follow", "handle" and "cropper" modes, which will be introduced in detail later.
methods contains the hook program to be extended and is the main part of the extension.
ps: The pattern mentioned here is not the pattern in "design pattern".
Expansion needs to be performed during program initialization and must be executed before the _initialize program.
In order not to affect the structure of the original program, we use the weaving method to insert a program before _initialize:
ImageZoom.prototype._initialize = (function(){
var init = ImageZoom.prototype._initialize,
...;
return function (){
...
init.apply( this, arguments );
}
})();
The principle is to save the original function first, Insert a program to form a new function, and then replace the original function.
Considering the combination of basic modes, an object is used to save the actual mode used:
mode = ImageZoom._MODE,
modes = {
"follow": [ mode.follow ],
"handle": [ mode. handle ],
"cropper": [ mode.cropper ],
"handle-cropper": [ mode.handle, mode.cropper ]
};
Can be viewed The "handle-cropper" mode is actually a combination mode of "handle" and "cropper".
The main task of the inserted program is to expand according to the set basic mode:
var options = arguments[2];
if ( options && options.mode && modes[ options.mode ] ) {
$$A.forEach( modes[ options.mode ], function( mode ){
$$.extend( options, mode.options, false );
$$A.forEach( mode.methods, function( method, name ){
$$CE.addEvent( this, name, method );
}, this );
}, this );
}
First expand the options optional parameter object. Since the optional parameter is the third parameter, it is obtained with arguments[2]. The third parameter of
extend is set to false, which means that the same attribute will not be rewritten, that is, the customized attribute value will be retained.
Then add the methods in methods as hook functions to the program one by one.
methods can include init, load, start, repair, move, end, and dispose, which correspond to the initialization, loading, start, modification, move, end, and destruction events in ImageZoom respectively.
During expansion, different events perform different tasks:
init initialization function: used to set the attributes required for expansion. Note that these attributes do not conflict with the attributes of ImageZoom itself, that is, have the same name.
load loading function: The image loading is completed, and the relevant parameters are also set. It is mainly used to prepare for the enlargement effect.
start function: executed when the amplification effect is triggered.
repair correction function: used to correct the coordinate values of large image positioning.
move function: executed when the mouse moves after triggering the magnification effect.
The end function is: executed when ending the magnification effect.
dispose destruction function: cleans up the program when removing it.
ps: For the specific location, please refer to the section using $$CE.fireEvent in ImageZoom.
You can see that weave and hook are used to extend the program.
Weaving method is a kind of AOP, which can be expanded without changing the original program, but it can only add the program before or after the function.
The hook method must set the corresponding hook in the original program before it can be used together, but the position is relatively flexible.
【Follow Mode】
In "follow" mode, when you zoom in, the display frame will follow the movement of the mouse, just like holding a magnifying glass.
First of all, the display frame must be absolutely positioned. To realize that the display frame follows the movement of the mouse, just set the corresponding left/top in move:
var style = this._viewer. style;
style.left = e.pageX - this._repairFollowLeft "px";
style.top = e.pageY - this._repairFollowTop "px";
where pageX/pageY are the current coordinates of the mouse , _repairFollowLeft/_repairFollowTop are the correction parameters of the coordinates.
The correction parameters are set in load. If the display box is hidden, use the method of obtaining the display range in the previous article to obtain the parameters:
if ( !viewer.offsetWidth ) {
styles = { display: style.display, visibility: style.visibility };
$$D.setStyle( viewer, { display: "block", visibility: "hidden" });
}
...
if ( styles ) { $$D.setStyle( viewer, styles ); }
In order to follow, let the mouse be fixed at the center of the display frame, first correct the parameters according to the offsetWidth/offsetHeight of the display frame:
this._repairFollowLeft = viewer.offsetWidth / 2;
this._repairFollowTop = viewer.offsetHeight / 2;
If the offsetParent of the display box is not the body, the coordinates need to be corrected based on the offsetParent:
if ( !/BODY|HTML/.test( viewer.offsetParent.nodeName ) ) {
var parent = viewer.offsetParent, rect = $$D.rect( parent );
this._repairFollowLeft = rect.left parent.clientLeft;
this._repairFollowTop = rect.top parent.clientTop;
}
ps: Found body during Maxthon test The offsetParent of the element is not body but html.
In order to restore the display box style after removing the program, a backup of the style is made in the load program:
var viewer = this._viewer, style = viewer.style, styles;
this._stylesFollow = {
left: style.left, top: style.top, position: style.position
};
and restored in dispose:
$$D.setStyle( this._viewer, this._stylesFollow );
Now the basic effect has been achieved, but due to the limitation of the moving range of the large image, when the mouse moves close to the boundary, the large image will get stuck and will not move.
In order to achieve the effect that the large image will continue to change when the mouse moves, the movement coordinates have been corrected in repair:
pos.left = ( viewerWidth / 2 - pos.left ) * ( viewerWidth / zoom.width - 1 );
pos.top = ( viewerHeight / 2 - pos.top ) * ( viewerHeight / zoom.height - 1 );
The principle is a little complicated. Taking horizontal coordinates as an example, look at the picture below:
The large box represents the large image object, and the small box Frame represents the display frame.
The current position is the actual displayed position obtained based on the mouse coordinates, and the target position is where the effect is to be achieved.
Some physics or geometry knowledge should understand this equation: x / y = m / n
It can be deduced: y = x * n / m = x * ( zoom.width - viewerWidth ) / zoom.height
The current coordinate of x can be obtained by pos.left: x = viewerWidth / 2 - pos.left
Finally, we get: left = -y = (viewerWidth / 2 - pos.left ) * ( viewerWidth / zoom.width - 1)
The vertical coordinates are similar.
[Drag handle mode]
The drag handle is a layer on top of the original image, used to indicate the position and range of the display range in the original image.
The display range can be obtained based on _rangeWidth/_rangeHeight.
As for the position specification, it can be set according to mouse coordinates or large picture positioning coordinates.
If the mouse coordinates are used, other processing must be done, such as range control, but positioning the coordinates based on the large picture is relatively more convenient and accurate. The program also uses the latter method.
First define a _handle drag handle object in init:
var handle = $$( this.options.handle );
if ( !handle ) {
var body = document.body;
handle = body.insertBefore(this._viewer. cloneNode(false), body.childNodes[0]);
handle.id = "";
handle["_createbyhandle"] = true;
}
$$D.setStyle( handle, { padding: 0, margin: 0, display: "none" } );
If there is no custom drag handle object, the display box will be copied as the drag handle object.
For automatically generated drag handle objects, the "_createbyhandle" attribute will be added as a mark to facilitate removal in dispose.
When loading, set the drag handle style:
$$D.setStyle( handle, {
position: "absolute",
width: this._rangeWidth "px",
height: this._rangeHeight "px",
display: "block",
visibility: "hidden"
});
Absolute positioning is required and the size is set according to _rangeWidth/_rangeHeight.
Setting display and visibility is to obtain parameters below.
First get the correction parameters based on the original image coordinates:
this._repairHandleLeft = rect.left this._repairLeft - handle.clientLeft;
this._repairHandleTop = rect.top this ._repairTop - handle.clientTop;
Similar to follow mode, offsetParent positioning also needs to be corrected:
if ( handle.offsetParent.nodeName.toUpperCase() != "BODY" ) {
var parent = handle.offsetParent, rect = $$D .rect( parent );
this._repairHandleLeft -= rect.left parent.clientLeft;
this._repairHandleTop -= rect.top parent.clientTop;
}
Then re-hide:
$$D.setStyle( handle, { display: "none", visibility: "visible" });
At start, display the drag handle object.
When moving, set the drag handle positioning according to the large image positioning coordinates:
var style = this._handle.style, scale = this._scale;
style.left = Math.ceil( this._repairHandleLeft - x / scale ) "px";
style.top = Math.ceil( this._repairHandleTop - y / scale ) "px";
At end, hide the drag handle object.
【Cut mode】
"Cut" is the effect where the selected part is completely transparent and the other parts are translucent.
Mainly achieved through clipping, the specific principle can be seen in the picture cutting effect.
In order to achieve the cutting effect, you need to create a new _cropper cutting layer in init:
var body = document.body,
cropper = body.insertBefore(document.createElement("img"), body.childNodes[0]);
cropper .style.display = "none";
And set this cutting layer in load:
cropper.src = image.src;
cropper.width = image.width;
cropper.height = image.height;
$$D.setStyle( cropper, {
position: "absolute",
left: rect.left this._repairLeft "px",
top: rect.top this._repairTop "px"
});
Almost Copy an original image object and position it absolutely on top of the original image object.
When starting, display the cutting layer and set the original image to a semi-transparent state according to the transparency.
When moving, set the clipping range of the cutting layer according to the coordinates of the large image movement:
var w = this._rangeWidth, h = this._rangeHeight, scale = this._scale;
x = Math.ceil( -x / scale ); y = Math. ceil( -y / scale );
this._cropper.style.clip = "rect(" y "px " (x w) "px " (y h) "px " x "px)";
At the end, hide the cutting layer and reset the original image to opaque to restore the original state.
Also remember to remove the cutting layer in dispose.
Usage Tips
You need to add this extension only when you need the extended effect.
You can expand ImageZoom._MODE by yourself. After expansion, remember to add the corresponding mode in modes.
Multiple basic modes can be combined and used at the same time, please refer to the "handle-cropper" mode for details.
Instructions for use The usage method is similar to ImageZoom, except that there is an additional optional reference mode to set the display mode.
When using "handle" mode, the "handle" attribute of the optional parameter can set the drag handle object.
When using "cropper" mode, the "opacity" attribute of the optional parameter can set transparency.
When using "handle-cropper" mode, both of the above parameters can be used.
Program source code
ImageZoom._MODE = {
//Follow
"follow": {
methods: {
init: function() {
this._stylesFollow = null;/ /Backup style
this._repairFollowLeft = 0;//Correction coordinates left
this._repairFollowTop = 0;//Correction coordinates top
},
load: function() {
var viewer = this._viewer, style = viewer.style, styles;
this._stylesFollow = {
left: style.left, top: style.top, position: style.position
};
viewer .style.position = "absolute";
//Get the correction parameters
if ( !viewer.offsetWidth ) {//Hide
styles = { display: style.display, visibility: style.visibility };
$$D.setStyle( viewer, { display: "block", visibility: "hidden" });
}
//Correct the center position
this._repairFollowLeft = viewer.offsetWidth / 2 ;
this._repairFollowTop = viewer.offsetHeight / 2;
//Correct offsetParent position
if ( !/BODY|HTML/.test( viewer.offsetParent.nodeName ) ) {
var parent = viewer.offsetParent, rect = $$D.rect( parent );
this._repairFollowLeft = rect.left parent.clientLeft;
this._repairFollowTop = rect.top parent.clientTop;
}
if ( styles ) { $$D.setStyle( viewer, styles ); }
},
repair: function(e, pos) {
var zoom = this._zoom,
viewerWidth = this ._viewerWidth,
viewerHeight = this._viewerHeight;
pos.left = ( viewerWidth / 2 - pos.left ) * ( viewerWidth / zoom.width - 1 );
pos.top = ( viewerHeight / 2 - pos.top ) * ( viewerHeight / zoom.height - 1 );
},
move: function(e) {
var style = this._viewer.style;
style.left = e.pageX - this._repairFollowLeft "px";
style.top = e.pageY - this._repairFollowTop "px";
},
dispose: function() {
$$D. setStyle( this._viewer, this._stylesFollow );
}
}
},
//Drag handle
"handle": {
options: {//Default value
handle: ""//Drag handle object
},
methods: {
init: function() {
var handle = $$( this.options.handle );
if ( !handle ) {//If not defined, replace the display box with a copy
var body = document.body;
handle = body.insertBefore(this._viewer.cloneNode(false), body.childNodes[0] ; 0, margin: 0, display: "none" } );
this._handle = handle;
this._repairHandleLeft = 0;//Correction coordinates left
this._repairHandleTop = 0;/ /Correction top
},
load: function() {
var handle = this._handle, rect = this._rect;
$$D.setStyle( handle, {
position : "absolute",
width: this._rangeWidth "px",
height: this._rangeHeight "px",
display: "block",
visibility: "hidden"
} );
//Get the correction parameters
this._repairHandleLeft = rect.left this._repairLeft - handle.clientLeft;
this._repairHandleTop = rect.top this._repairTop - handle.clientTop;
/ /Correct offsetParent position
if ( !/BODY|HTML/.test( handle.offsetParent.nodeName ) ) {
var parent = handle.offsetParent, rect = $$D.rect( parent );
this._repairHandleLeft -= rect.left parent.clientLeft;
this._repairHandleTop -= rect.top parent.clientTop;
}
//Hide
$$D.setStyle( handle, { display : "none", visibility: "visible" });
},
start: function() {
this._handle.style.display = "block";
},
move: function(e, x, y) {
var style = this._handle.style, scale = this._scale;
style.left = Math.ceil( this._repairHandleLeft - x / scale ) "px ";
style.top = Math.ceil( this._repairHandleTop - y / scale ) "px";
},
end: function() {
this._handle.style.display = "none";
},
dispose: function() {
if( "_createbyhandle" in this._handle ){ document.body.removeChild( this._handle ); }
this._handle = null;
}
}
},
//Cut
"cropper": {
options: {//Default value
opacity: .5//Transparency
},
methods: {
init: function() {
var body = document.body,
cropper = body.insertBefore(document.createElement("img"), body. childNodes[0]);
cropper.style.display = "none";
this._cropper = cropper;
this.opacity = this.options.opacity;
},
load: function() {
var cropper = this._cropper, image = this._image, rect = this._rect;
cropper.src = image.src;
cropper.width = image. width;
cropper.height = image.height;
$$D.setStyle( cropper, {
position: "absolute",
left: rect.left this._repairLeft "px",
top: rect.top this._repairTop "px"
});
},
start: function() {
this._cropper.style.display = "block";
$$D.setStyle( this._image, "opacity", this.opacity );
},
move: function(e, x, y) {
var w = this._rangeWidth, h = this._rangeHeight, scale = this._scale;
x = Math.ceil( -x / scale ); y = Math.ceil( -y / scale );
this._cropper.style.clip = " rect(" y "px " (x w) "px " (y h) "px " x "px)";
},
end: function() {
$$D.setStyle( this._image, "opacity", 1 );
this._cropper.style.display = "none";
},
dispose: function() {
document.body.removeChild( this._cropper );
this._cropper = null;
}
}
}
}
ImageZoom.prototype._initialize = (function(){
var init = ImageZoom.prototype._initialize,
mode = ImageZoom._MODE,
modes = {
"follow": [ mode.follow ],
"handle": [ mode.handle ],
"cropper": [ mode.cropper ],
"handle-cropper": [ mode.handle, mode.cropper ]
};
return function(){
var options = arguments[2];
if ( options && options.mode && modes[ options.mode ] ) {
$$A.forEach( modes[ options.mode ], function( mode ){
//扩展options
$$.extend( options, mode.options, false );
//扩展钩子
$$A.forEach( mode.methods, function( method, name ){
$$CE.addEvent( this, name, method );
}, this );
}, this );
}
init.apply( this, arguments );
}
})();
在线演示地址
http://demo.jb51.net/js/ImageZoom_ext/ImageZoom_ext.htm打包下载地址
http://www.jb51.net/jiaoben/25809.html出处:http://www.cnblogs.com/cloudgamer/