7

divのどちら側からマウスカーソルが来たかを検出する方法はありますか?

現在、私はこの方法を使用しています:

jQuery(this).bind('mousemove',function(e){
    offset_pos_x = parseInt(e.offsetX);
    offset_pos_y = parseInt(e.offsetY);
    ...

次に、マウスがdiv内をどの方向に移動したかを調べます。

問題は、この方法は少しバグが多いことです。これは、2つだけでなく、4つの側面すべてが必要なため、offsetXとoffsetYをチェックする必要があるためです。

たとえばX:+ 15、Y:-3(ピクセル単位)のようにマウスをdiv内に移動すると、マウスはx軸で15ピクセル移動しましたが、y軸では-3ピクセルしか移動しなかったため、マウスは左から移動したことがわかります。 。これに関するバグのあることは、XとYがほぼ同じで、マウスが左から来たのか上から来たのかわからない場合です(たとえば)。

また、私の他の質問(jQuery:mouseenter / mousemove / mouseoverは小さなdivと速いマウスの動きでは認識されません)によると、ブラウザー/ OSの制限により、イベントはdiv側の最初のピクセルで発生しません。そのため、私の「entered_at」座標はそれほど正確ではありません-例:

マウスカーソルをdiv内(左から)で非常に速く動かすと、「entered_at」座標はたとえばx:17、y:76になります。ここで、マウスを停止した後、たとえばx:6、y:76にマウスを左に移動すると、開始点とoffsetXの差が負になるため、「カーソルが右から来ました」関数がトリガーされます。

マウスカーソルが来た側を検出する別の方法はありますか?

あいさつ、パトリック

4

6 に答える 6

11

オフセットは使用しませんが、pageX / pageYを使用します(jQueryはこれらを正規化します)。カーソルの最初のmousemoveイベントが他のどのエッジよりも左端に近い場合、それは左から発生しました。また、mousemoveではなく、ホバーイベントを使用することを検討してください。

JSFiddle、ジャマイカの国旗の礼儀。 http://jsfiddle.net/MJTkk/1/

function closestEdge(x,y,w,h) {
        var topEdgeDist = distMetric(x,y,w/2,0);
        var bottomEdgeDist = distMetric(x,y,w/2,h);
        var leftEdgeDist = distMetric(x,y,0,h/2);
        var rightEdgeDist = distMetric(x,y,w,h/2);
        var min = Math.min(topEdgeDist,bottomEdgeDist,leftEdgeDist,rightEdgeDist);
        switch (min) {
            case leftEdgeDist:
                return "left";
            case rightEdgeDist:
                return "right";
            case topEdgeDist:
                return "top";
            case bottomEdgeDist:
                return "bottom";
        }
}

function distMetric(x,y,x2,y2) {
    var xDiff = x - x2;
    var yDiff = y - y2;
    return (xDiff * xDiff) + (yDiff * yDiff);
}
于 2013-02-22T09:12:52.297 に答える
9

これは、絶対位置のdivの修正を含む、スクリプトの正しい/機能する例です。turiyagを助けてくれてありがとう!

jsfiddle: http: //jsfiddle.net/MJTkk/2/

脚本:

$(function() {
    $("img").hover(function(e) {
        var el_pos = $(this).offset();
        var edge = closestEdge(e.pageX - el_pos.left, e.pageY - el_pos.top, $(this).width(), $(this).height());
        log('entered at: '+edge);
    }, function(e) {
        var el_pos = $(this).offset();
        var edge = closestEdge(e.pageX - el_pos.left, e.pageY - el_pos.top, $(this).width(), $(this).height());
        log('left at: '+edge+'<br><br>');
    });
});

function closestEdge(x,y,w,h) {
        var topEdgeDist = distMetric(x,y,w/2,0);
        var bottomEdgeDist = distMetric(x,y,w/2,h);
        var leftEdgeDist = distMetric(x,y,0,h/2);
        var rightEdgeDist = distMetric(x,y,w,h/2);

        var min = Math.min(topEdgeDist,bottomEdgeDist,leftEdgeDist,rightEdgeDist);
        switch (min) {
            case leftEdgeDist:
                return "left";
            case rightEdgeDist:
                return "right";
            case topEdgeDist:
                return "top";
            case bottomEdgeDist:
                return "bottom";
        }
}

function log(msg) {
    $("#console").append("<pre>" + msg + "</pre>");
}

function distMetric(x,y,x2,y2) {
    var xDiff = x - x2;
    var yDiff = y - y2;
    return (xDiff * xDiff) + (yDiff * yDiff);
}
于 2013-02-25T09:00:23.380 に答える
5

ジャマイカの旗のフィドルの最も近いエッジ関数は、それが可能なほど良くなく、特定の要素に対して不正確でした。関数を単純化して関数を削除するために、をoffsetX使用できます。offsetYdistMetric

// Pass object offsetX,offsetY,width,height
function closestEdge(distLeft,distTop,w,h){
    var distBottom = (h - distTop);
    var distRight = (w - distLeft);
    var min = Math.min(distTop, distBottom, distLeft, distRight);
    switch (min) {
        case distLeft:
            return "left";
        case distRight:
            return "right";
        case distTop:
            return "top";
        case distBottom:
            return "bottom";
    }
}

例えば:

$('.btn').on('mouseenter',function(e){
    var edge = closestEdge(e.offsetX, e.offsetY, $(this).width(), $(this).height());
});
于 2014-03-06T14:24:31.457 に答える
1

このコードでいくつかの問題が発生しました。長方形を操作すると、エッジが上にあるはずのときにエッジが正しく識別されないことがわかりました。私は答えを考え出すのに少し時間を費やし、私が共有したいと感じました:

var getDir = function( elem, e ) {       

            /** the width and height of the current div **/
            var w = elem.width();
            var h = elem.height();
            var offset = elem.offset();
            /** calculate the x and y to get an angle to the center of the div from that x and y. **/
            /** gets the x value relative to the center of the DIV and "normalize" it **/
            var x = (e.pageX - offset.left - (w/2)) * ( w > h ? (h/w) : 1 );
            var y = (e.pageY - offset.top  - (h/2)) * ( h > w ? (w/h) : 1 );

            /** the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123);**/
            /** first calculate the angle of the point, 
             add 180 deg to get rid of the negative values
             divide by 90 to get the quadrant
             add 3 and do a modulo by 4  to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/
            var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180 ) / 90 ) + 3 )  % 4;


            /** do your animations here **/ 
            switch(direction) {
             case 0:
                return 'top';
             break;
             case 1:
                return 'right';
             break;
             case 2:
                   return 'bottom';
             break;
             case 3:
                   return 'left';
             break;
            }

}


$(this).bind('mouseenter',function(e){
    //outputs the direction to the log
    console.log(getDir($(this), e));
});

クレジット:「マウスの方向」を使用したホバーのjQueryアニメーション

于 2013-06-18T10:02:44.060 に答える
0

ここにプラグイン

https ://github.com/JohnnyBeGood34/JQuery-MouseEntrance

お役に立てば幸いです。

于 2015-03-24T12:24:45.760 に答える
0

jQuery関数を使用して@Patrickのソリューションを改善し、さらにエレガントで堅牢なカスタムjQuery関数を作成しました。

これがjQuerygetMouseSidejsFiddleです

$(function () {
    $('img').hover(function (event) {
        log('entered at: ' + $(this).getMouseSide(event))
    }, function (event) {
        log('left at: ' + $(this).getMouseSide(event) + '<br><br>')
    })

    $.fn.getMouseSide = function (event) {
        function distanceMetric(x, y, x2, y2) {
            return Math.pow(x - x2, 2) + Math.pow(y - y2, 2)
        }

        function closestEdge(x, y, w, h) {
            var edgeDistance = {
                top:        distanceMetric(x, y, w / 2  , 0)
                , bottom:   distanceMetric(x, y, w / 2  , h)
                , left:     distanceMetric(x, y, 0      , h / 2)
                , right:    distanceMetric(x, y, w      , h / 2)
            }
            , edgeDistances = $.map(edgeDistance, function (value) {
                return [value]
            })

            return Object.keys(edgeDistance)[
                $.inArray(
                    Math.min.apply(null, edgeDistances)
                    , edgeDistances
                )
            ]
        }

        var current = $(this)
        , elementOffset = current.offset()

        return closestEdge(
            event.pageX - elementOffset.left
            , event.pageY - elementOffset.top
            , current.width()
            , current.height()
        )
    }
})

function log(message) {
    $('#console').append('<pre>' + message + '</pre>')
}
于 2016-08-30T17:23:25.947 に答える