javascript drag

    作者:雪山老人 译
    怎么用javascript进行拖拽

  本文译自:http://www.webreference.com/programming/javascript/mk/column2/index.html
  所有版权归原文所有
 
  Javascript的特点是dom的处理与网页效果,大多数情况我们只用到了这个语言的最简单的功能,比如制作图片轮播/网页的tab等等,这篇文章将向你展示如何在自己的网页上制作拖拽.

  有很多理由让你的网站加入拖拽功能,最简单的一个是数据重组.例如:你有一个序列的内容让用户排序,用户需要给每个条目进行输入或者用 select选择,替代前面这个方法的就是拖拽.或许你的网站也需要一个用户可以拖动的导航窗口!那么这些效果都是很简单:因为你可以很容易的实现!

  网页上实现拖拽其实也不是很复杂.第一你需要知道鼠标坐标,第二你需要知道用户鼠标点击一个网页元素并实现拖拽,最后我们要实现移动这个元素。

  点击这里运行代码

获取鼠标移动信息

  第一我们需要获取鼠标的坐标.我们加一个用户函数到document.onmousemove就可以了:

 

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坐标,然后它移动了。


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,然后放在鼠标释放的位置.这个解决方案,也是因为美学原因不予接受.

  最后的解决方案是,我们并不去除拖拽效果.这种方法比前两种繁杂许多,我们需要定义我们需要释放目标的列表,当鼠标释放时,手工去检查释放的位置是否是在目标列表位置上,如果在,说明是释放在目标位置上了.


