我正在尝试模拟悬停在图像上的效果,覆盖的半透明图像将从鼠标来自的方向淡入。当鼠标离开图像时(淡出+移开)
,反之亦然我为此准备了test page。继续检查,它将阐明所期望的效果。
我为此定义了一个HTML结构:
<div class="overlayLink">
<img src="assets/work/thumbnails/kreatude.jpg" alt="Kreatude" />
<div class="overlayLink_overlay_bg"> </div>
<div class="overlayLink_overlay_fg">
<span class="overlayLink_overlay_link"><a href="#">View Case Study</a></span>
<div class="top"> </div>
<div class="left"> </div>
<div class="right"> </div>
<div class="bottom"> </div>
</div>
</div>
以及以下JS(我正在使用jQuery):
jQuery(document).ready(function () {
ourWork();
});
function ourWork(){
var inHandler = function(){
var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');
var divClass = inClass;
blue_bg.stop(true,true).fadeIn();
var ml,mt;
if(divClass == 'left'){
ml = -260;
mt = 0;
}
else if(divClass == 'right'){
ml = 260;
mt = 0;
}
else if(divClass == 'top'){
ml = 0;
mt = -140;
}
else if(divClass == 'bottom'){
ml = 0;
mt = 140;
}
//positioning
jQuery(this).find('a').css({
'marginLeft': ml + 'px',
'marginTop' : mt + 'px'
});
//animation
jQuery(this).find('a').stop(true,true).animate({
"marginLeft": "0px",
"marginTop": "0px"
}, "slow");
}
var outHandler = function(){
var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');
var divClass = outClass;
blue_bg.stop(true,true).fadeOut();
var ml,mt;
if(divClass == 'left'){
ml = -260;
mt = 0;
}
else if(divClass == 'right'){
ml = 260;
mt = 0;
}
else if(divClass == 'top'){
ml = 0;
mt = -140;
}
else if(divClass == 'bottom'){
ml = 0;
mt = 140;
}
//animation
jQuery(this).find('a').stop(true,true).animate({
"marginLeft": ml + "px",
"marginTop": mt + "px"
}, "slow");
}
var inClass, outClass;
jQuery('.overlayLink_overlay_fg div').hover(function(){
inClass = jQuery(this).attr('class');
},function(){
outClass = jQuery(this).attr('class');
});
jQuery('.overlayLink').mouseenter(inHandler).mouseleave(outHandler);
}
解释
基本上我在图像顶部有四个绝对定位的div,当我将鼠标悬停在其中一个div(.overlayLink_overlay_fg div)上时,我知道方向(左,上,下,右)我把悬停的类名称变量中的div(var inClass和var outclass)
一旦我将鼠标悬停在覆盖图像区域的div上(.overlayLink),我从inClass或outClass变量请求方向并执行动画(inHandler,outHandler)
然而这一切似乎都有效,当你快速移动鼠标时会有点小问题,现在我问问题是什么(导致故障)以及如何修复用我现在的代码。
提前致谢
答案 0 :(得分:44)
也许你应该考虑不要将div用作“热点”,而是使用一些Math和Javascript来找到鼠标进入并离开div的点。这避免了重叠/间隙问题。 basicaly下面的代码将4个三角区域中的div分开。当鼠标移过它时,每个区域都会返回一个数字。代码需要一些微调,你必须自己决定绑定和取消绑定事件的位置。但我认为这会消除大部分闪烁问题。
$(".overlayLink").bind("mouseenter mouseleave",function(e){
/** the width and height of the current div **/
var w = $(this).width();
var h = $(this).height();
/** 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 - this.offset().left - (w/2)) * ( w > h ? (h/w) : 1 );
var y = (e.pageY - this.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:
/** animations from the TOP **/
break;
case 1:
/** animations from the RIGHT **/
break;
case 2:
/** animations from the BOTTOM **/
break;
case 3:
/** animations from the LEFT **/
break;
}});
当然,获得方向的简短符号应该是:
var direction = Math.round( Math.atan2(y, x) / 1.57079633 + 5 ) % 4
其中1.57 ...是Math.PI / 2这对我来说更难以解释,因为它会跳过度转换。
答案 1 :(得分:1)
从根本上说,鼠标移动事件发生的是一系列点而不是曲线,因为我们感知到屏幕上的移动。移动鼠标的速度越快,点之间的间距越大,鼠标可以移动的对象越大而不接触。因此,理想情况下,您需要知道在着陆到对象之前最后一个鼠标位置的方向,并从中计算出它接近的方向。即你需要不断跟踪整个页面上的鼠标位置,以确保每次都能正常工作。
答案 2 :(得分:0)
您可以尝试使用图像映射,将处理程序附加到定义的区域,而不是使用绝对定位的div来围绕图像。只需将边界区域定义得足够厚,即使它移动得相当快,也可以检测到鼠标移动。
答案 3 :(得分:0)
如果您从左向右快速滑动鼠标以使其穿过3个矩形
[ 1 ] [ 2 ] [ 3 ]
鼠标通过右边框div退出矩形#2后,立即通过左边框div输入矩形#3。但是,当矩形#3通过其左边界div输入时,赋值inClass =“left”outClass =“left”发生在矩形#2的outHandler被触发之前。
答案 4 :(得分:0)
如果我要实现此功能,请按照以下方式进行操作:
每个矩形都应该有自己的处理程序,因此两个重要的值 sideEntered 和 lastSideTouched 在其处理程序的范围内被封装。
答案 5 :(得分:0)
此代码(以及inClass&amp; outClass的使用)存在问题。您正在更改事件处理程序中使用的全局变量的状态。
var inClass, outClass;
jQuery('.overlayLink_overlay_fg div').hover(function(){
inClass = jQuery(this).attr('class');
},function(){
outClass = jQuery(this).attr('class');
});
此代码假定outClass是由“local”div设置的,但coulsd是由邻近的顶级div设置的
var outHandler = function(){
var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');
var divClass = outClass;
不要将此作为单个全局变量进行管理,尝试使用Isolated mannor进行管理。
这是一个评论: 我还没有测试过这段代码
jQuery('.overlayLink_overlay_fg div').hover(function() {
jQuery(this).parents('.overlayLink').attr('mouseEnterClass', jQuery(this).attr('class'));
}, function() {
jQuery(this).parents('.overlayLink').attr('mouseLeaveClass', jQuery(this).attr('class'));
});
在您的处理程序中,请参考这些新数据。
var outHandler = function() {
var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');
var divClass = jQuery(this).attr('mouseLeaveClass');
....
}
这个woulod解决了全局变量问题。我不确定如果'hover'事件在动画完成之前发生会发生什么。
编辑: 修复了代码问题。
答案 6 :(得分:0)
这是一个简单的解决方案,但是在mouseenter事件中边缘需要改进。
在鼠标进入事件中,我给了它5%(0%&0%)(100%&100%)的差异,只是为了快速移动光标来捕获光标,这是需要修复的错误。
const div = document.querySelector('div');
const mouseLeave = (e) => {
e.preventDefault();
e = e || window.event;
// get box properties
let a = e.target.getBoundingClientRect();
let w = a.width;
let h = a.height;
// get x,y
const x = e.pageX - a.left;
const y = e.pageY - a.top;
//* detect mouse out
if (x >= w) console.log('out-right');
if (x <= 0) console.log('out-left');
if (y >= h) console.log('out-bottom');
if (y <= 0) console.log('out-top');
}
const mouseEnter = (e) => {
e.preventDefault();
e = e || window.event;
// get box properties
let a = e.target.getBoundingClientRect();
let w = a.width;
let h = a.height;
// get x,y
const x = e.pageX - a.left;
const y = e.pageY - a.top;
// get positions by percentage
const X = (x / w) * 100;
const Y = (y / h) * 100;
//* detect mouse in
if ((X >= 0 && X <= 100) && (Y >= 0 && Y <= 5)) console.log('in-top');
if ((X >= 0 && X <= 100) && (Y >= 95 && Y <= 100)) console.log('in-bottom');
if ((Y >= 0 && Y <= 100) && (X >= 95 && X <= 100)) console.log('in-right');
if ((Y >= 0 && Y <= 100) && (X >= 0 && X <= 5)) console.log('in-left');
}
div.addEventListener('mouseleave', mouseLeave, true);
div.addEventListener('mouseenter', mouseEnter, true);
div {
width: 300px;
height: 300px;
outline: 1px solid blue;
margin: 50px auto;
}
<div></div>