cloudgamer出品ImageZoom 图片放大效果


Posted in Javascript onApril 01, 2010

一般用于放大查看商品图片,在凡客,京东商城,阿里巴巴等都有类似的效果。
好处是能在原图附近对图片进行局部放大查看,而且可以通过鼠标控制查看的部位。
前一阵子看到sohighthesky的图片放大效果,心血来潮自己也写一个看看。
这个程序有以下特点:
1,支持使用原图放大或新图片设置大图;
2,大图完成载入前使用原图放大代替,减少操作等待时间;
3,支持鼠标滚动缩放大图;
4,可以通过设置显示范围或显示框大小设置显示尺寸;
5,可以设置是否自动隐藏显示框;
6,支持插件形式的扩展来实现更多的功能(下一篇再详细介绍)。
兼容:ie6/7/8, firefox 3.6.2, opera 10.51, safari 4.0.4, chrome 4.1

var styles; 
if ( !viewer.clientWidth ) { 
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 );

注意,显示范围是通过clientWidth/clientHeight来获取的。
如果显示框是display为none的隐藏状态,就不能直接获取clientWidth/clientHeight。
这种情况下,程序用以下方法获取:
1,记录display/position/visibility的原始值;
2,分别设为"block"/"absolute"/"hidden",这是既能隐藏也能占位的状态;
3,获取参数;
4,重新设回原始值,恢复原来的状态。
得到显示范围后,再配合比例就能得到范围参数了。
ps:这是通用的获取不占位元素尺寸参数的方法,jquery的css也是用这个方法获取width/height的。
比例计算后可能会得到小数,而尺寸大小只能是整数,程序一律使用Math.ceil来取整。
【放大效果】
所有东西都设置好后,就可以执行start设置触发程序了。
程序会自动执行start方法,里面主要是给原图对象的mouseover/mousemove绑定_start程序:
var image = this._image, START = this._START;
$$E.addEvent( image, "mouseover", START );
$$E.addEvent( image, "mousemove", START );
分别对应移入原图对象和在原图对象上移动的情况。
ps:如果使用attachEvent的话还要注意重复绑定同一函数的问题,这里的addEvent就没有这个问题。
绑定的_start程序,主要是进行一些事件的解绑和绑定:
$$E.removeEvent( image, "mouseover", this._START ); 
$$E.removeEvent( image, "mousemove", this._START ); 
$$E.addEvent( document, "mousemove", this._MOVE ); 
$$E.addEvent( document, "mouseout", this._OUT );

为了在移出窗口时能结束放大效果,给document的mouseout绑定了_OUT程序:
this._OUT = $$F.bindAsEventListener( function(e){ 
if ( !e.relatedTarget ) this._END(); 
}, this );

当鼠标移出document会触发mouseout,如果当前relatedTarget是null的话,就延时执行_end结束程序:
var oThis = this, END = function(){ oThis._end(); };
this._END = function(){ oThis._timer = setTimeout( END, oThis.delay ); };
在_end程序中,会先执行stop方法,在里面移除所有可能绑定的事件,再执行start方法继续等待触发。
而mousemove绑定的_move移动程序,主要用来实现鼠标移动到哪里就放大哪里的功能。
为适应更多的情况(例如扩展篇的其他模式),把它绑定到document上,但也因此不能用mouseout事件来触发移出程序。
程序通过鼠标和原图的坐标比较,来判断鼠标是否移出原图对象范围:
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(); 
} else { 
... 
}

