事件传播、覆盖和拖放事件

发布于 2024-12-27 22:58:25 字数 1748 浏览 1 评论 0原文

当用户将文件拖到窗口上时,我想在视口上覆盖一个 div。

但是,我在事件传播方面遇到了麻烦。当我将叠加层设置为 display: block 时,它似乎会触发一个 dragleave 事件,然后触发另一个 dragenter ,然后触发另一个 dragleave< /code> 再次,因此它始终处于拖后状态。当然,我在事件对象上调用 e.stopPropagation()e.preventDefault() ,但这似乎没有什么区别。

当您将某些内容拖到窗口上时,console.log() 输出:

龙人
拖拽者
拖离
德拉格特
拖拽离开

CSS。 #overlay 默认设置为 display: none,但会显示 body 是否具有 dragenter

    body {
        position: absolute;
        height: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: 0;
        padding: 0;
    }

    #overlay {
        position: absolute;        
        height: auto;
        width: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: url(bg.png) repeat-x top right, url(bg.png) repeat-x bottom left, url(bg.png) repeat-y top right, url(bg.p
ng) repeat-y bottom left;
        display: none;
    }

    body.dragenter #overlay {
        display: block;
    }

: JavaScript;在 dragenter 上添加 'dragenter' 类,并在 dragleave 上删除它:

$(document).on('dragenter', function (e) {
    e.stopPropagation();
    e.preventDefault();
    console.log('dragenter');
    $(document.body).addClass('dragenter');
});

$(document).on('dragleave', function (e) {
    e.stopPropagation();
    e.preventDefault();
    console.log('dragleave';
    $(document.body).removeClass('dragenter');
});

html:

<body>
<div id="overlay">...</div>
...    
</body>

I want to overlay a div over the viewport when the user drags a file onto the window.

However, I'm having trouble with the event propagation. When I set the overlay to display: block it appears to fire off a dragleave event and then another dragenter and then another dragleave again, so it's always in a post-dragleave state. Of course I call e.stopPropagation() and e.preventDefault() on the event object, but it doesn't seem to make a difference.

The console.log() output when you drag something over the window:

dragenter
dragenter
dragleave
dragenter
dragleave

The css. #overlay is set to display: none by default, but will show if body has the dragenter class:

    body {
        position: absolute;
        height: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        margin: 0;
        padding: 0;
    }

    #overlay {
        position: absolute;        
        height: auto;
        width: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: url(bg.png) repeat-x top right, url(bg.png) repeat-x bottom left, url(bg.png) repeat-y top right, url(bg.p
ng) repeat-y bottom left;
        display: none;
    }

    body.dragenter #overlay {
        display: block;
    }

The JavaScript; add the 'dragenter' class on dragenter and removes it on dragleave:

$(document).on('dragenter', function (e) {
    e.stopPropagation();
    e.preventDefault();
    console.log('dragenter');
    $(document.body).addClass('dragenter');
});

$(document).on('dragleave', function (e) {
    e.stopPropagation();
    e.preventDefault();
    console.log('dragleave';
    $(document.body).removeClass('dragenter');
});

The html:

<body>
<div id="overlay">...</div>
...    
</body>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

对不⑦ 2025-01-03 22:58:25

您的覆盖层占据了整个文档大小,当您拖入时,它会填满其空间,并且您的鼠标实际上已从正文中取出,现在位于覆盖层上方。这会触发 mouseleave/mouseenter 循环。为了实现您想要的目标,您可能希望将事件绑定到具有较高 z-index 的透明覆盖层,而不是具有较低 z-index 的可见覆盖层。这将使事件保持在最高元素中。

示例:

http://jsfiddle.net/scottux/z7yaB/

Your overlay takes up the whole document size, when you drag in, it fills up its space and your mouse is effectively taken out of the body and is now over the overlay. This triggers a mouseleave/mouseenter loop. To achieve what you are after, you may want to bind the event to a transparent overlay with a high z-index over the visible overlay which has a lower z-index. This would keep the event in the highest element.

Example:

http://jsfiddle.net/scottux/z7yaB/

心碎的声音 2025-01-03 22:58:25

感谢 Scottux,让我走上了正确的道路。

唯一的问题是它还覆盖了页面的其余部分,因此没有任何元素或输入是可单击的。默认情况下,我必须使用“display: none”隐藏 #dragOverlay 并在此事件中显示它

// Display an overlay when dragging a file over
$('*:visible').live('dragenter', function(e) {
    e.stopPropagation();
    $('body').addClass('drag-enter');
});

Thanks to Scottux, that led me onto the right track.

Only problem was it also covered up the rest of the page, so none of the elements or inputs were clickable. I had to hide #dragOverlay by default with "display: none" and display it on this event

// Display an overlay when dragging a file over
$('*:visible').live('dragenter', function(e) {
    e.stopPropagation();
    $('body').addClass('drag-enter');
});
巴黎夜雨 2025-01-03 22:58:25
    var dropZone = function() {
        var self = this;
        this.eTimestamp = 0;
        this.showDropZone = function(e) {
            e.stopPropagation();
            e.preventDefault();
            if (self.eTimestamp + 300 < e.timeStamp) {
                $("#coverDropZone").show();
                self.eTimestamp = e.timeStamp;
            }
            return false;
        }
        this.hideDropZone = function(e) {
            e.stopPropagation();
            e.preventDefault();
            if (self.eTimestamp + 300 < e.timeStamp) {
                $("#coverDropZone").hide();
                self.eTimestamp = e.timeStamp;
            }
            return false;
        }
        this.showImage = function(e) {
            e.stopPropagation();
            e.preventDefault();
            console.log(e);
            return false;
        }
        document.addEventListener('dragenter', self.showDropZone, false);
        document.addEventListener('dragleave', self.hideDropZone, false);
        document.addEventListener('drop', self.showImage, false);
    }
    var dropZone = function() {
        var self = this;
        this.eTimestamp = 0;
        this.showDropZone = function(e) {
            e.stopPropagation();
            e.preventDefault();
            if (self.eTimestamp + 300 < e.timeStamp) {
                $("#coverDropZone").show();
                self.eTimestamp = e.timeStamp;
            }
            return false;
        }
        this.hideDropZone = function(e) {
            e.stopPropagation();
            e.preventDefault();
            if (self.eTimestamp + 300 < e.timeStamp) {
                $("#coverDropZone").hide();
                self.eTimestamp = e.timeStamp;
            }
            return false;
        }
        this.showImage = function(e) {
            e.stopPropagation();
            e.preventDefault();
            console.log(e);
            return false;
        }
        document.addEventListener('dragenter', self.showDropZone, false);
        document.addEventListener('dragleave', self.hideDropZone, false);
        document.addEventListener('drop', self.showImage, false);
    }
甜中书 2025-01-03 22:58:25

简单的解决方案是不使用 dragenter 使用 dragover

Dragover
当发生拖动时鼠标移到元素上时会触发此事件。大多数时候,侦听器期间发生的操作与 Dragenter 事件相同。

The simple solution is instead of using dragenter use dragover

dragover
This event is fired as the mouse is moved over an element when a drag is occurring. Much of the time, the operation that occurs during a listener will be the same as the dragenter event.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文