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 相关文章推荐
High Performance JavaScript(高性能JavaScript)读书笔记分析
May 05 Javascript
Node.js与Sails ~项目结构与Mvc实现及日志机制
Oct 14 Javascript
JS实现Fisheye效果动感放大菜单代码
Oct 21 Javascript
用jQuery获取table中行id和td值的实现代码
May 19 Javascript
浅谈js中的三种继承方式及其优缺点
Aug 10 Javascript
Vuejs第六篇之Vuejs与form元素实例解析
Sep 05 Javascript
Bootstrap 模态框(Modal)插件代码解析
Dec 21 Javascript
微信小程序实现天气预报功能
Jul 18 Javascript
vue实现的请求服务器端API接口示例
May 25 Javascript
详解django模板与vue.js冲突问题
Jul 07 Javascript
八种Vue组件间通讯方式合集(推荐)
Aug 18 Javascript
利用js实现简单开关灯代码
Nov 23 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
简单的过滤字符串中的HTML标记
2006/12/25 PHP
php有效防止同一用户多次登录
2015/11/19 PHP
ThinkPHP中html:list标签用法分析
2016/01/09 PHP
PHP面向对象程序设计之类与反射API详解
2016/12/02 PHP
PHP中数组转换为SimpleXML教程
2019/01/27 PHP
iframe父页面获取子页面参数的方法
2014/02/21 Javascript
NodeJS学习笔记之网络编程
2014/08/03 NodeJs
jquery实现的树形目录实例
2015/06/26 Javascript
javascript实现输出指定行数正方形图案的方法
2015/08/03 Javascript
JS实现仿QQ面板的手风琴效果折叠菜单代码
2015/09/11 Javascript
JavaScript和HTML DOM的区别与联系及Javascript和DOM的关系
2015/11/15 Javascript
Js实现简单的小球运动特效
2016/02/18 Javascript
Angular.js与Bootstrap相结合实现手风琴菜单代码
2016/04/13 Javascript
JS命令模式例子之菜单程序
2016/10/10 Javascript
Ajax 加载数据 练习代码
2017/01/05 Javascript
js实现简单的网页换肤效果
2017/01/18 Javascript
AngularJS自定义指令之复制指令实现方法
2017/05/18 Javascript
Node.js调用fs.renameSync报错(Error: EXDEV, cross-device link not permitted)
2017/12/27 Javascript
JS严格模式知识点总结
2018/02/27 Javascript
JS返回页面时自动回滚到历史浏览位置
2018/09/26 Javascript
大转盘抽奖小程序版 转盘抽奖网页版
2020/04/16 Javascript
JavaScript 装逼指南(js另类写法)
2020/05/10 Javascript
vue自定义树状结构图的实现方法
2020/10/18 Javascript
利用Python开发微信支付的注意事项
2016/08/19 Python
pygame游戏之旅 游戏中添加显示文字
2018/11/20 Python
django执行原始查询sql,并返回Dict字典例子
2020/04/01 Python
Django ORM实现按天获取数据去重求和例子
2020/05/18 Python
HTML5的结构和语义(4):语义性的内联元素
2008/10/17 HTML / CSS
HTML5中的websocket实现直播功能
2018/05/21 HTML / CSS
linux面试题参考答案(7)
2014/07/24 面试题
大学生毕业个人总结
2015/02/15 职场文书
公司员工辞职信范文
2015/05/12 职场文书
党员学习型组织心得体会
2019/06/21 职场文书
创业计划书之香辣虾火锅
2019/09/23 职场文书
导游词之吉林吉塔
2019/11/11 职场文书
Golang 如何实现函数的任意类型传参
2021/04/29 Golang