Javascript ลากและวางสำหรับอุปกรณ์ระบบสัมผัส [ปิด]


120

ฉันกำลังมองหาปลั๊กอินลากและวางที่ใช้งานได้กับอุปกรณ์ระบบสัมผัส

ฉันต้องการฟังก์ชันที่คล้ายกันกับปลั๊กอิน jQuery UIซึ่งช่วยให้องค์ประกอบ "droppable"

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ซึ่งมีใบอนุญาตแหล่งที่มาที่ จำกัด
joe

ฉันอยากรู้ว่ามันใช้งานได้บนเบราว์เซอร์มือถือและเดสก์ท็อป
มะนาว

คำตอบ:


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

และในเอกสารของคุณแล้วเพียงแค่เรียกใช้ฟังก์ชัน init ()

พบรหัสจาก ที่นี่


11
ขอบคุณตอนนี้อุปกรณ์ Android ของฉันสามารถลากได้แล้ว อย่างไรก็ตามเหตุการณ์การคลิกจะไม่เริ่มทำงานอีกต่อไปเมื่อฉันคลิกที่มัน มีความคิดอย่างไรในการแก้ไข
John Landheer

9
หมายเหตุ: เนื่องจากผู้ฟังเหตุการณ์ได้รับการลงทะเบียนสำหรับเอกสารทั้งหมดแล้วโซลูชันนี้จึงปิดใช้งานการเลื่อนบน Nexus S ของฉันด้วย ...
Ethan Leroy

29
ขอบคุณสำหรับการแบ่งปันสิ่งนี้ อย่างไรก็ตามคุณควรให้เครดิตกับผู้เขียนโค้ดต้นฉบับที่คุณโพสต์ไว้ ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript
ระบุ