/*
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; i<dropTargets.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.x>targetPos.x),而且还要符合条件(mousePos.x<(targPos.x + targWidth)).如果所有的条件符合,说明指针确实在范围内,可以执行drop指令了.


Pulling It All Together

  最后我们拥有了所有的drag/drop的脚本片断!下一个事情是我们将创建一个DOM处理.如果你不是很熟悉,请先阅读我的JavaScript Primer on DOM Manipulation.

  下面的代码将创建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效果
检查鼠标是否没有放开,如果没有
设置curTarget代表当前item
记录item的当前位置,如果需要的话,我们可以将它返回
克隆当前的item到dragHelper中,我们可以移动带阴影效果的item.
item拷贝到dragHelper后,原有的item还在鼠标指针下,我们必须删除掉dragObj,这样脚本起作用,dragObj被包含在一个容器中.
抓取容器中所有的item当前坐标,高度/宽度,这样只需要记录一次,当item被drag时,每随mouse移动,每移钟就会记录成千上万次.
如果没有,不需要做任何事,因为这不是一个需要移动的item
  5、检查curTarget,它应该包含一个被移动的item,如果存在,进行下面操作:

开始移动带有阴影的item,这个item就是前文所创建的
检查每个当前容器中的container,是否鼠标已经移动到这些范围内了
我们检查看一下正在拖动的item是属于哪个container
放置item在一个container的某一个item之前,或者整个container之后
确认item是可见的
如果鼠标不在container中,确认item是不可见了.
  6、剩下的事就是捕捉mouseUp的事件了

实现一个拖动的全代码:

  点击这里运行代码

  你现在拥有了拖拽的所有东西.

  下面的三个demo是记录事件历史.当你的鼠标在item上移动,将记录所生的事件,如果你不明白可以尝试一下鼠标的划过或者拖动,看有什么发生.

  点击这里运行代码

  关于译者:
  雪山老人,lamp程序员,web开发者,你可以访问sohotx.com来了解他! 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: jQuery的拖动进度条是一种可用于网页中的互动元素,可以实现对进度条的拖动来改变其进度。以下是实现这种拖动进度条的步骤: 1. 首先,在HTML中创建一个进度条的容器元素,可以是一个div或者其他合适的元素。给这个容器添加一个唯一的ID,方便在jQuery中选择和操作。 2. 使用CSS样式来美化进度条,可以设置进度条的宽度、颜色、边框样式等。可以使用CSS伪元素来实现进度条上的提示文字或者图标。 3. 在jQuery脚本中使用选择器选中进度条容器元素,并使用`.draggable()`方法来使其可拖动。该方法可以传入参数来设置拖动的约束范围和拖动时的各种回调函数。 4. 设置拖动时的回调函数,可以在拖动过程中触发一些事件,比如改变进度条的宽度、更新进度的数值显示等。可以使用`.css()`方法来改变进度条的样式。 5. 拖动结束后,可以使用`.mouseup()`方法来触发一些其他的事件,比如向服务器发送拖动进度条的数值,或者更新相关数据等。 总之,使用jQuery的`draggable()`方法可以很方便地实现拖动进度条的效果。通过设置相关的回调函数,可以实现与进度条相关的其他操作。这样用户就可以拖动进度条来改变进度,从而实现更丰富的交互。 ### 回答2: jQuery drag进度条是一种基于jQuery库的插件,用于创建可拖动的进度条。它能够实现通过鼠标拖动来改变进度条的值。下面是一个简单的示例: 首先,在HTML中添加一个进度条的容器: ```html <div id="progressBar" style="width: 300px; height: 20px; background-color: #EEE;"> <div id="progress" style="width: 0%; height: 100%; background-color: #00F;"></div> </div> ``` 然后,在JavaScript中使用jQuery drag功能来实现可拖动效果: ```javascript $(function() { $("#progress").draggable({ axis: "x", // 限制只能在水平方向拖动 containment: "#progressBar", // 拖动范围限制在容器内部 drag: function(event, ui) { var progressBarWidth = $("#progressBar").width(); var progressWidth = ui.position.left; var progressPercentage = Math.round((progressWidth / progressBarWidth) * 100); $("#progress").css("width", progressPercentage + "%"); }, stop: function(event, ui) { var progressBarWidth = $("#progressBar").width(); var progressWidth = ui.position.left; var progressPercentage = Math.round((progressWidth / progressBarWidth) * 100); console.log("Progress: " + progressPercentage + "%"); } }); }); ``` 上述代码使用了`draggable()`方法将`#progress`元素设为可拖动的。`axis`选项设置为`"x"`以限制只能在水平方向拖动。`containment`选项限制拖动范围在`#progressBar`容器内部。 在`drag`事件中,根据拖动位置的变化,计算进度条的宽度并设置给`#progress`元素。在`stop`事件中,获取最终的进度百分比并打印到控制台。 这样,当拖动进度条时,进度条的宽度会相应改变,实现了可拖动的进度条效果。 ### 回答3: Jquery drag进度条是一种使用Jquery库创建的可拖动的进度条。通过使用Jquery的拖放功能,我们可以使进度条的位置可随意拖动。 首先,我们需要引入Jquery库,并创建一个HTML元素来表示进度条。可以使用div元素,并设置其宽度、高度和背景颜色等样式属性。除此之外,也需要为进度条添加一个处理拖放事件的类名或id。 接下来,使用Jquery的drag()方法,将进度条元素作为参数传入。该方法会为进度条元素添加拖放功能,并允许用户通过鼠标拖动来改变进度条的位置。 在拖放事件处理函数中,我们可以获取用户拖动的距离,并根据需要来改变进度条的宽度或位置。可以通过Jquery的css()方法来修改进度条的样式属性。例如,可以根据鼠标拖动的距离来改变进度条的宽度百分比,从而反映进度的变化。 同时,我们还可以添加一些事件处理函数,如拖动开始时的回调函数、拖动结束时的回调函数等。这些函数可以在拖动过程中执行自定义的逻辑,如更新进度条的显示文本、向服务器发送拖动事件等。 最后,可以根据实际需要,为进度条添加其他功能,如设置进度条的最小值和最大值,限制拖动的范围等。 总之,通过使用Jquery的drag()方法,我们可以轻松地创建一个可拖动的进度条,并根据用户的拖动来实时更新进度的显示。这样的进度条可以应用于各种场景,如文件上传、下载进度显示等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值