如果鼠标移出原图对象的话,就执行_END结束放大效果。
如果鼠标在原图对象上移动,就计算坐标,并通过_repair程序把坐标转化成定位需要的值。
最后设置大图的left/top定位使显示框显示要放大的部位。
ps:我尝试过用scrollLeft/scrollTop来做定位,但发现这样在ie中会像锯齿那样移动,放得越大越明显,所以放弃。
【鼠标滚动缩放】
如果设置mouse属性为true,就会开启鼠标滚动缩放功能。
在执行放大效果期间,可以通过滚动鼠标滚轮对大图进行缩放处理。
其实就是根据滚轮动参数的变化来修改放大比例。
关于鼠标滚动事件,在slider中也提过,不过那时只分析了ie和ff的区别,这里再分析一下。
首先ie是用mousewheel绑定事件的,使用event的wheelDelta来获取滚动参数。
其他浏览器用以下代码测试:
<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<body style="height:1000px;"> 
<script> 
function test(e){ alert(e.type+":"+e.detail+"_"+e.wheelDelta) } 
document.addEventListener( "DOMMouseScroll", test, false ); 
document.addEventListener( "mousewheel", test, false ); 
</script> 
</body> 
</html>

向下滚动一下,可以得到以下结果:
ff:DOMMouseScroll:3_undefined
opera:mousewheel:3_-120
chrome/safari:mousewheel:0_-120
可以看到事件的绑定,ff只支持DOMMouseScroll,其他就只支持mousewheel。
而滚动参数的获取,ff只支持detail,opera两种都支持,chrome/safari就支持wheelDelta。
ps:不明白chrome/safari的detail为什么是0,有其他用途?
而DOMMouseScroll跟mousewheel还有一个不同是前者不能直接绑定元素,后者可以。
即可以elem.onmousewheel,但不能elem.onDOMMouseScroll。
根据以上分析,在_start程序里是这样把_mouse程序绑定到document的滚动事件中:
this.mouse && $$E.addEvent( document, $$B.firefox ? "DOMMouseScroll" : "mousewheel", this._MOUSE );
在_mouse程序里面根据滚动参数和自定义的rate缩放比率得到新的放大比例:
this._scale += ( e.wheelDelta ? e.wheelDelta / (-120) : (e.detail || 0) / 3 ) * this.rate;
修改比例时,程序参数也需要重新计算。
由于_rangeWidth/_rangeHeight会影响计算的过程,要重新恢复成自定义的默认值:
var opt = this.options;
this._rangeWidth = opt.rangeWidth;
this._rangeHeight = opt.rangeHeight;
然后执行_initSize和_initData重新设置尺寸和参数,再执行_move重新定位。
最后记得用preventDefault防止触发页面滚动。
使用技巧
【图片设置】
程序支持大图使用原图放大或用新大图。
如果用新大图而且图片比较大的话,强烈建议设置放大比例,这样程序会自动在大图载入前先使用原图放大,这样就不用等待大图加载完成。
还要注意新大图本身的宽高比例要跟原图一致,否则就对不准坐标了,使用原图放大就没有这个问题。
【显示框设置】
有两个方法可以设置显示框的尺寸:
要固定显示范围的话,先设置rangeWidth/rangeHeight,程序会根据显示范围和放大比例计算显示框的尺寸;
要用显示框当前的尺寸来显示的话,只要不设置rangeWidth/rangeHeight或设为0就可以了。
【reset】
由于各个属性和对象之间有很多的关联,很多属性不能直接修改。
程序设置了一个reset方法专门用来修改这类属性的。
如果程序加载完成后又修改了影响程序计算的样式,例如原图大小,显示框大小等,也要执行一次reset来重新设置参数和属性。
【浮动定位】
程序没有设置显示框浮动定位的功能,需要的话可以自行添加。
简单的定位可以参考实例的方法,还要小心覆盖select的问题。
如果要更复杂的浮动定位,可以参考“浮动定位提示效果”。
【opera的bug】
测试中发现opera 10.10有两个bug。
分别是img元素设置透明时会看到背景图,用js修改鼠标样式会有问题。
不过这两个问题在10.50都已经修复了,还没升级的赶快升啦。
【maxthon的bug】
用maxthon 2.5.1测试时发现一个问题,测试以下代码:
<div id="t" style="width:50px;"></div> 
<script> 
var t=document.getElementById("t"); 
t.clientWidth; 
t.style.display="none"; 
alert(t.clientWidth); 
</script>

