web-dev-qa-db-ja.com

iframe上にあるときにmousemoveを検出しますか?

ウィンドウ全体(幅100%、高さ100%)を占めるiframeがあり、マウスが移動されたことをメインウィンドウで検出できるようにする必要があります。

すでにiframeでonMouseMove属性を試しましたが、明らかに機能しませんでした。また、iframeをdivでラップしてみました:

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

..そしてそれはうまくいきませんでした。助言がありますか?

25
Charles Zink

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以下で動作させる必要がある場合は、createEventinitMouseEvent、およびdispatchEventのIE固有の置換を使用する必要があります。

24
Ozan

ターゲットがOpera 9以下およびIE 9以下でない場合、css属性pointer-events: none

Iframeを無視するのが最善の方法だと思いました。この属性を持つクラスをonMouseDownイベントでiframeに追加し、onMouseUpイベントで削除します。

私にぴったりの作品。

24
Jagi

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

    });

};

clientXclientYを設定している場所で、コンテンツウィンドウのイベントからディスパッチするイベントに情報を渡します(つまり、screenX/screenYのようなものを渡す必要がある場合は、そこで実行します)。

10
jeremy

Iframe内のページは完全なドキュメントです。すべてのイベントを消費し、その親ドキュメントへの直接の接続はありません。

子ドキュメント内のJavaScriptからマウスイベントをキャッチし、これを何らかの方法で親に渡す必要があります。

7
IanNorton

「親」フレームで、「子」iframeを選択し、興味のあるイベントを検出しますmousemove

これは、「親」フレームで使用されるコードの例です

document.getElementById('yourIFrameHere').contentDocument.addEventListener('mousemove', function (event) {
                console.log(, event.pageX, event.pageY, event.target.id);
            }.bind(this));
6
GibboK

これを解決する別の方法は、_mouse down_のようなものを使用して、iframe(s)のマウス移動イベントを無効にすることです。

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

次に、_mouse up_のiframe(s)でマウス移動イベントを再度有効にします。

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

上記の他のアプローチのいくつかを試してみましたが、うまくいきましたが、これが最も簡単なアプローチのようです。

クレジット: https://www.gyrocode.com/articles/how-to-detect-mousemove-event-over-iframe-element/

6
Bob

私は同様の問題に直面しており、iFrameの上にドラッグしたいdivがありました。問題は、マウスポインターが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ではない)でマウスダウンを検出したら、イベントハンドラーの一部として次の関数を呼び出します。

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同様に、私がそこで見つけたものでこの答えを更新しようとします!

4
Loophole
<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>
3
Anssi

私は、iframeとその横にdivが配置されたlongのサイズを変更する必要があった同様の問題について、比較的簡単な解決策を見つけました。マウスがiframe上に移動すると、jqueryはマウスの検出を停止します。

これを修正するために、divのi-frameに座って、divのz-index(0に設定)とiframe(1に設定)を除いて、同じ領域を同じスタイルで塗りつぶしました。これにより、サイズ変更しない場合にiframeを通常どおり使用できます。

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

サイズを変更すると、div z-indexは2に設定され、その後0に戻ります。つまり、iframeは引き続き表示されていましたが、オーバーレイがそれをブロックしていたため、マウスを検出できました。

2
Alistair

このコードはうまくいくようですが、あまりうまくいきません:

<div id="test" onmousemove="alert('test');">
    <iframe style="width:200px; height:200px; border:1px solid black;">
        <p>test</p>
    </iframe>
</div>  

イベントはすべてのマウスの動きでmotトリガーを行いますが、それらの一部でのみトリガーします。そのイベント内にある種の内部イベントバッファーがあるかどうかはわかりません。

0
Thor Jacobsen

ドラッグ開始時に(onmousedownイベント)、iframeの上にオーバーレイを追加し、ドラッグ終了時に(mouserrupイベントで)オーバーレイを削除できます。 jquery UI.layout plugin このメソッドを使用してこの問題を解決します。

0
sodarfish

これがjQueryを使用した私のソリューションです。以下のように、複数のイベントを検出できます。 .on( 'load')イベントハンドラー内に.on()イベントハンドラーを配置する必要があります。そうしないと、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
}
0
drolex