简体   繁体   English

HTML5拖放行为

[英]HTML5 drag & drop behaviour

I'm making extensive use of the HTML5 native drag & drop, and it's almost entirely behaving itself, with one small exception. 我正在广泛使用HTML5本机拖放,它几乎完全表现自己,只有一个小例外。

I'm trying to highlight my dropzones when anything is dragged over the page. 当任何东西被拖到页面上时,我正在尝试突出显示我的下拉区域。 I originally tried to accomplish this by putting jQuery listeners on the document body, like this: 我最初试图通过在文档体上放置jQuery侦听器来实现这一点,如下所示:

$("body").live('dragover',function(event){lightdz(event)});
$("body").live('dragexit dragleave drop',function(event){dimdz(event)});

with lightdz() and dimdz() changing the background-color style property of all dropzones on the page to make them stand out. 使用lightdz()和dimdz()更改页面上所有dropzones的背景颜色样式属性,使它们脱颖而出。 This didn't work. 这没用。 Whenever a dragged object entered a child element on the page (like a div container), the listener would flag this up as a dragleave event and dim the dropzones. 每当拖动的对象进入页面上的子元素(如div容器)时,侦听器就会将其标记为dragleave事件并使dropzones变暗。

I got around this by applying the listener to all visible elements on the page, instead of just the body. 我通过将侦听器应用于页面上的所有可见元素而不仅仅是正文来解决这个问题。 There was occasionally a slight visible flickering on the dropzones when it crossed the boundary between one element and another, but it looked fine. 当它跨越一个元素和另一个元素之间的边界时,它们偶尔会出现轻微的可见闪烁,但它看起来很好。

Anyway, now I've changed lightdz() and dimdz() so that they apply a quick jQuery fadeTo() animation to all non-dropzones. 无论如何,现在我已经改变了lightdz()和dimdz(),以便他们将快速的jQuery fadeTo()动画应用到所有非dropzones。 This looks awesome when it works, and makes it very apparent to the user what they can and can't drop things on. 这在它工作时看起来很棒 ,并且使用户非常清楚他们可以做什么,也不能放弃。 The trouble is that when it passes between element boundaries, it applies the fade animation. 麻烦的是当它在元素边界之间传递时,它应用淡入淡出动画。 This is a lot more apparent than the occasional flicker of background-color, especially since if the object is dragged over multiple boundaries very quickly, it will queue the animations and have the page fade in and out repeatedly. 这比背景颜色的偶然闪烁要明显得多,特别是因为如果对象被快速拖过多个边界,它将对动画进行排队并使页面反复淡入淡出。

Even if I don't bother with the fadeTo() animation, and just change the opacity, it's a lot more visible than the background-color flicker, because the entire page changes rather than just the dropzone elements. 即使我不打扰fadeTo()动画,只是改变不透明度,它比背景颜色闪烁更明显,因为整个页面改变而不仅仅是dropzone元素。

Is there any way to reference the entire page as a single element for purposes of dragover and dragleave events? 有没有办法将整个页面作为单一元素引用以用于dragover和dragleave事件? Failing that, is there any way to detect a drop that takes place outside of the browser window? 如果失败了,有没有办法检测在浏览器窗口之外发生的丢弃? If I skip the dragleave event, it looks fine, but if any object is dragged over the browser window and then dropped outside it, the whole page stays faded. 如果我跳过dragleave事件,它看起来很好,但如果任何对象被拖过浏览器窗口然后掉到它外面,整个页面都会褪色。

I'm genuinely embarrassed by how easy this one was. 我真的很尴尬,这是多么容易。

$("*:visible").live('dragenter dragover',function(event){lightdz(event)});

$("#page").live('dragleave dragexit',function(event)
{
    if(event.pageX == "0")
       dimdz(event);
});

$("*:visible").live('drop',function(event){dimdz(event)});

#page is a page-wide container. #page是一个页面范围的容器。 If the dragleave event takes the dragged object outside of the browser window, event.pageX will have a value of 0. If it happens anywhere else, it'll have a non-zero value. 如果dragleave事件将拖动的对象移到浏览器窗口之外,则event.pageX的值为0.如果它在其他任何地方发生,则它将具有非零值。

I may be getting overly complex here but I would do something like this: 我可能在这里变得过于复杂,但我会做这样的事情:

var draggingFile = false;
var event2;

//elements with the class hotspots are OK
var hotspots = $(".hotspots");

//Handlers on the body for drag start & stop
$("body").live("dragover", function(event){ draggingFile = true; event2 = event; });
$("body").live("dragexit dragleave drop", function(event){ draggingFile = false; event2 = event; });

//Function checks to see if file is being dragged over an OK hotspot regardless of other elements infront
var isTargetOK = function(x, y){
    hotspots.each(function(i, el){
        el2 = $(el);
        var pos = el2.offset();
        if(x => pos.left && x <= pos.left+el2.width() && y => pos.top && y <= post.top+el2.height()){
            return true;
        }
    });
    return false;
};

//Mousemove handler on body
$("body").mousemove(function(e){
    //if user is dragging a file
    if(draggingFile){
        //Check to see if this is an OK element with mouse X & Y
        if(isOKTarget(e.pageX, e.pageY)){
            //Light em' up!
            lightdz(event2);
        } else { /* Fade em' :( */ dimdz(event2); }
    } else {
        dimdz(); //Having no parematers means just makes sure hotspots are off
    }
});

BTW that's probably not going to work straight off the bat, so you'll have to tweak it a bit to work with your code. 顺便说一句,这可能不会直接起作用,所以你必须稍微调整一下才能使用你的代码。

I tried the accepted solution here, but ended up using setTimeout to overcome the issue. 我在这里尝试了接受的解决方案,但最终使用setTimeout来克服这个问题。 I was having a ton of trouble with the page-wide container blocking the drop element if it was floated on top, and still causing the problem if it was the drop element. 我在页面范围内容器阻塞drop元素时遇到了很多麻烦,如果它在顶部浮动,并且如果它是drop元素仍然会导致问题。

<body style="border: 1px solid black;">
    <div id="d0" style="border: 1px solid black;">&nbsp;</div>
    <div id="d1" style="border: 1px solid black; display: none; background-color: red;">-&gt; drop here &lt;-</div>
    <div id="d2" style="border: 1px solid black;">&nbsp;</div>
    <div style="float: left;">other element</div>
    <div style="float: left;">&nbsp;-&nbsp;</div>
    <div style="float: left;">another element</div>
    <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
</body>
<script type="text/javascript">
    var resetTimer;

    var f = function(e)
    {
        if (e.type == "dragover")
        {
            e.stopPropagation();
            e.preventDefault();
            if (resetTimer)
            {
                clearTimeout(resetTimer);
            }
            document.getElementById('d1').style.display = '';
        }
        else
        {
            var f = function()
            {
                document.getElementById('d1').style.display = 'none';
            };
            resetTimer = window.setTimeout(f, 25);  
        }
    };

    document.body.addEventListener("dragover", f, true);
    document.body.addEventListener("dragleave", f, true);
    document.getElementById('d1').addEventListener("drop", function(e){ f(); alert('dropped'); }, false);
</script>

If you were to just call f(); 如果你只是调用f(); instead of window.setTimeout(f, 250); 而不是window.setTimeout(f, 250); , you'll see some nasty flickering of the element showing and hiding. ,你会看到一些令人讨厌的闪烁的元素显示和隐藏。

http://jsfiddle.net/guYWx/ http://jsfiddle.net/guYWx/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM