【问题标题】:How can I handle File drag and drop with a window overlay and multiple drop zones?如何使用窗口覆盖和多个拖放区处理文件拖放?
【发布时间】:2017-07-07 15:05:30
【问题描述】:

我希望能够检测用户何时将文件拖入窗口并在整个应用程序上弹出一个覆盖层,显示用户可以将文件上传到的各种文件夹。

到目前为止,我知道我可以收听“dragenter”的窗口并显示我的叠加层,并收听“dragleave”的叠加层以隐藏它,但问题似乎是拖动拖放区会导致触发叠加层的 dragleave 事件,使叠加层隐藏(使窗口的 dragenter 事件显示叠加层,依此类推)。

我将 Dropzone.js 用于我的文件夹 dropzones。我环顾四周,看到了与我类似的问题,但没有一个能解决这个问题。

编辑:我在 StackOverflow 的其他地方找到了(某种)解决方案:jQuery Drag-and-Drop Flickering on Hover (Webkit only)

解决方案是检查dragleave 上的事件,如果pageX 和pageY 都为0,则表示dragleave 是因为用户离开了窗口,而不是拖动到其中一个dropzone 上。

【问题讨论】:

  • 您要显示叠加层的目的是什么?停止文件上传?
  • 该页面默认显示已上传的文件。当用户将文件拖到屏幕上时,叠加层将显示他们可以上传到的可用文件夹(有点像 imgur.com 处理文件上传叠加层的方式,除了有多个放置区且没有全局放置区)。因此,叠加层的目的是向用户显示文件夹放置区。
  • 您只是想显示叠加层或期望用户输入,例如从叠加层中选择文件夹?
  • 我想在用户拖动文件时显示覆盖。叠加层包含文件的放置区。然后,用户将文件拖放到叠加层的放置区之一,叠加层就会消失。
  • 这个答案提供了关于这个问题的更多细节stackoverflow.com/questions/12945307/…

标签: javascript drag-and-drop dropzone.js


【解决方案1】:

在这种特定情况下(在全屏叠加层中使用 Dropzone 实例,该实例仅在拖动文件时可见,并且您只希望用户将文件拖放到 dropzones 而不是整个叠加层),这是我为解决问题所做的.

  • 在窗口中收听“dragenter”
    • 如果事件 dataTransfer 对象有一个 types 数组,其中存在 1 个项目并且 types[0] == "Files" 则显示叠加层(这样,如果拖动文本之类的内容,我们就不会显示叠加层)李>
  • 在叠加层上监听“dragleave”
    • 如果 dragleave 事件 pageX 和 pageY 都为 0,则用户拖出文档,我们应该隐藏叠加层,否则他们将拖过其中一个放置区
  • 在叠加层上收听“dragover”
    • 如果屏幕上有任何元素具有“dz-drag-hover”类,则将事件 dataTransfer.dropEffect 设置为“copy”,因为我们将鼠标悬停在 dropzone 上
    • 否则将事件 dataTransfer.dropEffect 设置为“none”和 preventDefault()

这里有一些未经测试的 javascript:

function handleDragEnter( e ) {
    // make sure we're dragging a file
    var dt = ( e && e.dataTransfer );
    var isFile = ( dt && dt.types && dt.types.length == 1 && dt.types[0] == "Files" );
    if ( isFile ) {
        // and, if so, show the overlay
        showOverlay();
    }
}

function handleDragLeave( e ) {
    // was our dragleave off the page?
    if ( e && e.pageX == 0 && e.pageY == 0 ) {
        // then hide the overlay
        hideOverlay();
    }
}

function handleDragOver(e) {
    // look for any dropzones being hovered
    var isHovering = document.getElementsByClassName( "dz-drag-hover" ).length > 0;
    if ( isHovering ) {
        // found some? then we're over a dropzone and want to allow dropping
        e.dataTransfer.dropEffect = 'copy';
    } else {
        // we're just on the overlay. don't allow dropping.
        e.dataTransfer.dropEffect = 'none';
        e.preventDefault();
    }
}

function showOverlay() {
    // only show the overlay if it's not already shown (can prevent flickering)
    if ( getComputedStyle(overlay, null).display == "none" ) 
        overlay.style.display = "block";
    }
}

function hideOverlay() {
    overlay.style.display = "none";
}

// listen to dragenter on the window for obvious reasons
window.addEventListener("dragenter", handleDragEnter);
// our fullscreen overlay will cover up the window, so we need to listen to it for dragleave events
overlay.addEventListener("dragleave", handleDragLeave);
// same thing for dragover
overlay.addEventListener("dragover", handleDragOver);

【讨论】:

    【解决方案2】:

    dragleave 事件的触发速度比我们想象的要快,因此我们可以延迟该过程。

     Dropzone.autoDiscover = false;
    $("div#upload").dropzone({
        url: "upload.php",
        addRemoveLinks:true,
        paramName:"composeUpload",
        init: function() {
            myDropZone = this;
            this.on('dragover', function(e,xhr,formData){
               $('.overlay').fadeIn();
              stopLoading(); //stops local file opens
                return false;
            });
          this.on('dragleave', function(e,xhr,formData){
               setTimeout(function(){
                 $('.overlay').fadeIn();
               },8000);
            });           
        }
    });
    

    如果您将文件放在空 div 或覆盖上,浏览器将在本地打开文件,因此我们必须停止默认设置

    function stopLoading(){
       window.addEventListener("dragover",function(e){
        e = e || event;
        e.preventDefault();
       },false);
      window.addEventListener("drop",function(e){
        e = e || event;
        e.preventDefault();
      },false);
    }
    

    我不认为这是您要寻找的答案,但它肯定会给您一个想法。谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-08
      • 2020-06-01
      • 1970-01-01
      • 2019-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多