Detect mousemove when over an iframe?

后端 未结 11 567
Happy的楠姐
Happy的楠姐 2020-11-29 05:47

I have an iframe that takes up the entire window (100% wide, 100% high), and I need the main window to be able to detect when the mouse has been moved.

Already tried

相关标签:
11条回答
  • 2020-11-29 06:18

    I have been faced with a similar issue, where I had div's that I wanted to drag around over an iFrame. Problem was that if the mouse pointer moved outside the div, onto the iFrame, the mousemove events were lost and the div stopped dragging. If this is the sort of thing you want to do (as opposed to just detecting the user waving the mouse over the iFrame), I found a suggestion in another question thread which seems to work well when I tried it.

    In the page that contains the and the things you want to drag, also include a like this:

    <div class="dragSurface" id="dragSurface">
    <!-- to capture mouse-moves over the iframe-->
    </div>
    

    Set it's initial style to be something like this:

    .dragSurface
    {
      background-image: url('../Images/AlmostTransparent.png');
      position: absolute;
      z-index: 98;
      width: 100%;
      visibility: hidden;
    }
    

    The z-index of '98' is because I set the div's I want to drag around to be z-index:99, and the iFrame at z-index:0.

    When you detect the mousedown in the to-be-dragged object (not the dragSurface div), call the following function as part of your event handler:

    function activateDragSurface ( surfaceId )
    {
      var surface = document.getElementById( surfaceId );
      if ( surface == null ) return;
    
      if ( typeof window.innerWidth != 'undefined' )
      { viewportheight = window.innerHeight; } 
      else
      { viewportheight = document.documentElement.clientHeight; }
    
      if ( ( viewportheight > document.body.parentNode.scrollHeight ) && ( viewportheight > document.body.parentNode.clientHeight ) )
      { surface_height = viewportheight; }
      else
      {
        if ( document.body.parentNode.clientHeight > document.body.parentNode.scrollHeight )
        { surface_height = document.body.parentNode.clientHeight; }
        else
        { surface_height = document.body.parentNode.scrollHeight; }
      }
    
      var surface = document.getElementById( surfaceId );
      surface.style.height = surface_height + 'px';
      surface.style.visibility = "visible";
    }
    

    Note: I cribbed most of that from somebody else's code I found on the internet! The majority of the logic is just there to set the size of the dragSurface to fill the frame.

    So, for example, my onmousedown handler looks like this:

    function dragBegin(elt)
    {
      if ( document.body.onmousemove == null )
      {
        dragOffX = ( event.pageX - elt.offsetLeft );
        dragOffY = ( event.pageY - elt.offsetTop );
        document.body.onmousemove = function () { dragTrack( elt ) };
        activateDragSurface( "dragSurface" ); // capture mousemoves over the iframe.
      }
    }
    

    When dragging stops, your onmouseup handler should include a call to this code:

    function deactivateDragSurface( surfaceId )
    {
      var surface = document.getElementById( surfaceId );
      if ( surface != null ) surface.style.visibility = "hidden";
    }
    

    Finally, you create the background image (AlmostTransparent.png in my example above), and make it anything except completely transparent. I made an 8x8 image with alpha=2.

    I have only tested this in Chrome so far. I need to get it working in IE as well, and will try and update this answer with what I discover there!

    0 讨论(0)
  • 2020-11-29 06:19

    MouseEvent.initMouseEvent() is now deprecated, so @Ozan's answer is a bit dated. As an alternative to what's provided in his answer, I'm now doing it like this:

    var bubbleIframeMouseMove = function( iframe ){
    
        iframe.contentWindow.addEventListener('mousemove', function( event ) {
            var boundingClientRect = iframe.getBoundingClientRect();
    
            var evt = new CustomEvent( 'mousemove', {bubbles: true, cancelable: false})
            evt.clientX = event.clientX + boundingClientRect.left;
            evt.clientY = event.clientY + boundingClientRect.top;
    
            iframe.dispatchEvent( evt );
    
        });
    
    };
    

    Where I'm setting clientX & clientY you'll want to pass any info from the content window's event to the event we'll be dispatching (i.e., if you need to pass something like screenX/screenY, do it there).

    0 讨论(0)
  • 2020-11-29 06:20

    The page inside your iframe is a complete document. It will consume all events and have no immediate connection to it's parent document.

    You will need to catch the mouse events from javascript inside the child document and then pass this somehow to the parent.

    0 讨论(0)
  • 2020-11-29 06:25
    <script>
    // dispatch events to the iframe from its container
    $("body").on('click mouseup mousedown touchend touchstart touchmove mousewheel', function(e) {
        var doc = $("#targetFrame")[0].contentWindow.document,
            ev = doc.createEvent('Event');
        ev.initEvent(e.originalEvent.type, true, false);
        for (var key in e.originalEvent) {
            // we dont wanna clone target and we are not able to access "private members" of the cloned event.
            if (key[0] == key[0].toLowerCase() && $.inArray(key, ['__proto__', 'srcElement', 'target', 'toElement']) == -1) {
                ev[key] = e.originalEvent[key];
            }
        }
        doc.dispatchEvent(ev);
    });
    </script>
    <body>
    <iframe id="targetFrame" src="eventlistener.html"></iframe>
    </body>
    
    0 讨论(0)
  • 2020-11-29 06:28

    Iframes capture mouse events, but you can transfer the events to the parent scope if the cross-domain policy is satisfied. Here's how:

    // This example assumes execution from the parent of the the iframe
    
    function bubbleIframeMouseMove(iframe){
        // Save any previous onmousemove handler
        var existingOnMouseMove = iframe.contentWindow.onmousemove;
    
        // Attach a new onmousemove listener
        iframe.contentWindow.onmousemove = function(e){
            // Fire any existing onmousemove listener 
            if(existingOnMouseMove) existingOnMouseMove(e);
    
            // Create a new event for the this window
            var evt = document.createEvent("MouseEvents");
    
            // We'll need this to offset the mouse move appropriately
            var boundingClientRect = iframe.getBoundingClientRect();
    
            // Initialize the event, copying exiting event values
            // for the most part
            evt.initMouseEvent( 
                "mousemove", 
                true, // bubbles
                false, // not cancelable 
                window,
                e.detail,
                e.screenX,
                e.screenY, 
                e.clientX + boundingClientRect.left, 
                e.clientY + boundingClientRect.top, 
                e.ctrlKey, 
                e.altKey,
                e.shiftKey, 
                e.metaKey,
                e.button, 
                null // no related element
            );
    
            // Dispatch the mousemove event on the iframe element
            iframe.dispatchEvent(evt);
        };
    }
    
    // Get the iframe element we want to track mouse movements on
    var myIframe = document.getElementById("myIframe");
    
    // Run it through the function to setup bubbling
    bubbleIframeMouseMove(myIframe);
    

    You can now listen for mousemove on the iframe element or any of its parent elements -- the event will bubble up as you would expect.

    This is compatible with modern browsers. If you need it to work with IE8 and below, you'll need to use the IE-specific replacements of createEvent, initMouseEvent, and dispatchEvent.

    0 讨论(0)
  • 2020-11-29 06:30

    you can add a overlay on top of iframe when drag begin ( onmousedown event ) , and remove it when drag end ( on mouserup event ). the jquery UI.layout plugin use this method to solve this problem.

    0 讨论(0)
提交回复
热议问题