有没有办法检测鼠标光标来自div的哪一侧?
目前我正在使用这种方法:
jQuery(this).bind('mousemove',function(e){
offset_pos_x = parseInt(e.offsetX);
offset_pos_y = parseInt(e.offsetY);
...
然后我查找鼠标进入div内的距离,方向。
问题是,这种方法有点儿麻烦,因为我需要所有4个边,而不仅仅是两个,所以我必须检查offsetX和offsetY。
如果我在div中移动鼠标,例如X:+ 15,Y:-3(以像素为单位)我知道鼠标是从左侧移动的,因为鼠标在x轴上移动了15px,但只有-3px在y轴。关于这个问题的错误是,当X和Y几乎相同并且我不知道鼠标是从左侧还是顶部时(例如)。
另外,根据我的另一个问题(jQuery: mouseenter/mousemove/mouseover not recognized with small div and fast mouse movement),由于浏览器/操作系统的限制,事件不会在div的第一个Pixel上触发。因此,我的“entered_at”坐标不准确 - 例如:
如果我在div(左起)内快速移动鼠标光标,则“entered_at”坐标位于x:17,y:76。现在如果我在停止鼠标后将鼠标移动到左边,例如x:6,y:76,起点和offsetX之间的差值为负,所以触发了“光标来自右边”功能...... / p>
是否有其他方法可以检测鼠标光标来自哪一侧?
问候, 帕特里克
答案 0 :(得分:9)
我不会使用偏移量,而是使用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);
}
答案 1 :(得分:8)
这是脚本的正确/工作示例,包括绝对定位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);
}
答案 2 :(得分:5)
牙买加国旗小提琴中最接近的边缘功能并不尽如人意,并且某些元素不准确。我们可以使用offsetX
和offsetY
来简化函数并消除distMetric
函数:
// 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";
}
}
E.g:
$('.btn').on('mouseenter',function(e){
var edge = closestEdge(e.offsetX, e.offsetY, $(this).width(), $(this).height());
});
答案 3 :(得分: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));
});
答案 4 :(得分:0)
这是一个插件
希望能帮到你。答案 5 :(得分:0)
我使用jQuery函数改进了@Patrick的解决方案,以获得更优雅,更健壮的自定义jQuery函数。
以下是jQuery getMouseSide jsFiddle:
$(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>')
}