它没有所有花哨的回调和选项,但它可以使元素可拖动(并且可以选择指定一个手柄)。
(function($) {
$.fn.drags = function(opt) {
opt = $.extend({handle:"",cursor:"move"}, opt);
if(opt.handle === "") {
var $el = this;
} else {
var $el = this.find(opt.handle);
}
return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
if(opt.handle === "") {
var $drag = $(this).addClass('draggable');
} else {
var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
}
var z_idx = $drag.css('z-index'),
drg_h = $drag.outerHeight(),
drg_w = $drag.outerWidth(),
pos_y = $drag.offset().top + drg_h - e.pageY,
pos_x = $drag.offset().left + drg_w - e.pageX;
$drag.css('z-index', 1000).parents().on("mousemove", function(e) {
$('.draggable').offset({
top:e.pageY + pos_y - drg_h,
left:e.pageX + pos_x - drg_w
}).on("mouseup", function() {
$(this).removeClass('draggable').css('z-index', z_idx);
});
});
e.preventDefault(); // disable selection
}).on("mouseup", function() {
if(opt.handle === "") {
$(this).removeClass('draggable');
} else {
$(this).removeClass('active-handle').parent().removeClass('draggable');
}
});
}
})(jQuery);
用法
$('div').drags();
演示
查看 CodePen 上 Chris Coyier 的笔 jQuery Draggable with out jQuery UI(@chriscoyier)在 CodePen 上。
我之前不知道可以在页面中插入 CodePen 代码。这是一个非常棒的功能。抱歉偏离了这篇文章的主题。
到目前为止,工作良好。
我只是想请求这个功能,谢谢。
(顺便说一句,我会将“var $el”和“var $drag”向上移动几行,这样“var”只会出现一次,并且 JSHint 不会报错……也许手柄也可以在可拖动对象中更深一层,.parent() 无法做到吗?)
演示?:\
jQuery UI 的可拖动功能的快速轻量级替代方案!!!!
哦,谢谢,我一直试图找到一个像这样的简单脚本……并且没有 bug :) 现在在这种情况下添加一些
onDragEnd
和onDragStart
非常简单嗯,它会禁用可拖动父容器内的
select
元素,如果你点击那个小三角形,选项将不再显示:/ 但是按钮、复选框和单选按钮仍然可以正常工作。
如何在基于触摸的设备上使它工作?
嘿!你找到解决方案了吗?
提前感谢!:D
是的,我也在寻找触摸屏可拖动的解决方案。当对元素使用 transform 时,ui-draggable 会出现问题:\
针对询问触摸支持的人,您可能对这个我制作的简单可拖动插件感兴趣,它支持触摸和鼠标事件:https://github.com/grantm/jquery-udraggable/
触摸支持来自 Michael S. Mikowski 的 jquery.event.ue 插件。
有一个小错误……如果同一页面上有两个可拖动项目,第一次单击其中一个时,另一个项目会覆盖到它上面。这仅发生在第一次单击时,然后一切正常……有人能告诉我如何修复它吗?
这不是错误。移除设置的 css z-index。
$drag.css(‘z-index’, 1000)
$drag.css(‘z-index’, ‘auto’) 工作正常!
非常感谢开发者
我已经解决了,是我的错误,我没有为每个可拖动项目使用 id,而是为一个类设置了插件,并且我将其命名为“draggable”,不知道该插件需要该类来激活/禁用 mousedown/mouseup 上的移动。抱歉,我忘记再次评论问题是如何解决的。这确实是一个很好的插件。有没有办法向此插件添加一个新选项,设置一个按钮或其他东西,并且只能通过该按钮移动项目?我有一个“可拖动面板”,其中包含动态内容,有时需要垂直滚动条,当您移动滚动条时,也会移动面板。目前我通过添加一个“激活/禁用可拖动”按钮解决了这个问题
出现错误“TypeError: $el.css(“cursor”, opt.cursor).on 不是函数”
更新 jQuery 或使用 bind 代替 on
可拖动元素非常有趣。我玩得很开心——http://grafiks101.com。现在,'Tis the season',我想看到一个基于放置区域触发操作的程序。你知道的,就像装饰圣诞树一样,但是……如果你把灯泡挂到错误的分支上,树就会爆炸!
有趣的东西,我无法告诉你我从 css-tricks.com 学到了多少东西!!
我应该如何使用手柄?我有一个弹出窗口,我想将标题作为手柄,整个弹出窗口作为可拖动的。
忘记提到我尝试过使用“$.extend({handle:”.drag_handle”,cursor:”move”}, opt);” 但不起作用。
抱歉各位……是我的错误。已经解决了。
这个可拖动技巧太棒了!有没有办法在可拖动对象中包含一个小按钮来关闭它?
我的网站上有“老式风格的对话框”——http://www.stefangougherty.com,它们是可拖动的,更重要的是可关闭的。不幸的是,启用它们的旧 JavaScript 与 header 中的 !DOCTYPE 信息冲突,因此我不得不将其删除,这对于我的网站在 IE 中正确运行至关重要。
有什么建议吗?(我只了解基本的 html 和 css,但在“反向工程”更复杂的东西方面取得了相当大的成功)
谢谢!!!
我在 IExplorer 中遇到了一种奇怪的行为,其中光标会变成“此处无法拖动”,并且拖动需要我点击其他地方,拖动会进行,但会有延迟。
嗯,你不需要在某个地方解除绑定 mousemove 吗?一旦你开始拖动,触发器就永远不会停止。移动停止是因为 .draggable 类被删除了,但是触发器仍然在继续触发?
*-pike
我真的很感谢这段代码。一些小的批评/问题……
为什么要在拖动项目上设置一个类?在拖动时突出显示?
为什么要使用 drg_w、drg_h 变量?这些可以简单地删除,没有任何影响。
为什么这个博客软件会愚蠢地将下划线转换为斜体?;)
为什么这个博客软件会愚蠢地删除前导破折号?
这太棒了!我有一个快速的问题——我该如何打开和关闭它?
就像在可拖动中我们可以执行 $element.draggable('option','disabled',true/false);
有没有办法在这里做到这一点?
在 Win8 和 IE10 上不起作用!
我在这个脚本中遇到一个问题:尝试在第 28 行的 mouseup 函数内部记录一些内容,你就会发现,因为 mouseup 监听器是在 mousedown 函数(第 12 行)内部调用的,所以这个特定的函数不仅会在每次触发 mousemove 事件(第 23 行)时被调用,而且还会随着每次触发 mousedown 事件(第 12 行)而被乘以次数。在你将方块拖动到某个地方 4 到 5 次后,这会导致一些严重的表现性能问题。
我自己也写过类似的东西——你觉得我的解决方案怎么样?
如果这太晚了,请原谅(确实晚了),但我把所有代码都复制到这儿,完全一样地尝试了一下,但不知为何它没有变成可拖动的。是不是有bug?
这正是我需要的,非常感谢 Chris。
太棒了!
嘿,很棒的工作!!但是你能否给我解释一下这个,或者你有关于这项工作的任何文档吗?我渴望了解它,因为我对 JavaScript 还很陌生,所以才问这些。
这很好!在 Chrome 浏览器中运行完美。但是,如何修改它才能适用于基于触控的设备?
有没有办法让它在 div 元素后面工作?
嘿 Chris,我是你的技巧的忠实粉丝。我有两个 div 嵌套在一起,它们具有相同的宽度和高度,并且它们之间有一个边框,你能否给我一些提示,如何使该边框可拖动,以便当我们拖动该边框时,每个 div 的宽度都会发生变化,我的意思是 50% 50% 将边框拖动到右侧,例如宽度更改为 30% 70%
mousemove 事件一直在触发。你需要使用 window 对象触发 mouseup。就在 `$drag....parents().on('mousemove', ...` 之前写
不错的提示 Arthur,谢谢。
$(window).unbind(‘mouseup’);
不要使用 mouseup……
到目前为止,我做到了这一点。它可能仍然有一些错误,但对于我的目的来说,我更喜欢它而不是 jQuery UI 拖动程序。
define(function(require, exports, module) {
(function($) {
$.fn.drags = function(opt) {
var originalZ = null,
thisDrag = this,
pos = null,
dragger, $el, $parents;
function sortConstraint(x) {
if (x != null) {
x.sort();
}
}
function startChildEvents(isActive) {
$this = $(thisDrag);
var onOff = isActive ? "on" : "off";
$drag = (opt.handle === "") ?
$this.toggleClass('draggable', isActive)
$this.toggleClass('active-handle', isActive).parent().toggleClass('draggable', isActive);
if (originalZ == null) { originalZ = $drag.css('z-index'); }
$parents = $drag.css('z-index', isActive ? 1001 : originalZ).parents();
$parents[onOff]("mousemove", mouseMove);
$el[onOff]("mouseup", mouseUp);
$el.css('cursor', isActive ? opt.cursor : "default");
}
function mouseEnd(e) {
$drag.css('z-index', originalZ);
startChildEvents(false);
var movedLeft = (pos.current.left - pos.start.left) < 0;
if(opt.handle === "") {
$(this).removeClass('draggable');
} else {
$(this).removeClass('active-handle').parent().removeClass('draggable');
}
if (opt.autoEnd) {
dragger.start(false);
}
opt.onEndMove({ movedLeft: movedLeft })
}
function mouseDown(e) {
startChildEvents(true);
pos.current = $drag.offset();
pos.start = pos.current;
pos.click = { y: e.pageY, x: e.pageX };
e.preventDefault(); // 禁用选择
}
function mouseMove(e) {
var endMove = (opt.xMaxMove != null && Math.abs(pos.current.left - pos.start.left) > opt.xMaxMove);
pos.current = {
top: (opt.axis == "x" ? pos.start.top : pos.start.top + e.pageY - pos.click.y),
left:(opt.axis == "y" ? pos.start.left: pos.start.left + e.pageX - pos.click.x)
};
if (opt.xConstrain != null) {
var xDiff = pos.current.left - pos.reference.left;
if (xDiff < opt.xConstrain[0]){
pos.current.left = pos.reference.left + opt.xConstrain[0];
endMove = true;
} else if (xDiff > opt.xConstrain[1]) {
pos.current.left = pos.reference.left + + opt.xConstrain[1];
endMove = true;
}
}
endMove = (endMove || opt.yMaxMove != null && Math.abs(pos.current.top - pos.start.top) > opt.yMaxMove);
if (opt.yConstrain != null) {
var yDiff = pos.current.top - pos.reference.top;
if (yDiff < opt.yConstrain[0]){
pos.current.top = pos.reference.top + opt.yConstrain[0];
endMove = true;
} else if (yDiff > opt.yConstrain[1]) {
pos.current.top = pos.reference.top + + opt.yConstrain[1];
endMove = true;
}
}
$d = $('.draggable');
if (endMove) { mouseEnd(); } else {
$d.offset(pos.current);
}
}
function mouseUp(e) {
$(this).removeClass('draggable').css('z-index', originalZ);
}
dragger = {
start: function(start, newPos) {
if (pos == null) {
var cc = $el.offset();
pos = { start: cc, current: cc, reference: cc };
}
if (typeof newPos != "undefined") {
pos = $.extend(pos, newPos);
}
$el[start ? "on" : "off"]("mousedown", mouseDown);
if (! start) {
startChildEvents(false);
}
}
}
opt = $.extend({
handle:"",
cursor:"move",
axis: null,
autoStart: true,
autoEnd: false,
xMaxMove: null,
yMaxMove: null,
xConstrain: null,
yConstrain: null,
allowDrag: function() { return true; },
onEndMove: function() {}
}, opt);
sortConstraint(opt.xConstrain);
sortConstraint(opt.yConstrain);
$el = (opt.handle === "") ? $el = this : this.find(opt.handle);
$el.dragger = dragger;
if (opt.autoStart) { dragger.start(true); }
return $el
}
})(jQuery);
});
对先前代码的更新。现在,此代码可以传递一个点击事件,如果鼠标拖动仅为几个像素或更少,则运行该事件。这两个代码都使用比此处最初发布的代码更简单的数学方法,但整体结构与最初的代码非常相似。它也比最初的代码具有更多功能,但它处理约束的方式比 jqueryUI 拖动程序更容易处理。
使用带有 input[type=range] 控件的面板进行拖动存在一个固有问题,即无法使用范围滑块,因为 mousedown 事件将被拦截,并且面板将开始拖动。因此我编写了一个小解决方案:dragsOff,使用 JQuery 的 hover 方法。
当然,还有 dragsOff
不错!
您好,
我遇到了同样的问题(关于范围输入),但不想使用 Jquery。我所做的只是在鼠标按下时更改可拖动属性。
然后
要使可拖动容器内的输入元素(文本、文本区域、范围滑块……)工作,只需删除语句 e.preventDefault();
太棒了!非常感谢,我已经找了几个小时了…… :)
我理解上面的代码可以拖动图像,如果我想让视频流(WebRTC 客户端视频)可拖动怎么办?
我已经编辑了脚本以支持触摸事件……我想它不是万无一失的,但对我来说是有效的。
http://pastebin.com/wVzEqG7i
先生,如何在可拖动 div 内选择输入元素中的文本时禁用可拖动功能?谢谢!
如何指定处理程序?我是 jQuery 新手,我不理解你的解释。谢谢
我需要在带有链接的元素上使用它。在原始代码中,当拖动完成时,如果用户抓取以开始/结束拖动的位置是链接,则它将遵循该链接。此版本添加了几行代码,以防止在(意外)移动非常小的情况下遵循链接。它还使它能够在使用其 CSS 中的 bottom 或 right 定位的元素上工作。
http://codepen.io/swinggraphics/pen/cxmbj
如何为此添加缓动?
此代码存在严重的性能问题,如果你多次拖动对象,每次都会越来越滞后,你就会看到这一点。
这是因为每次用户点击被拖动的对象时,都会绑定一个新的 mousemove 事件处理程序“在顶部”。如果你拖动了对象 10 次,那么将有 10 个冗余的 mousemove 处理程序跟踪光标,因此会出现延迟。
Geoffrey Swenson 的代码解决了此问题,因为它在每次用户停止拖动后都会清理事件处理程序。我建议任何人都使用他的代码段而不是原始代码段。
看看我的解决方案——https://gist.github.com/NazarkinRoman/12654be37a35ca006375
代码有一个刚刚修复的版本。完全没有重写,所以用法仍然相同。
可拖动元素内的文本区域变得无法编辑,不得不切换回UI的draggable()。
有没有办法将可拖动元素限制在其父div的大小内?
这样它就无法被拖出屏幕外?
jQuery UI可以做到这一点。我觉得一旦你需要一些花哨的额外功能,最好使用更强大的东西,比如jQuery UI或Dragabilly,而不是上面这段简单的代码。
所以,每次调用“mousedown”事件时,它都会添加一个“mousemove”的事件处理程序?
这段代码运行得很好..但我只想添加一个点击事件,当元素被拖动时应该阻止它。谁能帮我提供一个简单的解决方案?
稍微优化一下,删除无用的宽度和高度,更好的事件处理程序
并且处理程序只附加到文档而不是所有父元素
演示 http://jsbin.com/vuhasika/1/edit
这两个版本都需要以
return this;
结束拖动函数,否则它不可链式调用。如果你在一个页面上测试多个,你会发现它们在拖动时都被移动到第一个的位置。
非常感谢
我认为这将比jquery ui运行得更好更快
这是一段很棒的代码。正是我需要的。
不过我想建议一个修复方案
如果使用了{handle: ___}选项,那么它会破坏jQuery的链式调用,因为它切换到handle元素,而不是停留在同一个元素上。
要修复它,请更改此行
return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
为
$el.css('cursor', opt.cursor).on("mousedown", function(e) {
并将结尾行更改为此
自从DHTML时代以来,我不需要任何类似的东西,而且我惊讶地发现对此类轻量级(少行代码)解决方案如此之少。感谢Chris和精彩的评论者,以下是另一个版本,主要基于**Wing**的优化,但针对多个元素进行了调整,而不是他最初的版本。
处理程序和光标选项已被删除,因为我在我的项目中没有看到它们的用途,但作为奖励,它可以很好地与设置了**bottom**或**right**属性的元素一起使用。
也可在Gist上找到: https://gist.github.com/Arty2/11199162
当然,欢迎提出意见和建议
此演示效果很好。但是当我将其应用到我的页面上时,当我拖动元素时,幽灵拖动项是页面很大一部分,而不仅仅是被拖动的LI。我还注意到,如果我有许多这样的可拖动项,页面上的其他功能(重新排序列表)会变得非常非常慢。有什么想法吗?谢谢!
更新-问题1通过删除被拖动LI内具有绝对位置的子元素得到修复。
在可拖动div区域内无法对点击函数起作用
这太棒了。很棒的作品
不错的代码,非常感谢分享。一个问题
通常,你有一个容器div,里面有很多子div,比如“header”、“main”、“footer”等等。
当拖动其中一个,比如“header”div时,有没有办法拖动整个它们(容器及其子元素)?
请注意,上面的原始代码运行良好,除了每次拖动都会使浏览器越来越慢。要解决此问题,请在每个.on调用之前添加一个.off('event')
拖动WordPress帖子、页面和分类到其列表中上下的代码是什么?我正在寻找要添加到我正在构建的自定义函数插件中的代码。(而不是使用现有的插件,最好获取为此所需的代码以及CSS。)
更进一步(如果可以的话)。
关闭树分支。如果用户有很多子元素,最好关闭一个分支以节省空间。例如,有可能关闭页面分支、类别分支等。
这段代码对我来说完美地运行了。我有一个问题。
有没有办法在移动设备上使用它而不使用jQuery Mobile??
像我之前很多人一样,我对这一点也有自己的看法。包括触摸支持。
尽管代码结构非常相似,但我直到最近才注意到这篇文章。但它促使我开始学习如何编写jQuery库扩展。到目前为止,它只是一个函数(不是插件)
http://codepen.io/Shikkediel/pen/ZYbWzL
阅读评论,我认为Arthur关于取消绑定mousemove的提示很有价值,所以我已经实现了它。对于提到的其他大多数问题,我认为脚本中添加了解决方案。
之前,我求助于jQuery UI的必要部分来创建可拖动元素,并结合Touch Punch以期实现跨浏览器兼容性。
很高兴看到这个版本确实在我的手机上运行,但是当页面上有多个可拖动项时,移动一个时所有项都会被移动。
我从Heracles的版本开始,最终得到了适用于iOS和Android的版本。查看代码
这看起来很完美,谢谢!
这个可以工作,甚至在我的手机上也可以,但拖动后,看到项目在页面上向下移动一点,这很烦人。实际上是transform scale(1.1)。如果它改变大小,你无法精确地拖动。
此外,在这个代码所基于的代码中,你创建了一个名为stack的全局变量。
在移动设备上,此版本在小项目上更难使用,因为要检查小动作。我不断滚动页面而不是拖动项目。
性能似乎不太好,有点卡顿…
感谢slavap提供的代码,它非常有用。但是我怎样才能检测点击事件呢,我正在创建一个日期滚动(类似于mobiscroll),我想返回我点击的项目的value。
有没有方法避免可拖动元素重叠?
我正在使用这个插件,但当设置为可拖动的元素具有元素时,它存在一个重大错误。选择框停止工作(至少在Chrome上是这样)。我也不喜欢用户在输入或按钮元素上“开始拖动”时执行拖动然后执行鼠标点击的UX问题。
我更倾向于忽略一些元素以防止触发拖动事件,所以我对这个插件进行了修改,添加了一个类似于jquery-ui的取消选项: https://github.com/pjfsilva/dte-project/blob/master/jquery-draggable/draggable.js
现在可以工作了,并且UX得到了改进。默认情况下,取消元素为:a、input、textarea、button、select、option
您有演示链接吗?
也许有人可以实际创建一个WordPress帖子和页面的拖放功能。如果有人有兴趣……可以查看
https://core.trac.wordpress.org/ticket/2702
http://easywebdesigntutorials.com/drag-and-drop-page-ordering-in-a-tree-page-view-wordpress/
它简短但功能强大
我的版本在github上有一个可用的演示 https://github.com/geewhizbang/jQueryDragger
这个对我来说不起作用。在一个页面上有多个可拖动项目时,拖动一个会将所有项目移动到第一个项目的位置。即使在鼠标松开后,它们也会继续跟随光标。
而且它不处理触摸事件。
jquery ui 在移动设备上有效,而这个无效。无法比较