用于触摸设备的Javascript拖放


120

我正在寻找可在触摸设备上使用的拖放拖放插件。

我想要与允许“可放置”元素的jQuery UI插件类似的功能。

插件jqtouch支持拖动操作,但没有落下。

这里是仅支持iPhone / iPad的拖放操作。

谁能指出我在适用于android / ios的拖放插件的方向?

...或者可能会更新jqtouch插件以实现可投放性,它已经在Andriod和IOS上运行。

谢谢!


1
这正在进行中,但是我不知道哪些设备支持它:这个plugins.jquery.com/project/mobiledraganddrop ...您是否浏览过jQuerymobile.com库?我还发现了这个重复的SO问题:stackoverflow.com/questions/3172100/…–
iivel

谢谢。是的,mobiledraganddrop仅支持在移动设备上进行点击和放置。我在jQuerymobile.com上找不到任何内容。另一个问题的答案已经被标记为正确,这是指sencha.com/products/touch的来源许可有限。

我很好奇一个可以在移动和桌面浏览器上使用的工具。
石灰

Answers:


258

您可以使用Jquery UI进行拖放,并使用一个额外的库来将鼠标事件转换为您需要的触摸,我建议使用的库为https://github.com/furf/jquery-ui-touch-punch,这从Jquery UI拖放到触摸装置

或者您可以使用我正在使用的这段代码,它也可以将鼠标事件转换为触摸事件,并且就像魔术一样工作。

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);
}

在您的document.ready中,只需调用init()函数

这里找到的代码


11
谢谢,我的Android设备上的东西现在可以拖动了。但是,单击事件不再触发。任何想法如何解决?
约翰·兰德

9
注意:由于事件监听器是为整个文档注册的,因此该解决方案还禁止在我的Nexus S上滚动...
Ethan Leroy

29
感谢您分享。但是,您应该感谢所发布代码的原始作者。 ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript
未定义

2
@JohnLandheer我通过将事件侦听器仅附加到我希望可拖动的对象上来解决此问题,document.getElementById('draggableContainer').addEventListener(...
chiliNUT13年

1
触摸打孔很棒。其中一种“行之有效”的东西。las,它不支持双点触控...我很想看看。
DA。

21

对于希望使用此功能并保留“单击”功能(如John Landheer在他的评论中所述)的任何人,您只需做几处修改即可:

添加几个全局变量:

var clickms = 100;
var lastTouchDown = -1;

然后将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;
}

您可能需要根据自己的喜好调整“ clickms”。基本上,它只是在等待一个“ touchstart”,然后是一个“ touchend”来模拟点击。


@EZ Hart-您能否让我知道将您的代码放在上述给定代码中以启用点击事件的位置???
2014年

1
@ChakoDesai-自从我写了答复以来,答案中的代码已被大量编辑。请查看stackoverflow.com/posts/6362527/revisions并查看自2011年6月30日起的代码;根据该版本,我的答案会更有意义。
EZ哈特2014年

@EZ Hart-我已经从给定的URL更新了我的代码。但是,为什么有时click起作用而有时却不起作用?
2014年

@ChakoDesai-我不确定自己没有看到代码。您可能要为此提出一个新问题。
EZ哈特

更新的答案,以与click事件上面的代码工作可以在这里找到:stackoverflow.com/questions/28218888/...
Blunderfest

12

感谢上面的代码!-我尝试了几种选择,这就是票。我的问题是preventDefault阻止了在ipad上滚动-我现在正在测试可拖动的项目,并且到目前为止效果很好。

if (event.target.id == 'draggable_item' ) {
    event.preventDefault();
}

您在Windows Phone中测试过吗?还是iPhone以外的其他东西?从过去的经验来看,这似乎可以在iPhone / iPad上完美运行,但是在其他设备(尤其是Windows Phone)上则无法正常工作。
几乎是初学者

10

我有与gregpress answer相同的解决方案,但是我的可拖动项使用类而不是id。它似乎有效。

var $target = $(event.target);  
if( $target.hasClass('draggable') ) {  
    event.preventDefault();  
}

4
您仅使用了一个不同的选择器这一事实并不能保证是单独的答案,但是您应该对@gregpress的答案进行评论。
bPratik 2012年

2
@bPratik除非他希望提供更好的答案格式,而且他提供了完整的代码示例这一事实确实需要单独的答案。虽然应该留下评论链接到他的答案……
drzaus

8

我知道的旧线程.......

@ryuutatsuo答案的问题是它还会阻止任何必须对“单击”做出反应的输入或其他元素(例如输入),因此我编写了此解决方案。该解决方案使在任何触摸设备(或计算机)上使用任何基于mousedown,mousemove和mouseup事件的现有拖放库成为可能。这也是跨浏览器的解决方案。

我已经在多种设备上进行了测试,并且运行速度很快(结合ThreeDubMedia的拖放功能(另请参见http://threedubmedia.com/code/event/drag))。这是一个jQuery解决方案,因此您只能将其与jQuery库一起使用。我之所以使用jQuery 1.5.1,是因为某些较新的功能无法在IE9及更高版本上正常使用(未经jQuery较新版本测试)。

向事件添加任何拖放操作之前,必须首先调用以下函数

simulateTouchEvents(<object>);

您还可以使用以下语法来阻止所有组件/子组件进行输入或加速事件处理:

simulateTouchEvents(<object>, true); // ignore events on childs

这是我写的代码。我使用了一些不错的技巧来加快评估速度(请参见代码)。

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;
}; 

它的作用:首先,它将单次触摸事件转换为鼠标事件。它检查事件是否由必须拖动的元素上/元素中的元素引起。如果它是输入元素(例如输入,文本区域等),则它会跳过翻译,或者如果附加了标准鼠标事件,它也会跳过翻译。

结果:可拖动元素上的每个元素仍在工作。

快乐编码,greetz,Erwin Haantjes


我应该传递哪个对象simulateTouchEvents(<object>, true);???
2014年

例如:SimulationTouchEvents($('#yourid;),true); 或SimulationTouchEvents(document.getElementById('yourid'),true); 等
Codebeat

你能看看我的另一个问题链接吗?
2014年

使用threedubmedia.com/code/event/drag并禁用元素的x或y移动。当您使用本文中的代码时,您可以“滚动”滚动条。但是一定要知道为什么要这么做,因为手机上的页面已经具有滚动条。不明白您想用它做什么。成功!
Codebeat

我必须添加列的拖放并同时滚动两者。当我打开中的touch事件时chrome,我无法滚动表格。甚至不在手机上。
Valay 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.