2
@JohnLandheer ฉันแก้ไขปัญหาโดยแนบผู้ฟังเหตุการณ์เข้ากับวัตถุที่ฉันต้องการลากเท่านั้นdocument.getElementById('draggableContainer').addEventListener(...
ChiliNUT

1
Touch-punch ดีมาก หนึ่งในสิ่งที่ 'มันใช้งานได้' อนิจจามันไม่รองรับ dual-touch ... ซึ่งฉันชอบที่จะเห็น
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" ตามด้วย "สัมผัส" อย่างรวดเร็วเพื่อจำลองการคลิก


@EZ Hart - คุณช่วยแจ้งให้เราทราบได้ไหมว่าจะใส่รหัสของคุณไว้ที่ใดในโค้ดด้านบนเพื่อเปิดใช้งานเหตุการณ์คลิก ???
วัลเลย์

1
@ChakoDesai - รหัสในคำตอบได้รับการแก้ไขอย่างหนักตั้งแต่ฉันเขียนคำตอบ ตรวจสอบstackoverflow.com/posts/6362527/revisionsและดูรหัสตั้งแต่วันที่ 30 มิถุนายน 2554 คำตอบของฉันจะสมเหตุสมผลมากขึ้นตามเวอร์ชันนั้น
EZ Hart

@EZ Hart - ฉันได้อัปเดตรหัสของฉันจาก URL ที่ระบุ แต่ทำไมบางครั้งใช้clickงานได้และบางครั้งไม่ได้ ???
วัลเลย์

@ChakoDesai - ถ้าไม่เห็นรหัสของคุณฉันก็ไม่แน่ใจ คุณอาจต้องการเปิดคำถามใหม่สำหรับสิ่งนั้น
EZ Hart

สามารถดูคำตอบที่อัปเดตเพื่อให้โค้ดด้านบนทำงานร่วมกับเหตุการณ์การคลิกได้ที่นี่: stackoverflow.com/questions/28218888/…
Blunderfest

12

ขอบคุณสำหรับรหัสด้านบน! - ฉันลองใช้หลายตัวเลือกและนี่คือตั๋ว ฉันมีปัญหาในการที่ PreventDefault ป้องกันการเลื่อนบน iPad - ตอนนี้ฉันกำลังทดสอบรายการที่ลากได้และใช้งานได้ดีจนถึงตอนนี้

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

คุณได้ทดสอบสิ่งนี้ใน Windows Phone หรือไม่? หรืออะไรก็ได้ที่ไม่ใช่ iPhone? จากประสบการณ์ที่ผ่านมาดูเหมือนว่าจะใช้งานได้ดีใน iPhone / iPads แต่ใช้งานได้ไม่ดีในอุปกรณ์อื่น ๆ โดยเฉพาะใน Windows Phone
เกือบจะเป็นมือใหม่

10

ฉันมีวิธีแก้ปัญหาเดียวกับคำตอบของ gregpressแต่รายการที่ลากได้ของฉันใช้คลาสแทนรหัส ดูเหมือนว่าจะได้ผล

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

4
ความจริงที่ว่าคุณใช้เพียงตัวเลือกอื่นไม่ได้รับประกันว่าจะเป็นคำตอบแยกต่างหาก แต่คุณควรแสดงความคิดเห็นในคำตอบของ @ gregpress แทน
bPratik

2
@bPratik เว้นแต่ว่าเขาต้องการคำตอบในการจัดรูปแบบที่ดีกว่าและข้อเท็จจริงที่ว่าเขาให้ตัวอย่างโค้ดทั้งหมดจะรับประกันคำตอบแยกต่างหาก ควรแสดงความคิดเห็นที่เชื่อมโยงไปยังคำตอบของเขาแม้ว่า ...
drzaus

8

กระทู้เก่ารู้แล้ว .......

ปัญหาเกี่ยวกับคำตอบของ @ryuutatsuo คือมันบล็อกอินพุตหรือองค์ประกอบอื่น ๆ ที่ต้องตอบสนองต่อ 'การคลิก' (เช่นอินพุต) ดังนั้นฉันจึงเขียนวิธีแก้ปัญหานี้ โซลูชันนี้ช่วยให้สามารถใช้ไลบรารีการลากและวางที่มีอยู่ซึ่งอิงตามเหตุการณ์การเลื่อนลงมูสมูฟและเมาส์อัพบนอุปกรณ์สัมผัสใด ๆ (หรือคัมพิเตอร์) นอกจากนี้ยังเป็นโซลูชันข้ามเบราว์เซอร์

ฉันได้ทดสอบในอุปกรณ์หลายเครื่องและทำงานได้รวดเร็ว (ร่วมกับคุณสมบัติการลากและวางของ ThreeDubMedia (ดูเพิ่มเติมที่http://threedubmedia.com/code/event/drag )) เป็นโซลูชัน jQuery เพื่อให้คุณสามารถใช้กับ jQuery libs เท่านั้น ฉันใช้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;
}; 

ให้ประโยชน์อะไร: ในตอนแรกจะแปลเหตุการณ์การสัมผัสเพียงครั้งเดียวเป็นเหตุการณ์ของเมาส์ ตรวจสอบว่าเหตุการณ์เกิดจากองค์ประกอบบน / ในองค์ประกอบที่ต้องลากไปรอบ ๆ หรือไม่ หากเป็นองค์ประกอบอินพุตเช่นอินพุตพื้นที่ข้อความ ฯลฯ จะข้ามการแปลหรือหากมีการแนบเหตุการณ์เมาส์มาตรฐานเข้าด้วยก็จะข้ามการแปลไปด้วย

ผลลัพธ์: ทุกองค์ประกอบในองค์ประกอบที่ลากได้ยังคงทำงานอยู่

ขอให้มีความสุขในการเขียนโปรแกรมทักทาย Erwin Haantjes


ฉันควรส่งผ่านวัตถุไหนsimulateTouchEvents(<object>, true);???
วัลเลย์

ตัวอย่างเช่น: simulateTouchEvents ($ ('# yourid;), true); หรือ simulateTouchEvents (document.getElementById ('yourid') จริง); ฯลฯ
Codebeat

คุณช่วยดูลิงค์คำถามอื่นของฉันได้ไหม???
Valay

ใช้threedubmedia.com/code/event/dragและปิดใช้งานการย้าย x หรือ y ขององค์ประกอบ เมื่อคุณใช้รหัสในบทความนี้คุณสามารถ "เลื่อน" แถบเลื่อนได้ แต่รู้หรือไม่ว่าทำไมคุณถึงต้องการทำเช่นนี้เพราะหน้าบนโทรศัพท์มือถือมีแถบเลื่อนอยู่แล้ว ไม่เข้าใจว่าคุณต้องการทำอะไรกับมัน ที่ประสบความสำเร็จ!
Codebeat

ฉันเพิ่มการลาก n-drop ของคอลัมน์และเลื่อนทั้งสองอย่าง เมื่อเปิดใช้touchงานกิจกรรมchromeฉันไม่สามารถเลื่อนตารางได้ ไม่แม้แต่บนมือถือ
วัลเลย์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.