[英]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>
https://imgur.com/a/I8hzPxC (尺寸太大,無法直接嵌入)
為什么這不適用於iOS? 我甚至無法啟動dragstart
事件。 在Android Chrome上,longpress會觸發dragstart
。
我的后備想法是使用touchstart
和touchend
進行長按,然后創建我自己的絕對定位的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的支持。
dragstart
, dragover
, dragleave
, drop
events不適用於所有觸控設備。
您必須為觸摸事件使用適當的事件名稱,例如:
touchstart
touchend
touchcancel
touchmove
閱讀有關此事件的文檔 。
為了為基於觸摸的用戶界面提供高質量的支持,觸摸事件提供了在觸摸屏或觸控板上解釋手指(或觸控筆)活動的能力。
觸摸事件接口是相對低級的API,可用於支持特定於應用程序的多點觸摸交互,例如雙指手勢。 當手指(或觸筆)首先接觸接觸表面時,多觸摸交互開始。 其他手指隨后可以觸摸表面並且可選地在觸摸表面上移動。 當手指從表面移除時,相互作用結束。 在此交互期間,應用程序在開始,移動和結束階段接收觸摸事件。
觸摸事件類似於鼠標事件,除了它們支持同時觸摸和觸摸表面上的不同位置。 TouchEvent界面封裝了當前活動的所有觸摸點。 Touch界面代表單個觸摸點,包括諸如觸摸點相對於瀏覽器視口的位置之類的信息。
不幸的是,事件touchenter
和touchleave
已從規范中刪除,因此,如果您需要它,那么您必須使用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( 1 , 2 ),這使得移動(觸摸)設備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.