扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
javascript 实现拖拽实现原理。如下:
10多年的稷山网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。网络营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整稷山建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“稷山网站设计”,“稷山网站推广”以来,每个客户项目都认真落实执行。
用JavaScript事件方法表示就是:
① onmousedown + onmousemove → startDrag()
② onmouseup → stopDrag()
1.首先调用js文件,如下:
script src="" type="text/javascript"/script
2.然后使用startDrag()方法绑定拖拽效果,startDrag()方法有两个参数,第一个是点击的对象(即点击那里可以实现拖拽,例如弹出层的标题栏),第二个是拖拽的对象(例如一个弹出层)。也就是startDrag(触发拖拽对象,被拖拽对象)。
style type="text/css"
#box{position:absolute; left:100px; top:100px; padding:5px; background:#f0f3f9; font-size:12px; -moz-box-shadow:2px 2px 4px #666666; -webkit-box-shadow:2px 2px 4px #666666;}
#main{border:1px solid #a0b3d6; background:white;}
#bar{line-height:24px; background:#beceeb; border-bottom:1px solid #a0b3d6; padding-left:5px; cursor:move;}
#content{width:420px; height:250px; padding:10px 5px;}
/style
div id="box"
div id="main"
div id="bar"拖拽/div
div id="content"
内容……
/div
/div
/div
JS部分
script src="" type="text/javascript"/script
script type="text/javascript"
var oBox = document.getElementById("box");
var oBar = document.getElementById("bar");
startDrag(oBar, oBox);
/script
Javascript的特点是dom的处理与网页效果,大多数情况我们只用到了这个语言的最简单的功能,比如制作图片轮播/网页的tab等等,这篇文章将向你展示如何在自己的网页上制作拖拽.
有很多理由让你的网站加入拖拽功能,最简单的一个是数据重组.例如:你有一个序列的内容让用户排序,用户需要给每个条目进行输入或者用select 选择,替代前面这个方法的就是拖拽.或许你的网站也需要一个用户可以拖动的导航窗口!那么这些效果都是很简单:因为你可以很容易的实现!
网页上实现拖拽其实也不是很复杂.第一你需要知道鼠标坐标,第二你需要知道用户鼠标点击一个网页元素并实现拖拽,最后我们要实现移动这个元素.
获取鼠标移动信息
第一我们需要获取鼠标的坐标.我们加一个用户函数到document.onmousemove就可以了:
Java代码 收藏代码
document.onmousemove = mouseMove;
function mouseMove(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
}
function mouseCoords(ev){
if(ev.pageX || ev.pageY){
return {x:ev.pageX, y:ev.pageY};
}
return {
x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
y:ev.clientY + document.body.scrollTop - document.body.clientTop
};
}
你首先要声明一个evnet对象.不论何时你移动鼠标/点击/按键等等,会对应一个event的事件.在Internet Explorer里event是全局变量,会被存储在window.event里. 在firefox中,或者其他浏览器,event事件会被相应的自定义函数获取.当我们将mouseMove函数赋值于document.onmousemove,mouseMove会获取鼠标移动事件.
(ev = ev || window.event) 这样让ev在所有浏览器下获取了event事件,在Firefox下"||window.event"将不起作用,因为ev已经有了赋值.在MSIE下ev是空的,所以ev将设置为window.event.
因为我们在这篇文章中需要多次获取鼠标坐标,所以我们设计了mouseCoords这个函数,它只包含了一个参数,就是the event.
我们需要运行在MSIE与Firefox为首的其他浏览器下.Firefox以event.pageX和event.pageY来代表鼠标相应于文档左上角的位置.如果你有一个500*500的窗口,而且你的鼠标在正中间,那么paegX和pageY将是250,当你将页面往下滚动500px,那么 pageY将是750.此时pageX不变,还是250.
MSIE和这个相反,MSIE将event.clientX与event.clientY来代表鼠标与ie窗口的位置,并不是文档.当我们有一个 500*500的窗口,鼠标在正中间,那么clientX与clientY也是250,如果你垂直滚动窗口到任何位置,clientY仍然是250,因为相对ie窗口并没有变化.想得到正确的结果,我们必须加入scrollLeft与scrollTop这两个相对于文档鼠标位置的属性.最后,由于MSIE 并没有0,0的文档起始位置,因为通常会设置2px的边框在周围,边框的宽度包含在document.body.clientLeft与 clientTop这两个属性中,我们再加入这些到鼠标的位置中.
很幸运,这样mouseCoords函数就完成了,我们不再为坐标的事操心了.
捕捉鼠标点击
下次我们将知道鼠标何时点击与何时放开.如果我们跳过这一步,我们在做拖拽时将永远不知道鼠标移动上面时的动作,这将是恼人的与违反直觉的.
这里有两个函数帮助我们:onmousedown与onmouseup.我们预先设置函数来接收document.onmousemove,这样看起来很象我们会获取document.onmousedown与document.onmouseup.但是当我们获取 document.onmousedown时,我们同时获取了任何对象的点击属性如:text,images,tables等等.我们只想获取那些需要拖拽的属性,所以我们设置函数来获取我们需要移动的对象.
移动一个元素
我们知道了怎么捕捉鼠标移动与点击.剩下的就是移动元素了.首先,要确定一个明确的页面位置,css样式表要用'absolute'.设置元素绝对位置意味着我们可以用样式表的.top和.left来定位,可以用相对位置来定位了.我们将鼠标的移动全部相对页面top-left,基于这点,我们可以进行下一步了.
当我们定义item.style.position='absolute',所有的操作都是改变left坐标与top坐标,然后它移动了.
Java代码 收藏代码
document.onmousemove = mouseMove;
document.onmouseup = mouseUp;
var dragObject = null;
var mouseOffset = null;
function getMouseOffset(target, ev){
ev = ev || window.event;
var docPos = getPosition(target);
var mousePos = mouseCoords(ev);
return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
}
function getPosition(e){
var left = 0;
var top = 0;
while (e.offsetParent){
left += e.offsetLeft;
top += e.offsetTop;
e = e.offsetParent;
}
left += e.offsetLeft;
top += e.offsetTop;
return {x:left, y:top};
}
function mouseMove(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
if(dragObject){
dragObject.style.position = 'absolute';
dragObject.style.top = mousePos.y - mouseOffset.y;
dragObject.style.left = mousePos.x - mouseOffset.x;
return false;
}
}
function mouseUp(){
dragObject = null;
}
function makeDraggable(item){
if(!item) return;
item.onmousedown = function(ev){
dragObject = this;
mouseOffset = getMouseOffset(this, ev);
return false;
}
}
你会注意到这个代码几乎是前面的全集,将前面的合在一起就实现了拖拽效果了.
当我们点击一个item时,我们就获取了很多变量,如鼠标位置,鼠标位置自然就包含了那个item的坐标信息了.如果我们点击了一个20*20px图像的正中间,那么鼠标的相对坐标为{x:10,y:10}.当我们点击这个图像的左上角那么鼠标的相对坐标为 {x:0,y:0}.当我们点击时,我们用这个方法取得一些鼠标与图片校对的信息.如果我们不能加载页面item,那么信息将是document信息,会忽略了点击的item信息.
mouseOffset函数使用了另一个函数getPosition.getPosition的作用是返回 item相对页面左上角的坐标,如果我们尝试获取item.offsetLeft或者item.style.left,那么我们将取得item相对与父级的位置,不是整个document.所有的脚本我们都是相对整个document,这样会更好一些.
为了完成getPosition任务,必须循环取得item的父级,我们将加载内容到item的左/上的位置.我们需要管理想要的top与left列表.
自从定义了mousemove这个函数,mouseMove就会一直运行.第一我们确定item的 style.position为absolute,第二我们移动item到前面定义好的位置.当mouse点击被释放,dragObject被设置为 null,mouseMove将不在做任何事.
Dropping an Item
前面的例子目的很简单,就是拖拽item到我们希望到的地方.我们经常还有其他目的如删除item,比如我们可以将item拖到垃圾桶里,或者其他页面定义的位置.
很不幸,我们有一个很大的难题,当我们拖拽,item会在鼠标之下,比如mouseove,mousedown,mouseup或者其他mouse action.如果我们拖拽一个item到垃圾桶上,鼠标信息还在item上,不在垃圾桶上.
怎么解决这个问题呢?有几个方法可以来解决.第一,这是以前比较推荐的,我们在移动鼠标时item会跟随鼠标,并占用了mouseover/mousemove等鼠标事件,我们不这样做,只是让item跟随着鼠标,并不占用mouseover等鼠标事件,这样会解决问题,但是这样并不好看,我们还是希望item能直接跟在mouse下.
另一个选择是不做item的拖拽.你可以改变鼠标指针来显示需要拖拽的item,然后放在鼠标释放的位置.这个解决方案,也是因为美学原因不予接受.
最后的解决方案是,我们并不去除拖拽效果.这种方法比前两种繁杂许多,我们需要定义我们需要释放目标的列表,当鼠标释放时,手工去检查释放的位置是否是在目标列表位置上,如果在,说明是释放在目标位置上了.
Java代码 收藏代码
/*
All code from the previous example is needed with the exception
of the mouseUp function which is replaced below
*/
var dropTargets = [];
function addDropTarget(dropTarget){
dropTargets.push(dropTarget);
}
function mouseUp(ev){
ev = ev || window.event;
var mousePos = mouseCoords(ev);
for(var i=0; idropTargets.length; i++){
var curTarget = dropTargets[i];
var targPos = getPosition(curTarget);
var targWidth = parseInt(curTarget.offsetWidth);
var targHeight = parseInt(curTarget.offsetHeight);
if(
(mousePos.x targPos.x)
(mousePos.x (targPos.x + targWidth))
(mousePos.y targPos.y)
(mousePos.y (targPos.y + targHeight))){
// dragObject was dropped onto curTarget!
}
}
dragObject = null;
}
鼠标释放时会去取是否有drop属性,如果存在,同时鼠标指针还在drop的范围内,执行drop操作.我们检查鼠标指针位置是否在目标范围是用(mousePos.xtargetPos.x),而且还要符合条件(mousePos.x(targPos.x + targWidth)).如果所有的条件符合,说明指针确实在范围内,可以执行drop指令了.
Pulling It All Together
最后我们拥有了所有的drag/drop的脚本片断!下一个事情是我们将创建一个DOM处理.
下面的代码将创建container(容器),而且使任何一个需要drag/drop的item变成一个容器的item.代码在这个文章第二个demo的后面,它可以用户记录一个list(列表),定为一个导航窗口在左边或者右边,或者更多的函数你可以想到的.
下一步我们将通过"假代码"让reader看到真代码,下面为推荐:
1、当document第一次载入时,创建dragHelper DIV.dragHelper将给移动的item加阴影.真实的item没有被dragged,只是用了insertBefor和appendChild来移动了,我们隐藏了dragHelper
2、有了mouseDown与mouseUp函数.所有的操作会对应到当到iMouseDown的状态中,只有当mouse左键为按下时iMouseDown才为真,否则为假.
3、我们创建了全局变量DragDrops与全局函数CreateDragContainer.DragDrops包含了一系列相对彼此的容器.任何参数(containers)将通过CreatedcragContainer进行重组与序列化,这样可以自由的移动.CreateDragContainer函数也将item进行绑定与设置属性.
4、现在我们的代码知道每个item的加入,当我们移动处mouseMove,mouseMove函数首先会设置变量target,鼠标移动在上面的item,如果这个item在容器中(checked with getAttribute):
* 运行一小段代码来改变目标的样式.创造rollover效果
* 检查鼠标是否没有放开,如果没有
o 设置curTarget代表当前item
o 记录item的当前位置,如果需要的话,我们可以将它返回
o 克隆当前的item到dragHelper中,我们可以移动带阴影效果的item.
o item拷贝到dragHelper后,原有的item还在鼠标指针下,我们必须删除掉dragObj,这样脚本起作用,dragObj被包含在一个容器中.
o 抓取容器中所有的item当前坐标,高度/宽度,这样只需要记录一次,当item被drag时,每随mouse移动,每移钟就会记录成千上万次.
* 如果没有,不需要做任何事,因为这不是一个需要移动的item
5、检查curTarget,它应该包含一个被移动的item,如果存在,进行下面操作:
* 开始移动带有阴影的item,这个item就是前文所创建的
* 检查每个当前容器中的container,是否鼠标已经移动到这些范围内了
o 我们检查看一下正在拖动的item是属于哪个container
o 放置item在一个container的某一个item之前,或者整个container之后
o 确认item是可见的
* 如果鼠标不在container中,确认item是不可见了.
script type="text/javascript"
var _y;
var scrolling=false;
document.onmousedown=function(e){
var e = window.event || e;
_y = e.clientY;
scrolling=true;
};
document.onmousemove = function(e){
if(!scrolling) return;
var e = window.event || e;
document.body.style.cursor="move";
var move=(e.clientY-_y)/10;
var scrollTop=document.body.scrollTop + document.documentElement.scrollTop;
window.scrollTo(0,scrollTop+move);
};
document.onmouseup=function(){
scrolling=false;
document.body.style.cursor="default";
};
/script
不足是会选中文字- -!
你的代码没用代码排版太杂乱,我直接把自己写的拖拽给你参考一下,这段代码只是无聊时写的,所以没写吸附和区域限制,你可以参考修改一下。使用方法在底部。
function ClickMove(id){
var _this = this;
this.ele = document.querySelector(id);
this.left = this.ele.offsetLeft;
this.top = this.ele.offsetTop;
this.ele.onmousedown = function(ev){
_this.mDown(ev);
}
}
ClickMove.prototype.mDown = function(ev){
var _this = this;
if( getComputedStyle(this.ele).position != 'absolute' ) this.ele.style.position = 'relative';
var eleX = ev.clientX - this.ele.offsetLeft;
var eleY = ev.clientY - this.ele.offsetTop;
document.documentElement.onmousemove = function(ev){
_this.ele.style.left = ev.clientX - eleX - _this.left + 'px';
_this.ele.style.top = ev.clientY - eleY - _this.top + 'px';
}
document.documentElement.onmouseup = function(){
this.onmousemove = null;
}
}
/*
元素你只要给一个宽高背景就好,其他的不用给都可以。
使用方法:写ID或者class名字
class方式demo: var div1 = new ClickMove('.box1');
id方式demo: var div1 = new ClickMove('#box1');
*/
本文实例讲述了JS基于面向对象实现的拖拽库。分享给大家供大家参考。具体如下:
这是一个面向对象的JS拖拽库,可设置水平锁定、垂直锁定、锁定位置、锁定范围等,设定这些范围后,只能在设定的模式下拖动,我觉得这是个挺不错的拖拽实例。
运行效果截图如下:
在线演示地址如下:
具体代码如下:
!DOCTYPE
html
PUBLIC
"-//W3C//DTD
XHTML
1.0
Transitional//EN"
""
html
xmlns=""
head
meta
http-equiv="Content-Type"
content="text/html;
charset=utf-8"
/
title拖拽库/title
style
type="text/css"
div,h2,p{margin:0;padding:0;}
body{font:14px/1.5
arial;}
#box{width:100px;height:100px;background:#fef4eb;padding:5px;margin:50px;border:1px
solid
#f60;}
#box
.title{height:25px;background:#f60;}
#tool{margin-bottom:10px;}
/style
script
type="text/javascript"
function
Drag()
{
//初始化
this.initialize.apply(this,
arguments)
}
Drag.prototype
=
{
//初始化
initialize
:
function
(drag,
options)
{
this.drag
=
this.$(drag);
this._x
=
this._y
=
0;
this._moveDrag
=
this.bind(this,
this.moveDrag);
this._stopDrag
=
this.bind(this,
this.stopDrag);
this.setOptions(options);
this.handle
=
this.$(this.options.handle);
this.maxContainer
=
this.$(this.options.maxContainer);
this.maxTop
=
Math.max(this.maxContainer.clientHeight,
this.maxContainer.scrollHeight)
-
this.drag.offsetHeight;
this.maxLeft
=
Math.max(this.maxContainer.clientWidth,
this.maxContainer.scrollWidth)
-
this.drag.offsetWidth;
this.limit
=
this.options.limit;
this.lockX
=
this.options.lockX;
this.lockY
=
this.options.lockY;
this.lock
=
this.options.lock;
this.onStart
=
this.options.onStart;
this.onMove
=
this.options.onMove;
this.onStop
=
this.options.onStop;
this.handle.style.cursor
=
"move";
this.changeLayout();
this.addHandler(this.handle,
"mousedown",
this.bind(this,
this.startDrag))
},
changeLayout
:
function
()
{
this.drag.style.top
=
this.drag.offsetTop
+
"px";
this.drag.style.left
=
this.drag.offsetLeft
+
"px";
this.drag.style.position
=
"absolute";
this.drag.style.margin
=
"0"
},
startDrag
:
function
(event)
{
var
event
=
event
||
window.event;
this._x
=
event.clientX
-
this.drag.offsetLeft;
this._y
=
event.clientY
-
this.drag.offsetTop;
this.addHandler(document,
"mousemove",
this._moveDrag);
this.addHandler(document,
"mouseup",
this._stopDrag);
event.preventDefault
event.preventDefault();
this.handle.setCapture
this.handle.setCapture();
this.onStart()
},
moveDrag
:
function
(event)
{
var
event
=
event
||
window.event;
var
iTop
=
event.clientY
-
this._y;
var
iLeft
=
event.clientX
-
this._x;
if
(this.lock)
return;
this.limit
(iTop
(iTop
=
0),
iLeft
(iLeft
=
0),
iTop
this.maxTop
(iTop
=
this.maxTop),
iLeft
this.maxLeft
(iLeft
=
this.maxLeft));
this.lockY
||
(this.drag.style.top
=
iTop
+
"px");
this.lockX
||
(this.drag.style.left
=
iLeft
+
"px");
event.preventDefault
event.preventDefault();
this.onMove()
},
stopDrag
:
function
()
{
this.removeHandler(document,
"mousemove",
this._moveDrag);
this.removeHandler(document,
"mouseup",
this._stopDrag);
this.handle.releaseCapture
this.handle.releaseCapture();
this.onStop()
},
//参数设置
setOptions
:
function
(options)
{
this.options
=
{
handle:
this.drag,
//事件对象
limit:
true,
//锁定范围
lock:
false,
//锁定位置
lockX:
false,
//锁定水平位置
lockY:
false,
//锁定垂直位置
maxContainer:
document.documentElement
||
document.body,
//指定限制容器
onStart:
function
()
{},
//开始时回调函数
onMove:
function
()
{},
//拖拽时回调函数
onStop:
function
()
{}
//停止时回调函数
};
for
(var
p
in
options)
this.options[p]
=
options[p]
},
//获取id
$
:
function
(id)
{
return
typeof
id
===
"string"
?
document.getElementById(id)
:
id
},
//添加绑定事件
addHandler
:
function
(oElement,
sEventType,
fnHandler)
{
return
oElement.addEventListener
?
oElement.addEventListener(sEventType,
fnHandler,
false)
:
oElement.attachEvent("on"
+
sEventType,
fnHandler)
},
//删除绑定事件
removeHandler
:
function
(oElement,
sEventType,
fnHandler)
{
return
oElement.removeEventListener
?
oElement.removeEventListener(sEventType,
fnHandler,
false)
:
oElement.detachEvent("on"
+
sEventType,
fnHandler)
},
//绑定事件到对象
bind
:
function
(object,
fnHandler)
{
return
function
()
{
return
fnHandler.apply(object,
arguments)
}
}
};
//应用
window.onload
=
function
()
{
var
oBox
=
document.getElementById("box");
var
oTitle
=
oBox.getElementsByTagName("h2")[0];
var
oSpan
=
document.getElementsByTagName("span")[0];
var
oDrag
=
new
Drag(oBox,
{handle:oTitle,
limit:false});
var
aInput
=
document.getElementsByTagName("input");
//锁定范围接口
aInput[0].onclick
=
function
()
{
oDrag.limit
=
!oDrag.limit;
this.value
=
oDrag.limit
?
"取消锁定范围"
:
"锁定范围"
};
//水平锁定接口
aInput[1].onclick
=
function
()
{
oDrag.lockX
=
!oDrag.lockX;
this.value
=
oDrag.lockX
?
"取消水平锁定"
:
"水平锁定"
};
//垂直锁定接口
aInput[2].onclick
=
function
()
{
oDrag.lockY
=
!oDrag.lockY;
this.value
=
oDrag.lockY
?
"取消垂直锁定"
:
"垂直锁定"
};
//锁定位置接口
aInput[3].onclick
=
function
()
{
oDrag.lock
=
!oDrag.lock;
this.value
=
oDrag.lock
?
"取消锁定位置"
:
"锁定位置"
};
//开始拖拽时方法
oDrag.onStart
=
function
()
{
oSpan.innerHTML
=
"开始拖拽"
};
//开始拖拽时方法
oDrag.onMove
=
function
()
{
oSpan.innerHTML
=
"left:"
+
this.drag.offsetLeft
+
",
top:"
+
this.drag.offsetTop
};
//开始拖拽时方法
oDrag.onStop
=
function
()
{
oSpan.innerHTML
=
"结束拖拽"
};
};
/script
/head
body
div
id="tool"
input
type="button"
value="锁定范围"
/
input
type="button"
value="水平锁定"
/
input
type="button"
value="垂直锁定"
/
input
type="button"
value="锁定位置"
/
/div
p拖放状态:span未开始/span/p
div
id="box"
h2
class="title"/h2
/div
/body
/html
希望本文所述对大家的JavaScript程序设计有所帮助。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流