用于触摸设备的 Javascript 拖放
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5186441/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Javascript Drag and drop for touch devices
提问by joe
I am looking for a drag & DROP plugin that works on touch devices.
我正在寻找适用于触摸设备的拖放插件。
I would like similar functionality to the jQuery UI pluginwhich allows "droppable" elements.
我想要与jQuery UI 插件类似的功能,它允许“放置”元素。
The jqtouch pluginsupports dragging, but no dropping.
该插件jqtouch支持拖动操作,但没有落下。
Hereis drag & drop that only supports iPhone/iPad.
这是仅支持 iPhone/iPad 的拖放。
Can anyone point me in the direction of a drag & drop plugin that works on android/ios?
任何人都可以指点我在 android/ios 上运行的拖放插件的方向吗?
...Or it might be possible to update the jqtouch plugin for droppability, it already runs on Andriod and IOS.
...或者可以更新 jqtouch 插件以获得可删除性,它已经在 Andriod 和 IOS 上运行。
Thanks!
谢谢!
回答by ryuutatsuo
You can use the Jquery UI for drag and drop with an additional library that translates mouse events into touch which is what you need, the library I recommend is https://github.com/furf/jquery-ui-touch-punch, with this your drag and drop from Jquery UI should work on touch devises
您可以使用 Jquery UI 进行拖放以及将鼠标事件转换为您需要的触摸的附加库,我推荐的库是https://github.com/furf/jquery-ui-touch-punch,使用这您从 Jquery UI 拖放应该适用于触摸设备
or you can use this code which I am using, it also converts mouse events into touch and it works like magic.
或者你可以使用我正在使用的这段代码,它还可以将鼠标事件转换为触摸,它的工作原理就像魔术一样。
function touchHandler(event) {
var touch = event.changedTouches[0];
var simulatedEvent = document.createEvent("MouseEvent");
simulatedEvent.initMouseEvent({
touchstart: "mousedown",
touchmove: "mousemove",
touchend: "mouseup"
}[event.type], true, true, window, 1,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY, false,
false, false, false, 0, null);
touch.target.dispatchEvent(simulatedEvent);
event.preventDefault();
}
function init() {
document.addEventListener("touchstart", touchHandler, true);
document.addEventListener("touchmove", touchHandler, true);
document.addEventListener("touchend", touchHandler, true);
document.addEventListener("touchcancel", touchHandler, true);
}
And in your document.ready just call the init() function
在你的 document.ready 中调用 init() 函数
code found from Here
从这里找到的代码
回答by E.Z. Hart
For anyone looking to use this and keep the 'click' functionality (as John Landheer mentions in his comment), you can do it with just a couple of modifications:
对于任何希望使用它并保留“点击”功能的人(正如 John Landheer 在他的评论中提到的),您只需进行一些修改即可:
Add a couple of globals:
添加几个全局变量:
var clickms = 100;
var lastTouchDown = -1;
Then modify the switch statement from the original to this:
然后把原来的switch语句修改成这样:
var d = new Date();
switch(event.type)
{
case "touchstart": type = "mousedown"; lastTouchDown = d.getTime(); break;
case "touchmove": type="mousemove"; lastTouchDown = -1; break;
case "touchend": if(lastTouchDown > -1 && (d.getTime() - lastTouchDown) < clickms){lastTouchDown = -1; type="click"; break;} type="mouseup"; break;
default: return;
}
You may want to adjust 'clickms' to your tastes. Basically it's just watching for a 'touchstart' followed quickly by a 'touchend' to simulate a click.
您可能想根据自己的喜好调整“clickms”。基本上它只是在观察“touchstart”,然后是“touchend”来模拟点击。
回答by gregpress
Thanks for the above codes! - I tried several options and this was the ticket. I had problems in that preventDefault was preventing scrolling on the ipad - I am now testing for draggable items and it works great so far.
感谢以上代码!- 我尝试了几种选择,这就是票。我遇到了问题, preventDefault 阻止在 ipad 上滚动 - 我现在正在测试可拖动的项目,到目前为止效果很好。
if (event.target.id == 'draggable_item' ) {
event.preventDefault();
}
回答by Eric
I had the same solution as gregpress answer, but my draggable items used a class instead of an id. It seems to work.
我有与gregpress answer相同的解决方案,但我的可拖动项目使用了一个类而不是一个 id。它似乎工作。
var $target = $(event.target);
if( $target.hasClass('draggable') ) {
event.preventDefault();
}
回答by Codebeat
Old thread I know.......
我知道的旧线程......
Problem with the answer of @ryuutatsuo is that it blocks also any input or other element that has to react on 'clicks' (for example inputs), so i wrote this solution. This solution made it possible to use any existing drag and drop library that is based upon mousedown, mousemove and mouseup events on any touch device (or cumputer). This is also a cross-browser solution.
@ryuutatsuo 的答案的问题在于它还会阻止任何输入或其他必须对“点击”做出反应的元素(例如输入),所以我写了这个解决方案。该解决方案使得在任何触摸设备(或计算机)上使用基于 mousedown、mousemove 和 mouseup 事件的任何现有拖放库成为可能。这也是一个跨浏览器的解决方案。
I have tested in on several devices and it works fast (in combination with the drag and drop feature of ThreeDubMedia (see also http://threedubmedia.com/code/event/drag)). It is a jQuery solution so you can use it only with jQuery libs. I have used jQuery 1.5.1for it because some newer functions don't work properly with IE9 and above(not tested with newer versions of jQuery).
我已经在多个设备上进行了测试,它运行速度很快(结合 ThreeDubMedia 的拖放功能(另见http://threedubmedia.com/code/event/drag))。它是一个 jQuery 解决方案,因此您只能将它与 jQuery 库一起使用。我为此使用了jQuery 1.5.1,因为一些较新的函数在 IE9 及更高版本中无法正常工作(未使用较新版本的 jQuery 进行测试)。
Beforeyou add any drag or dropoperation to an event you have to call this function first:
在向事件添加任何拖放操作之前,您必须先调用此函数:
simulateTouchEvents(<object>);
You can also block all components/children for input or to speed up event handling by using the following syntax:
您还可以使用以下语法阻止所有组件/子组件的输入或加速事件处理:
simulateTouchEvents(<object>, true); // ignore events on childs
Here is the code i wrote. I used some nice tricks to speed up evaluating things (see code).
这是我写的代码。我使用了一些不错的技巧来加速评估事物(见代码)。
function simulateTouchEvents(oo,bIgnoreChilds)
{
if( !$(oo)[0] )
{ return false; }
if( !window.__touchTypes )
{
window.__touchTypes = {touchstart:'mousedown',touchmove:'mousemove',touchend:'mouseup'};
window.__touchInputs = {INPUT:1,TEXTAREA:1,SELECT:1,OPTION:1,'input':1,'textarea':1,'select':1,'option':1};
}
$(oo).bind('touchstart touchmove touchend', function(ev)
{
var bSame = (ev.target == this);
if( bIgnoreChilds && !bSame )
{ return; }
var b = (!bSame && ev.target.__ajqmeclk), // Get if object is already tested or input type
e = ev.originalEvent;
if( b === true || !e.touches || e.touches.length > 1 || !window.__touchTypes[e.type] )
{ return; } //allow multi-touch gestures to work
var oEv = ( !bSame && typeof b != 'boolean')?$(ev.target).data('events'):false,
b = (!bSame)?(ev.target.__ajqmeclk = oEv?(oEv['click'] || oEv['mousedown'] || oEv['mouseup'] || oEv['mousemove']):false ):false;
if( b || window.__touchInputs[ev.target.tagName] )
{ return; } //allow default clicks to work (and on inputs)
// https://developer.mozilla.org/en/DOM/event.initMouseEvent for API
var touch = e.changedTouches[0], newEvent = document.createEvent("MouseEvent");
newEvent.initMouseEvent(window.__touchTypes[e.type], true, true, window, 1,
touch.screenX, touch.screenY,
touch.clientX, touch.clientY, false,
false, false, false, 0, null);
touch.target.dispatchEvent(newEvent);
e.preventDefault();
ev.stopImmediatePropagation();
ev.stopPropagation();
ev.preventDefault();
});
return true;
};
What it does: At first, it translates single touch events into mouse events. It checks if an event is caused by an element on/in the element that must be dragged around. If it is an input element like input, textarea etc, it skips the translation, or if a standard mouse event is attached to it it will also skip a translation.
它的作用:首先,它将单个触摸事件转换为鼠标事件。它检查事件是否由必须拖动的元素上/中的元素引起。如果它是输入元素,如 input、textarea 等,它会跳过翻译,或者如果附加了标准鼠标事件,它也会跳过翻译。
Result: Every element on a draggable element is still working.
结果:可拖动元素上的每个元素仍在工作。
Happy coding, greetz, Erwin Haantjes
快乐编码,greetz,Erwin Haantjes