一般来说用display隐藏后,clientWidth应该是0的,但maxthon貌似没有处理这个情况。
这会影响到程序中clientWidth的判断,不过对一般使用没什么影响。
我已经提交了这个问题,不知会不会处理。
使用说明
实例化时,必须有一个img元素作为原图对象,和一个容器作为显示框:
var iz = new ImageZoom( "idImage", "idViewer" );
可选参数用来设置系统的默认属性,包括:
属性: 默认值//说明
mode: "simple",//模式
scale: 0,//比例(大图/原图)
max: 10,//最大比例
min: 1.5,//最小比例
originPic: "",//原图地址
zoomPic: "",//大图地址
rangeWidth: 0,//显示范围宽度
rangeHeight:0,//显示范围高度
delay: 20,//延迟结束时间
autoHide: true,//是否自动隐藏
mouse: false,//鼠标缩放
rate: .2,//鼠标缩放比率
onLoad: $$.emptyFunction,//加载完成时执行
onStart: $$.emptyFunction,//开始放大时执行
onMove: $$.emptyFunction,//放大移动时执行
onEnd: $$.emptyFunction//放大结束时执行
其中模式的使用在下一篇扩展篇再说明。
初始化后,scale、max、min、originPic、zoomPic、rangeWidth、rangeHeight这些属性需要用reset方法来修改。
还提供了以下方法:
start:开始放大程序(程序会自动执行);
stop:停止放大程序;
reset:修改设置;
dispose:销毁程序。
程序源码
var ImageZoom = function(image, viewer, options) { 
this._initialize( image, viewer, options ); 
this._initMode( this.options.mode ); 
this._oninit(); 
this._initLoad(); 
}; 
ImageZoom.prototype = { 
//初始化程序 
_initialize: function(image, viewer, options) { 
this._image = $$(image);//原图 
this._zoom = document.createElement("img");//显示图 
this._viewer = $$(viewer);//显示框 
this._viewerWidth = 0;//显示框宽 
this._viewerHeight = 0;//显示框高 
this._preload = new Image();//预载对象 
this._rect = null;//原图坐标 
this._repairLeft = 0;//显示图x坐标修正 
this._repairTop = 0;//显示图y坐标修正 
this._rangeWidth = 0;//显示范围宽度 
this._rangeHeight = 0;//显示范围高度 
this._timer = null;//计时器 
this._loaded = false;//是否加载 
this._substitute = false;//是否替换 
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 ); 
}, 
//设置默认属性 
_setOptions: function(options) { 
this.options = {//默认值 
mode: "simple",//模式 
scale: 0,//比例(大图/原图) 
max: 10,//最大比例 
min: 1.5,//最小比例 
originPic: "",//原图地址 
zoomPic: "",//大图地址 
rangeWidth: 0,//显示范围宽度 
rangeHeight:0,//显示范围高度 
delay: 20,//延迟结束时间 
autoHide: true,//是否自动隐藏 
mouse: false,//鼠标缩放 
rate: .2,//鼠标缩放比率 
onLoad: $$.emptyFunction,//加载完成时执行 
onStart: $$.emptyFunction,//开始放大时执行 
onMove: $$.emptyFunction,//放大移动时执行 
onEnd: $$.emptyFunction//放大结束时执行 
}; 
return $$.extend(this.options, options || {}); 
}, 
//根据模式初始化函数属性 
_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; 
}, 
//初始化加载 
_initLoad: function() { 
var image = this._image, originPic = this._originPic, 
useOrigin = !this._zoomPic && this._scale, 
loadImage = $$F.bind( useOrigin ? this._loadOriginImage : this._loadImage, this ); 
//设置自动隐藏 
if ( this.autoHide ) { this._viewer.style.display = "none"; } 
//先加载原图 
if ( originPic && originPic != image.src ) {//使用自定义地址 
image.onload = loadImage; 
image.src = originPic; 
} else if ( image.src ) {//使用元素地址 
if ( !image.complete ) {//未载入完 
image.onload = loadImage; 
} else {//已经载入 
loadImage(); 
} 
} else { 
return;//没有原图地址 
} 
//加载大图 
if ( !useOrigin ) { 
var preload = this._preload, zoomPic = this._zoomPic || image.src, 
loadPreload = $$F.bind( this._loadPreload, this ); 
if ( zoomPic != preload.src ) {//新地址重新加载 
preload.onload = loadPreload; 
preload.src = zoomPic; 
} else {//正在加载 
if ( !preload.complete ) {//未载入完 
preload.onload = loadPreload; 
} else {//已经载入 
this._loadPreload(); 
} 
} 
} 
}, 
//原图放大加载程序 
_loadOriginImage: function() { 
this._image.onload = null; 
this._zoom.src = this._image.src; 
this._initLoaded(); 
}, 
//原图加载程序 
_loadImage: function() { 
this._image.onload = null; 
if ( this._loaded ) {//大图已经加载 
this._initLoaded(); 
} else { 
this._loaded = true; 
if ( this._scale ) {//有自定义比例才用原图放大替换大图 
this._substitute = true; 
this._zoom.src = this._image.src; 
this._initLoaded(); 
} 
} 
}, 
//大图预载程序 
_loadPreload: function() { 
this._preload.onload = null; 
this._zoom.src = this._preload.src; 
if ( this._loaded ) {//原图已经加载 
//没有使用替换 
if ( !this._substitute ) { this._initLoaded(); } 
} else { 
this._loaded = true; 
} 
}, 
//初始化加载设置 
_initLoaded: function(src) { 
//初始化显示图 
this._initSize(); 
//初始化显示框 
this._initViewer(); 
//初始化数据 
this._initData(); 
//开始执行 
this._onload(); 
this.onLoad(); 
this.start(); 
}, 
//初始化显示图尺寸 
_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 ); 
//按比例设置显示图大小 
zoom.width = Math.ceil( image.width * scale ); 
zoom.height = Math.ceil( image.height * scale ); 
}, 
//初始化显示框 
_initViewer: function() { 
var zoom = this._zoom, viewer = this._viewer; 
//设置样式 
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"; 
//插入显示图 
if ( !$$D.contains( viewer, zoom ) ){ viewer.appendChild( zoom ); } 
}, 
//初始化数据 
_initData: function() { 
var zoom = this._zoom, image = this._image, viewer = this._viewer, 
scale = this._scale, rangeWidth = this._rangeWidth, rangeHeight = this._rangeHeight; 
//原图坐标 
this._rect = $$D.rect( image ); 
//修正参数 
this._repairLeft = image.clientLeft + parseInt($$D.getStyle( image, "padding-left" )); 
this._repairTop = image.clientTop + parseInt($$D.getStyle( image, "padding-top" )); 
//设置范围参数和显示框大小 
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 ) {//隐藏 
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: 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: 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();//移出原图范围 
} else { 
var zoom = this._zoom, 
pos = this._repair( 
x - rect.left - this._repairLeft, 
y - rect.top - this._repairTop 
); 
this._onmove( e, pos ); 
//设置定位 
zoom.style.left = pos.left + "px"; 
zoom.style.top = pos.top + "px"; 
this.onMove(); 
} 
}, 
//修正坐标 
_repair: function(x, y) { 
var scale = this._scale, zoom = this._zoom, 
viewerWidth = this._viewerWidth, 
viewerHeight = this._viewerHeight; 
//修正坐标 
x = Math.ceil( viewerWidth / 2 - x * scale ); 
y = Math.ceil( viewerHeight / 2 - y * scale ); 
//范围限制 
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: 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/

如有任何建议或疑问,欢迎留言讨论。
打包下载地址

Javascript 相关文章推荐
javascript编程起步(第六课)
Feb 27 Javascript
JS实多级联动下拉菜单类,简单实现省市区联动菜单!
May 03 Javascript
javascript实现页面内关键词高亮显示代码
Apr 03 Javascript
js针对ip地址、子网掩码、网关的逻辑性判断
Jan 06 Javascript
jQuery的中 is(':visible') 解析及用法(必看)
Feb 12 Javascript
jQuery初级教程之网站品牌列表效果
Aug 02 jQuery
详解Vue2.0 事件派发与接收
Sep 05 Javascript
jQuery中内容过滤器简单用法示例
Mar 31 jQuery
vue中rem的配置的方法示例
Aug 30 Javascript
微信小程序wx.request的简单封装
Nov 13 Javascript
浅谈Vue static 静态资源路径 和 style问题
Nov 07 Javascript
js实现抽奖功能
Nov 24 Javascript
js 异步处理进度条
Apr 01 #Javascript
JavaScript中String和StringBuffer的速度之争
Apr 01 #Javascript
Cookie 小记
Apr 01 #Javascript
javascript操作cookie的文章(设置,删除cookies)
Apr 01 #Javascript
在模板页面的js使用办法
Apr 01 #Javascript
使用Microsoft Ajax Minifier减小JavaScript文件大小的方法
Apr 01 #Javascript
JS控制显示隐藏兼容问题(IE6、IE7、IE8)
Apr 01 #Javascript
You might like
php静态文件生成类实例分析
2015/01/03 PHP
[原创]smarty简单模板变量输出方法
2016/07/09 PHP
javascript 获取页面的高度及滚动条的位置的代码
2010/05/06 Javascript
jquery实现的可隐藏重现的靠边悬浮层实例代码
2013/05/27 Javascript
将json当数据库一样操作的javascript lib
2013/10/28 Javascript
jquery bind(click)传参让列表中每行绑定一个事件
2014/08/06 Javascript
node.js中的path.sep方法使用说明
2014/12/08 Javascript
原生js实现倒计时功能(多种格式调用)
2017/01/12 Javascript
jQuery按需加载轮播图(web前端性能优化)
2017/02/17 Javascript
Angular 4依赖注入学习教程之FactoryProvider配置依赖对象(五)
2017/06/04 Javascript
使用element-ui table expand展开行实现手风琴效果
2019/03/15 Javascript
JS实现的字符串数组去重功能小结
2019/06/17 Javascript
vue tab滚动到一定高度,固定在顶部,点击tab切换不同的内容操作
2020/07/22 Javascript
vue+vant实现购物车全选和反选功能
2020/11/17 Vue.js
Python实现把回车符\r\n转换成\n
2015/04/23 Python
Python开发SQLite3数据库相关操作详解【连接,查询,插入,更新,删除,关闭等】
2017/07/27 Python
Python 操作文件的基本方法总结
2017/08/10 Python
python3 发送任意文件邮件的实例
2018/01/23 Python
基于Python实现的微信好友数据分析
2018/02/26 Python
对python sklearn one-hot编码详解
2018/07/10 Python
Python 用matplotlib画以时间日期为x轴的图像
2019/08/06 Python
Python 爬虫性能相关总结
2020/08/03 Python
Python 在局部变量域中执行代码
2020/08/07 Python
python使用matplotlib:subplot绘制多个子图的示例
2020/09/24 Python
Melissa鞋马来西亚官方网站:MDreams马来西亚
2018/04/05 全球购物
意大利网上购书网站:Libraccio.it
2021/02/03 全球购物
《我的伯父鲁迅先生》教学反思
2014/02/12 职场文书
最经典的大学生职业生涯规划范文
2014/03/05 职场文书
风险评估实施方案
2014/03/09 职场文书
优秀少先队员主要事迹材料
2014/05/28 职场文书
计算机网络专业求职信
2014/06/05 职场文书
拉歌口号大全
2014/06/13 职场文书
机关领导查摆四风思想汇报
2014/09/13 职场文书
导游词格式
2015/02/13 职场文书
应届毕业生求职信范文
2015/03/19 职场文书
小学教师求职信范文
2015/03/20 职场文书