簡體   English   中英

HTML5 Drag'n'Drop - 在iOS 12.1.2上無效(Safari和Chrome)

[英]HTML5 Drag'n'Drop - Not Working on iOS 12.1.2 (Safari and Chrome)

背景

我有一個可以通過拖放進行排序的列表。 它可以在桌面瀏覽器和Android上的Chrome上完美運行。 但是,它在iOS 12.1.2(iPhone 8)上的Safari和Chrome上根本不起作用。

現行守則

請參閱下面的代碼段,以及便於移動測試: https//codepen.io/Kelderic/pen/KJMRgb

 var dragging = null; document.addEventListener('dragstart', function(event) { var target = getLI(event.target); dragging = target; event.dataTransfer.setData('text/plain', null); event.dataTransfer.setDragImage(self.dragging, 0, 0); }); document.addEventListener('dragover', function(event) { event.preventDefault(); var target = getLI(event.target); var bounding = target.getBoundingClientRect() var offset = bounding.y + (bounding.height / 2); if (event.clientY - offset > 0) { target.style['border-bottom'] = 'solid 4px blue'; target.style['border-top'] = ''; } else { target.style['border-top'] = 'solid 4px blue'; target.style['border-bottom'] = ''; } }); document.addEventListener('dragleave', function(event) { var target = getLI(event.target); target.style['border-bottom'] = ''; target.style['border-top'] = ''; }); document.addEventListener('drop', function(event) { event.preventDefault(); var target = getLI(event.target); if (target.style['border-bottom'] !== '') { target.style['border-bottom'] = ''; target.parentNode.insertBefore(dragging, event.target.nextSibling); } else { target.style['border-top'] = ''; target.parentNode.insertBefore(dragging, event.target); } }); function getLI(target) { while (target.nodeName.toLowerCase() != 'li' && target.nodeName.toLowerCase() != 'body') { target = target.parentNode; } if (target.nodeName.toLowerCase() == 'body') { return false; } else { return target; } } 
 ul.sorting { padding: 0; margin: 0; list-style: none; max-height: 300px; overflow-y: auto; box-shadow: inset 0 0 3px 1px rgba(0, 0, 0, 0.2); } ul.sorting li { padding: 10px; border-bottom: 1px solid black; user-select: none; cursor: move; } ul.sorting li:last-child { border-bottom: none; } 
 <ul class="sorting"> <li draggable="true" style="user-drag:element;">List Item 15</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 2</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 3</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 4</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 5</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 6</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 7</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 8</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 9</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 10</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 11</li> <li draggable="true" style="-webkit-user-drag:element;">List Item 12</li> </ul> 

iOS上的行為視頻

https://imgur.com/a/I8hzPxC (尺寸太大,無法直接嵌入)

為什么這不適用於iOS? 我甚至無法啟動dragstart事件。 在Android Chrome上,longpress會觸發dragstart

我的后備想法是使用touchstarttouchend進行長按,然后創建我自己的絕對定位的ghost元素並手動拖動它。 drag*事件應該正常工作時,這是很多額外的代碼。

我錯過了什么嗎?

編輯

移動Safari中的LI元素將ondragstart事件作為其原型的一部分。 問題是要解雇它。

此外,根據caniuse,移動Safari應該支持這一點。 但是,caniuse也表示Android Chrome不支持,但事實並非如此。

過去一周我在這個主題上做了很多研究,我做了很多測試和調試。 我發現iOS支持拖動事件,但iOS不會觸發它們。 (截至iOS 12)

如果您在iOS Safari上測試網頁,您會看到所有HTML元素都有ondragstart附加到他們的原型。 阻力事件就在那里。 它們永遠不會被觸發。

其他人也遇到過這個問題。 由於此錯誤支持,Event Modernizer 無法檢測拖放支持。

另外,我挖掘了Safari文檔, 發現了這個

iOS注意:雖然不支持拖放,但您可以生成...

它說“支持”,但在下面,有一個事件表,顯示drag並說它不是“生成”。

這意味着caniuse目前是錯誤的,需要更新。


直接回答問題

代碼不能單獨工作,因為Apple選擇不觸發拖動事件。

不幸的是我沒有iOS12的設備(我的設備不支持它),我無法測試它。 而且我不知道為什么iOS / Apple支持寫道他們在iOS 11.2和新設備上支持這些事件它不受支持。

替代解決方法

通過此解決方法,您將獲得適用於所有現代設備和瀏覽器的解決方案。 最好等待iOS / Apple的支持。

dragstartdragoverdragleavedrop events不適用於所有觸控設備。

您必須為觸摸事件使用適當的事件名稱,例如:

  • touchstart
  • touchend
  • touchcancel
  • touchmove

閱讀有關此事件的文檔

為了為基於觸摸的用戶界面提供高質量的支持,觸摸事件提供了在觸摸屏或觸控板上解釋手指(或觸控筆)活動的能力。

觸摸事件接口是相對低級的API,可用於支持特定於應用程序的多點觸摸交互,例如雙指手勢。 當手指(或觸筆)首先接觸接觸表面時,多觸摸交互開始。 其他手指隨后可以觸摸表面並且可選地在觸摸表面上移動。 當手指從表面移除時,相互作用結束。 在此交互期間,應用程序在開始,移動和結束階段接收觸摸事件。

觸摸事件類似於鼠標事件,除了它們支持同時觸摸和觸摸表面上的不同位置。 TouchEvent界面封裝了當前活動的所有觸摸點。 Touch界面代表單個觸摸點,包括諸如觸摸點相對於瀏覽器視口的位置之類的信息。

不幸的是,事件touchentertouchleave已從規范中刪除,因此,如果您需要它,那么您必須使用document.elementFromPoint()編寫一個解決方法,如下所示:

document.addEventListener('touchmove', function(e)
{
    var touch = e.touches[0],
        elementFromPoint = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset);

    if(elem == elementFromPoint) //elem is your element which was entered
    {
        //your code for touchenter event
    }
    else //the code for touchleave event
});

也許對於其他一些移動設備和他們的瀏覽器,你將需要使用polyfills( 12 ),這使得移動(觸摸)設備HTML5拖放支持。

我在這里分叉你的codepen測試用例: https ://codepen.io/bobacus/pen/MLjZMg

我想知道是否需要將偵聽器添加到<li>元素中,因此更改了一些代碼:

listEl = document.getElementById('my_list');
for (var i = 0; i < listEl.children.length; i ++) {
    itemEl = listEl.children[i];
    itemEl.addEventListener('dragstart', function(event) {
      dragging = getLI(event.target);
      if (dragging) {
          event.dataTransfer.setData('text/plain', null);
          event.dataTransfer.setDragImage(dragging, 0, 0);
      }
    });
}

但那沒用。

我嘗試了一些不同的東西,但最終在Safari中使用的是添加這里描述的polyfill: https//www.codeproject.com/Articles/1091766/Add-support-for-standard-HTML-Drag-and -drop-OPERAT

我將其添加到HTML代碼段的頂部:

<script src="http://bernardo-castilho.github.io/DragDropTouch/DragDropTouch.js"></script>

我希望這是有幫助的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM