35

我有一个占据整个窗口(100% 宽,100% 高)的 iframe,我需要主窗口能够检测鼠标何时移动。

已经onMouseMove在 iframe 上尝试了一个属性,但它显然不起作用。还尝试将 iframe 包装在 div 中,如下所示:

<div onmousemove="alert('justfortesting');"><iframe src="foo.bar"></iframe></div>

..它没有用。有什么建议么?

4

12 回答 12

34

如果您的目标不是 Opera 9 或更低版本和 IE 9 或更低版本,您可以使用 css attribute pointer-events: none

我发现这是忽略 iframe 的最佳方法。我在事件中将具有此属性的类添加到 iframe 并在onMouseDown事件中删除onMouseUp

非常适合我。

于 2012-08-08T12:58:10.607 回答
28

iframe 捕获鼠标事件,但如果满足跨域策略,您可以将事件转移到父范围。就是这样:

// 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);

您现在可以在 iframe 元素或其任何父元素上侦听 mousemove ——该事件将如您​​预期的那样冒泡。

这与现代浏览器兼容。如果您需要它与 IE8 及更低版本一起使用,则需要使用 IE 特定的替换createEventinitMouseEventdispatchEvent.

于 2013-03-10T02:44:43.703 回答
13

解决这个问题的另一种方法对我来说很有效,是在 上禁用鼠标移动事件,iframe(s)例如mouse down

$('iframe').css('pointer-events', 'none');

然后,在iframe(s)上重新启用鼠标移动事件mouse up

$('iframe').css('pointer-events', 'auto');

我尝试了上面的一些其他方法并且它们有效,但这似乎是最简单的方法。

归功于:https ://www.gyrocode.com/articles/how-to-detect-mousemove-event-over-iframe-element/

于 2018-05-18T18:42:55.910 回答
10

MouseEvent.initMouseEvent()现在已弃用,所以@Ozan 的回答有点过时了。作为他回答中提供的替代方案,我现在这样做:

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 );

    });

};

我在哪里设置clientX&clientY你会想要将任何信息从内容窗口的事件传递给我们将要调度的事件(即,如果你需要传递类似screenX/的东西screenY,就在那里做)。

于 2016-07-18T17:11:27.857 回答
8

iframe 中的页面是一个完整的文档。它将消耗所有事件并且与它的父文档没有直接联系。

您需要从子文档中的 javascript 捕获鼠标事件,然后以某种方式将其传递给父文档。

于 2011-04-13T07:02:18.750 回答
7

我遇到过类似的问题,我有 div 我想在 iFrame 上拖动。问题是,如果鼠标指针移到 div 之外,移到 iFrame 上,mousemove 事件就会丢失并且 div 停止拖动。如果这是您想要做的事情(而不是仅仅检测用户在 iFrame 上挥动鼠标),我在另一个问题线程中发现了一个建议,当我尝试它时似乎效果很好。

在包含 和要拖动的内容的页面中,还包括这样的:

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

将其初始样式设置为如下所示:

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

'98' 的 z-index 是因为我将要拖动的 div 设置为 z-index:99,并将 iFrame 设置为 z-index:0。

当您在要拖动的对象(而不是 dragSurface div)中检测到 mousedown 时,调用以下函数作为事件处理程序的一部分:

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";
}

注意:我从网上找到的其他人的代码中抄袭了大部分内容! 大部分逻辑只是用于设置 dragSurface 的大小以填充框架。

因此,例如,我的 onmousedown 处理程序如下所示:

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.
  }
}

当拖动停止时,您的 onmouseup 处理程序应包含对此代码的调用:

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

最后,您创建背景图像(在我上面的示例中为AlmostTransparent.png),并将其设置为除完全透明之外的任何内容。我制作了一张 alpha=2 的 8x8 图像。

到目前为止,我只在 Chrome 中对此进行了测试。我也需要让它在 IE 中工作,并将尝试用我在那里发现的内容更新这个答案!

于 2012-03-19T03:44:13.377 回答
6

在您的“父”框架上,选择您的“子”iframe 并根据您的情况检测您感兴趣的事件mousemove

这是要在“父”框架中使用的代码示例

document.getElementById('yourIFrameHere').contentDocument.addEventListener('mousemove', function (event) {
                console.log(, event.pageX, event.pageY, event.target.id);
            }.bind(this));
于 2015-04-09T07:31:33.870 回答
5

对于我遇到的类似问题,我找到了一个相对简单的解决方案,我想调整 iframe 的大小和一个长在它旁边的 div。一旦鼠标经过 iframe jquery 将停止检测鼠标。

为了解决这个问题,我让一个 div 与 iframe 一起使用相同的样式填充相同的区域,除了 div 的 z-index(设置为 0)和 iframe(设置为 1)。这允许 iframe 在不调整大小时正常使用。

<div id="frameOverlay"></div>  
<iframe></iframe>

调整大小时,div z-index 设置为 2,然后再设置为 0。这意味着 iframe 仍然可见,但覆盖层阻止了它,从而可以检测到鼠标。

于 2014-04-20T06:52:59.993 回答
3
<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>
于 2013-06-04T09:47:42.403 回答
1

文档中的基本方式

var IE = document.all?true:false;

// If NS -- that is, !IE -- then set up for mouse capture
if (!IE) document.captureEvents(Event.MOUSEMOVE);

// Set-up to use getMouseXY function onMouseMove
document.onmousemove = getMouseXY;

// Temporary variables to hold mouse x-y pos.s
var tempX = 0;
var tempY = 0;

// Main function to retrieve mouse x-y pos.s

function getMouseXY(e) {
  if (IE) { // grab the x-y pos.s if browser is IE
    tempX = event.clientX + document.body.scrollLeft;
    tempY = event.clientY + document.body.scrollTop;
  } else {  // grab the x-y pos.s if browser is NS
    tempX = e.pageX;
    tempY = e.pageY;
  }  
  // catch possible negative values in NS4
  if (tempX < 0){tempX = 0}
  if (tempY < 0){tempY = 0}  

  // show the position values in the form named Show
  // in the text fields named MouseX and MouseY
  console.log(tempX, tempY);
  return true;
}

检测鼠标在 iframe 上的移动

window.frames['showTime'].document.onmousemove = getMouseXY;

检测鼠标在父 iframe 下的子 iframe 中移动

window.frames['showTime'].document.getElementById("myFrame").contentWindow.onmousemove = getMouseXY;

当浏览器中没有鼠标移动时触发 IDLE 检测功能。

于 2021-01-19T09:22:31.150 回答
1

这是我使用 jQuery 的解决方案。您可以像我在下面那样检测多个事件。将 .on() 事件处理程序放在 .on('load') 事件处理程序中是必要的,因为当 iframe 导航到新页面时,它将停止检测 iframe 内容事件。此外,我相信这仅在 iframe 内容与父页面出于安全原因位于同一域中时才有效,并且没有办法解决这个问题。

$(document).ready(function() {
    $('#iframe_id').on('load', function() {
        $('#iframe_id').contents().on('click mousemove scroll', handlerFunction);
    });
});

handlerFunction() {
    //do stuff here triggered by events in the iframe
}
于 2020-01-24T22:22:33.180 回答
0

您可以在拖动开始时(onmousedown 事件)在 iframe 顶部添加叠加层,并在拖动结束时将其删除(在 mouserup 事件中)。jquery UI.layout 插件使用这种方法来解决这个问题。

于 2013-07-13T11:57:51.237 回答