2010-09-02 2 views
9

Я пытаюсь имитировать эффект, когда я нахожу изображение, наложенное полупрозрачное изображение будет исчезать с того направления, откуда появилась ваша мышь. И наоборот, когда ваша мышь покидает изображение (fadeout + удаляется)jQuery анимация для зависания с «направлением мыши»

Для этого я подготовил test page. Идите дальше и проверьте это, он разъяснит, каков желаемый эффект.

Я определил HTML структуру для этого:

<div class="overlayLink"> 
     <img src="assets/work/thumbnails/kreatude.jpg" alt="Kreatude" /> 
     <div class="overlayLink_overlay_bg">&nbsp;</div> 
     <div class="overlayLink_overlay_fg"> 
      <span class="overlayLink_overlay_link"><a href="#">View Case Study</a></span> 
      <div class="top">&nbsp;</div> 
      <div class="left">&nbsp;</div> 
      <div class="right">&nbsp;</div> 
      <div class="bottom">&nbsp;</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 на вершине изображения, чтобы знать направление (левое, верхнее, нижнее, правое), когда я наводил курсор на один из этих 4 div (.overlayLink_o verlay_fg div) Я поместил имя класса зависающего div в переменную (var inClass и var outclass)

Как только я накрою div, который покрывает область изображения (.overlayLink) Я запрашиваю направление от inClass или фора переменные и выполнять анимацию (inHandler, outHandler)

однако все это, кажется, работает, это немного Glitchy, когда вы перемещаете мышь очень быстро, теперь я спрашиваю, что проблема (это в результате чего глюки) и как это может быть исправлено с моим текущим кодом.

Заранее спасибо

+0

Theres много глюков на странице, которую вы указали выше - это ваше право? Если я спускаюсь с вершины, он работает. Затем налево он работает. Затем, если я спускаюсь с верха, он работает, но выходящий влево снова делает накладку вверх. Тогда, если я пойду слева, после этого наложение происходит сверху. Неважно, как быстро я это делаю. –

+0

Вы правы, не понимал, что это было так глючно. И да, это моя страница. Однако должна быть какая-то логическая причина, почему это происходит. Если я просмотрю свой код, я не вижу в нем логической ошибки, которая беспокоит меня совсем немного. – Ayrton

+0

Просто нет. Это нечестно для сенсорных пользователей. –

ответ

44

Возможно, вы считаете, что не использовать divs как «горячие точки», а использовать некоторую математику и Javascript, чтобы найти точку, в которую входит мышь и выходит из div. Это позволяет избежать проблем с перекрытием/пробелами. Код ниже basicaly делит div в 4 треугольных зонах. Каждая зона возвращает число, когда мышь перемещается над ним. Код нуждается в некоторой финализации, и вы должны сами решить, где привязать и развязать события. Но я думаю, что это уберет большинство ваших мерцающих проблем.

