javascript - HTML5 拖放 - 不适用于 iOS 12.1.2(Safari 和 Chrome)

标签 javascript ios html drag-and-drop webkit

背景

我有一个可通过拖放进行排序的列表。它在桌面浏览器和 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 上,长按会触发 dragstart

我的后备想法是使用 touchstarttouchend 进行长按,然后创建我自己的绝对定位幽灵元素并手动拖动它。当 drag* 事件应该正常工作时,这是很多额外的代码。

我错过了什么吗?

编辑

移动版 Safari 中的 LI 元素有一个 ondragstart 事件作为其原型(prototype)的一部分。问题是让它开火。

此外,根据 caniuse 的说法,移动版 Safari 应该支持这一点。但是,caniuse 还显示 Android Chrome 不支持,这是不正确的。

最佳答案

在过去的一周里,我对这个主题进行了大量研究,并且进行了大量测试和调试。我发现 iOS 支持拖动事件,但 iOS 不会触发它们。(从 iOS 12 开始)

如果您在 iOS Safari 上测试网页,您会看到所有 HTML 元素的原型(prototype)都附加了 ondragstart。拖动事件都在那里。他们只是永远不会被触发。

其他人也遇到过这个问题。事件现代化 doesn't detect Drag and Drop support因为这个错误的支持。

此外,我还浏览了 Safari 文档和 found this :

iOS Note: Although drag and drop are not supported, you can produce...

上面写着“supported”,但紧接着下面有一个事件表,显示了drag 并表示它不是“Generated”。

这意味着 caniuse目前是错误的,需要更新。


直接回答问题

代码无法正常工作仅仅是因为 Apple 选择不触发 拖动事件。

关于javascript - HTML5 拖放 - 不适用于 iOS 12.1.2(Safari 和 Chrome),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54237737/

相关文章:

jquery - 如何阻止 iOS 文本字段自动完成干扰 jQuery 自动完成?

jquery - 如何替换 HTML 标记的文本

JAVASCRIPT 检查 iframe 是否加载失败

javascript - Chrome 检查器控制台不适用于版本 54.0.2840.99

javascript - 在 native react 中使用带有地理定位的钩子(Hook)/状态我在哪里出错了?

Javascript:将子对象附加到对象的几个深度?

iOS 开发 : Is it necessary to change the class of the View Controller in the storyboard?

iphone - NSArray 到 NSData 用于核心数据

html - 如何将列表项 float 到页面顶部?

Javascript 的 indexOf 垫片说明?