前端工程师小A学习JS的旅程
前端工程师小A学习JS的旅程
前端工程师小A学习JS的旅程
在网页里, 拖拽效果是很常见的形式,实现起来也比较简单,但是这么简单的代码,却能体现出很多前端开发工程湿的JS能力,我们来看看小A工程师的实现路程:
HTML代码:
<! DOCTYPE HTML >
< html >
< head >
< title > 拖拽效果 </ title >
< meta charset ="UTF-8" >
< meta http-equiv ="X-UA-Compatible" content ="IE=Edge,chrome=1" >
< style type ="text/css" >
#drag_box { width : 150px ; height : 150px ; background-color : #ff0000 ; position : absolute ; margin : 0 ; top : 80px ; left : 0 ; }
#diy,#dix { width : 70px ; display : inline-block ; height : 30px ; }
</ style >
</ head >
< body >
< span id ="dix" > X:0px </ span >
< input type ="button" value ="锁定X轴" id ="closeX" data-open ="true" >
< br />
< span id ="diy" > Y:80px </ span >
< input type ="button" value ="锁定Y轴" id ="closeY" data-open ="true" >
< div id ="drag_box" ></ div >
</ body >
</ html >
JS代码:
小A的拖拽JS代码第一版
<script type="text/javascript">
var closeX=document.getElementById("closeX"),closeY=document.getElementById("closeY" );
closeX.onclick = function (){
if ( this .getAttribute("data-open")=="true" ){
this .setAttribute("data-open","false" );
this .value="解开X轴" ;
} else {
this .setAttribute("data-open","true" );
this .value="锁定X轴" ;
}
}
closeY.onclick = function (){
if ( this .getAttribute("data-open")=="true" ){
this .setAttribute("data-open","false" );
this .value="解开Y轴" ;
} else {
this .setAttribute("data-open","true" );
this .value="锁定Y轴" ;
}
}
var box=document.getElementById('drag_box' );
var x=y=0 ;
var dix=document.getElementById("dix"),diy=document.getElementById("diy" );
box.onmousedown = function (event){
var event=event|| window.event;
x =event.clientX- this .offsetLeft;
y =event.clientY- this .offsetTop;
this .style.cursor="move" ;
var that = this ;
document.onmousemove = function (event){
var event=event|| window.event;
var le=event.clientX-x,to=event.clientY- y;
var maxL = document.documentElement.clientWidth - box.offsetWidth;
var maxT = document.documentElement.clientHeight - box.offsetHeight;
if (le<0 ){
le =0
} else if (le> maxL){
le = maxL;
}
if (to<80 ){
to =80
} else if (to> maxT){
to = maxT;
}
if (closeX.getAttribute("data-open")=="true" ){
that.style.left =le+"px" ;
dix.innerHTML ="X:"+le+"px" ;
}
if (closeY.getAttribute("data-open")=="true" ){
that.style.top =to+"px" ;
diy.innerHTML ="Y:"+to+"px" ;
}
if (that.releaseCapture){
that.releaseCapture();
}
return false ;
}
this .onmouseup= function (){
document.onmousemove = null ;
document.onmouseup = null ;
this .style.cursor="default" ;
if ( this .releaseCapture){
this .releaseCapture();
}
return false ;
}
if ( this .releaseCapture){
this .releaseCapture();
}
return false ;
}
</script>
这是小A初学JS一个月写出来的JS代码,完美实现了拖拽的功能,并且也能也能注意在适当的时候阻止事件的默认行为,还能用上 if(this.releaseCapture){ this.releaseCapture(); }这样的语句来防止鼠标离开拖拽BOX。对于小A来说,学习一个月能写出这样的代码来已经实属不易,我们也不得不承认小A是一个学习能力很强的前端工程师。
又学习了一个月小A学到了js的封装,于是重新看了看上面的代码,觉得处理锁定X轴和锁定Y轴的代码有些重复,而且拖拽的对象可能会发生变化,于是小A改造了一下上面的代码,创建了两个方法函数 drag和closexy把主体功能封转在两个函数里面:
小A的拖拽JS代码第二版
<script type="text/javascript">
function drag (box) {
var x=y=0 ;
var dix=document.getElementById("dix"),diy=document.getElementById("diy" );
box.onmousedown = function (event){
var event=event|| window.event;
x =event.clientX- this .offsetLeft;
y =event.clientY- this .offsetTop;
this .style.cursor="move" ;
var that = this ;
document.onmousemove = function (event){
var event=event|| window.event;
var le=event.clientX-x,to=event.clientY- y;
var maxL = document.documentElement.clientWidth - box.offsetWidth;
var maxT = document.documentElement.clientHeight - box.offsetHeight;
if (le<0 ){
le =0
} else if (le> maxL){
le = maxL;
}
if (to<80 ){
to =80
} else if (to> maxT){
to = maxT;
}
if (closeX.getAttribute("data-open")=="true" ){
that.style.left =le+"px" ;
dix.innerHTML ="X:"+le+"px" ;
}
if (closeY.getAttribute("data-open")=="true" ){
that.style.top =to+"px" ;
diy.innerHTML ="Y:"+to+"px" ;
}
if (that.releaseCapture){
that.releaseCapture();
}
return false ;
}
this .onmouseup= function (){
document.onmousemove = null ;
document.onmouseup = null ;
this .style.cursor="default" ;
if ( this .releaseCapture){
this .releaseCapture();
}
return false ;
}
if ( this .releaseCapture){
this .releaseCapture();
}
return false ;
}
}
function closexy(xy,obj){
if (obj.getAttribute("data-open")=="true" ){
obj.setAttribute( "data-open","false" );
obj.value ="解开"+xy+"轴" ;
} else {
obj.setAttribute( "data-open","true" );
obj.value ="锁定"+xy+"轴" ;
}
}
var box=document.getElementById('drag_box' );
drag(box);
var closeX=document.getElementById("closeX"),closeY=document.getElementById("closeY" );
closeX.onclick = function (){
closexy( "X", this );
}
closeY.onclick = function (){
closexy( "Y", this );
}
</script>
这样一看,代码量减少了许多,而且显得也比较调理,更重要的是封转后的方法在随意的对象上都可以调用,简单、方便!此时的小A学习js的激情高涨,于是就更加勤奋的学习!
又不知过了多久。小A的js水平有了大幅提高,这个时候小A回头看之前写过的拖拽代码,觉得有很多不妥的地方,比如:没有注意命名空间,没有成模块化、如果拖拽的外围边界不是body了怎么变、如果拖拽的范围变化了呢,拖拽的锁定可不可以做成开放性的呢。基于这些问题,于是小A觉得完全可以把拖拽功能做成一个拖拽库,开放接口,以应付千变万化的拖拽效果和需求,所以小A又写了第三版的拖拽JS代码:
小A的拖拽JS代码第三版
<script type="text/javascript">
/* *
* * dragBox:拖动对象,可以是对象的ID;
* * options:参数;
* * maxContainer:设置拖动外围box,默认为body;
* * minL:离外围边界左边最小距离,默认为0;
* * maxL:离外边界左边最大距离,默认body的宽度-拖动对象宽度;
* * minT:离外围边界上边最小距离,默认为0;
* * maxT:离外围边界最大高度,默认为body高度-拖动对象高度;
* * lockx:是否锁定X轴,默认不锁定;
* * locky:是否锁定Y轴,默认不锁定;
* * onStart:开始拖动回调函数;
* * onMove:拖动过程中回调函数;
* * onStop:拖动结束回调函数;
*/
function Drag(){
this .init.apply( this ,arguments);
}
Drag.prototype = {
init: function (dragBox,options){
this .dragBox= this .$(dragBox);
this .setOptions(options);
this ._moveDrag= this .bind( this , this .moveDrag);
this ._stopDrag= this .bind( this , this .stopDrag);
this .maxContainer = this .options.maxContainer||document.documentElement || document.body;
this .minL= this .options.minL||0 ;
this .maxL= this .options.maxL||Math.max( this .maxContainer.clientWidth, this .maxContainer.scrollWidth)- this .dragBox.offsetWidth;
this .minT= this .options.minT||0 ;
this .maxT= this .options.maxT||Math.max( this .maxContainer.clientHeight, this .maxContainer.scrollHeight)- this .dragBox.offsetHeight;
this .lockx = this .options.lockx|| false ;
this .locky = this .options.locky|| false ;
this .onStart= this .options.onStart|| null ;
this .onMove= this .options.onMove|| null ;
this .onStop= this .options.onStop|| null ;
this .addHandle( this .dragBox, "mousedown", this .bind( this , this .startDrag));
this .haslayout();
},
haslayout: function (){
this .dragBox.style.left= this .minL+"px" ;
this .dragBox.style.top= this .minT+"px" ;
},
startDrag: function (event){
var event=event|| window.event;
this ._x=event.clientX- this .dragBox.offsetLeft;
this ._y=event.clientY- this .dragBox.offsetTop;
this .addHandle(document,"mousemove", this ._moveDrag);
this .addHandle(document,"mouseup", this ._stopDrag);
this .preventDefault(event);
this .dragBox.setCapture && this .dragBox.setCapture();
if ( typeof onStart==="function" ){
this .onStart();
}
},
moveDrag: function (event){
var event=event|| window.event;
this .dragBox.style.cursor = "move" ;
var le=event.clientX- this ._x,to=event.clientY- this ._y;
if (le< this .minL){
le = this .minL
} else if (le> this .maxL){
le = this .maxL;
}
if (to< this .minT){
to = this .minT;
} else if (to> this .maxT){
to = this .maxT;
}
if (! this .lockx){
this .dragBox.style.left=le+"px" ;
}
if (! this .locky){
this .dragBox.style.top=to+"px" ;
}
this .preventDefault(event);
this .dragBox.setCapture && this .dragBox.setCapture();
if ( typeof onMove==="function" ){
this .onMove();
}
},
stopDrag: function (){
this .removeHandle(document,"mousemove", this ._moveDrag);
this .removeHandle(document,"mouseup", this ._stopDrag);
this .dragBox.style.cursor = "default" ;
this .dragBox.setCapture && this .dragBox.setCapture();
if ( typeof onStop==="function" ){
this .onStop();
}
},
$: function (id){
return typeof id=="string" ? document.getElementById(id):id;
},
addHandle: function (element,type,handler){
if (element.addEventListener){
element.addEventListener(type,handler, false );
} else if (element.attachEvent){
element.attachEvent( "on"+ type,handler);
} else {
element[ "on"+type]= handler;
}
},
removeHandle: function (element,type,handler){
if (element.removeEventListener){
element.removeEventListener(type,handler, false );
} else if (element.detachEvent){
element.detachEvent( "on"+ type,handler);
} else {
element[ "on"+type]= null ;
}
},
preventDefault: function (event){
if (event.preventDefault){
event.preventDefault();
} else {
event.returnValue = false ;
}
},
setOptions : function (options){
this .options = {};
for ( var p in options) this .options[p] = options[p];
},
bind : function (object, fnHandler){
return function (){
return fnHandler.apply(object, arguments)
}
}
};
// 应用
var box=document.getElementById("drag_box" );
var Mydrag= new Drag(box,{
minT: 10 ,
maxT: 100 ,
lockx: true
});
</script>
这样,一个功能齐全的拖拽库就这样漂亮的诞生了!拖拽库开放接口很齐全,代码页很规范。从此小A就不用害怕任何拖拽功能需求了!
从小A学习js的旅程,我们可以看出,学习JS是一个循序渐进的过程,看似简单的功能,从最开始的实现功能,到不断改进,一直到最后写成一个插件,可以有很多版本,而这些不断改进的过程正是学习JS最好的方法!
标签: javascript
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息