$(".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 Это намного больше efiicient немного сложнее для меня, чтобы объяснить, так как оно пропускает градусы преобразования.

+1

гений! большое спасибо. – David

+0

также, если собственный javascript this.offsetTop не сообщает правильно, используя $ (this) .offset(). Top работал. Я перемещаю тело на ось translateY, которая беспорядочна с правильными показаниями смещения. Просто фью. – Abbey

+1

Привет, Каспар, я понимаю концепцию вычисления x и y, чтобы получить угол к центру div, но я не знаю, зачем нужно '(w> h? (H/w): 1)' ? не могли бы вы помочь понять это? Я решил нормализовать его '(e.pageX - this.offsetLeft - (w/2))' этого достаточно – Sean

0

Вместо того, вокруг изображения с абсолютно позиционируемых дивами, вы можете попробовать сделать это с изображением карты, приложив обработчик в определенных областях. Просто определите границы, чтобы быть достаточно толстыми, чтобы движение мыши было обнаружено, даже если оно перемещается довольно быстро.

+0

это просто мысль или считается ли это хорошей практикой? – Ayrton

+0

Заметьте, что вы подразумеваете под «просто мыслью». Окружать ваши изображения абсолютно позиционируемыми divs - умный хак. В то время как карта изображения и изображение являются неотъемлемыми друг от друга и предлагают более чистый дизайн с лучшей инкапсуляцией и менее сложной компоновкой страницы. – Tim

+0

Кроме того, с помощью карты изображения вы можете более легко регулировать толщину невидимых «горячих» областей границы, тем лучше обнаруживать мышь, не затрагивая макет. – Tim

0

Если вы проводите мышь быстро слева направо, так что она пересекает 3 прямоугольник

 [ 1 ] [ 2 ] [ 3 ] 

мышь будет въезжающий прямоугольник # 3 через его левую границу деления с сразу после того, как он вышел из прямоугольника # 2 через его правая граница div. Однако присваивание inClass = "left" outClass = "left", когда прямоугольник # 3 вводится через его левую границу div, происходит до того, как вышел извне для прямоугольника # 2.

0

Если бы я собирался реализовать эту функцию, вот как я бы подойти к нему:

  1. Создание карты областей изображения, определяющие верхнюю, нижнюю, левую и правую границы для изображения.
  2. Для каждого изображения, в котором вы хотите этот интеллект (т.с какой стороны он входил, с какой стороны он отходил): a) отслеживать sideEntered - это значение присваивается один раз и только один раз; всякий раз, когда вводится граница области карты изображения, обработчик обработчика мыши справляется с sideEntered и назначает его только в том случае, если он еще не назначен; б) отслеживать lastSideTouched - всякий раз, когда область изображения карты вводится ее mouseoverhandler перераспределяет эту переменную с), когда мышь покидает прямоугольник, обработчик отпуска консультируется lastSideTouched и перезагружает sideEntered обнулить

Каждый прямоугольник должен иметь свои собственные обработчики так два важных значений, sideEntered и lastSideTouched, являются инкапсулированные в пределах своего обработчика.

+0

Смотрите мое объяснение ниже, почему быстрое движение вызывает ваши сбои. – Tim

0
  • Что проблема (что вызывает глюки)

Этот код (и использование inClass & фору) являются проблематичными. Вы изменяете состояние глобальных переменных, которые используются в обработчиках событий.

var inClass, outClass; 
jQuery('.overlayLink_overlay_fg div').hover(function(){   
    inClass = jQuery(this).attr('class'); 
},function(){   
    outClass = jQuery(this).attr('class'); 
}); 

Этот код предполагает, что фора была установлена ​​на «местном» DIV, но coulsd были установлены в соседней верхней DIV

var outHandler = function(){   
    var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');   
    var divClass = outClass; 
  • как [может] это может быть исправлено с моим текущий код?

Не управляйте этим как единой глобальной переменной, попробуйте управлять им с помощью изолированного маннора.

Вот один apprach: Я не проверял этот код

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

В обработчиках, refrence эти новые данные.

var outHandler = function() { 
     var blue_bg = jQuery(this).find('.overlayLink_overlay_bg'); 
     var divClass = jQuery(this).attr('mouseLeaveClass'); 
     .... 
     } 

Этот woulod адресует проблему глобальной переменной. Я не уверен, что произойдет, если событие «hover» произойдет до завершения анимации.

EDIT: Исправлены проблемы с кодом.

1

Принципиально события движения мыши происходят как последовательность точек не как изогнутая линия, поскольку мы воспринимаем движение на экране. Чем быстрее вы перемещаете мышь, тем больше расстояние между точками и тем больше объектов, которые мышь может перемещать, не касаясь друг друга. Поэтому в идеале вам нужно знать направление последней позиции мыши перед тем, как приземляться на свой объект, и из этого вычислить направление, с которого оно приблизилось. т. е. вам нужно постоянно отслеживать положение мыши на всей странице, чтобы быть уверенным, что ваш эффект будет работать правильно каждый раз.