ОК, если вы хотите убедиться, что переход без зависания к транзиту завершен до того, как вы переключитесь, вы можете сделать это следующим образом:
$(document).ready(function() {
$(document.body).on('mouseenter mouseleave', '.tile', function(event) {
var $this = $(this);
if (event.type == 'mouseenter') {
$this.data("hovering", true);
if (!$this.hasClass('hover')) {
$this.addClass('hover');
var timeout = setTimeout(function() {
$this.removeData("timer");
if (!$this.data("hovering")) {
$this.removeClass('hover');
}
}, 400);
$this.data("timer", timeout);
}
} else {
$this.data("hovering", false);
// if no timer running, then just remove the class now
// if a timer is running, then the timer firing will clear the hover
if (!$this.data("timer")) {
$this.removeClass('hover');
}
}
});
});
И вот рабочая демонстрация с полнымКомментарии к коду: http://jsfiddle.net/jfriend00/rhVcp/
Это довольно подробное объяснение того, как это работает:
- Во-первых, я переключился на
.on()
, поскольку .live()
устарел для всех версийjQuery.Вам следует заменить document.body
ближайшим предком статического объекта .tile
. - Объект содержит элемент
.data("hovering", true/false)
, который всегда сообщает нам, находится ли мышь над объектом или нет, независимо от.hover
состояние класса.Это необходимо, когда срабатывает таймер, поэтому мы знаем, какое истинное состояние необходимо установить в этой точке. - Когда происходит событие
mouseenter
, мы проверяем, существует ли класс hover
.,Если так, то делать нечего.Если класс hover
отсутствует, мы добавляем его.Так как он ранее не присутствовал, и мы просто добавили его, это будет началом перехода hover
. - Мы устанавливаем таймер для длины перехода и устанавливаем элемент
.data("timer", timeout)
для объекта, чтобы будущий код мог знать, что таймер уже запущен. - Если мы получим
mouseleave
до того, как этот таймер сработает, мы увидим, что .data("timer")
существует, и мы ничего не будем делать (что позволит завершить переход). - Когда таймер сработает, мы делаем
.removeData("timer")
, чтобы избавиться отэтот маркер и затем мы видим, что мы все еще зависаем или нет с .data("hovering")
.Если мы больше не зависаем (поскольку mouseleave
произошло во время работы таймера), мы делаем .removeClass("hover")
, чтобы перевести объект в нужное состояние.Если мы все еще зависли, мы ничего не делаем, потому что мы все еще зависли, поэтому объект уже находится в правильном состоянии.
В двух словах, когда мы запускаем зависание, мы устанавливаем наведениесостояние и запустить таймер.Пока этот таймер работает, мы не меняем состояние объекта.Когда таймер срабатывает, мы устанавливаем правильное состояние объекта (зависание или отсутствие зависания, в зависимости от того, где находится мышь).Это гарантирует, что состояние при наведении останется включенным, по крайней мере, на время перехода, и когда пройдет минимальное время (таким образом, переход выполнен), мы обновим состояние объекта.
очень осторожно, не используйте глобальные переменные, так что это может работать с несколькими .tile
объектами без какого-либо вмешательства между ними.
В важной точке проектирования вы никогда не сможете запустить более одного таймера, потому что таймер только когда-либоустанавливается, когда класс hover не существует, и мы просто добавляем его сейчас, и когда таймер работает, мы никогда не удаляем класс hover, пока таймер не будет завершен.Таким образом, нет пути к коду для установки другого таймера после его запуска.Это упрощает логику.Это также означает, что таймер запускается только с момента первого применения класса hover, что гарантирует, что мы применяем время только с классом hover с момента его первого применения.
Что касается производительности, переход CSSЯ собираюсь использовать любой процессор - это зависит от реализации браузера, и мы ничего не можем с этим поделать.Все, что мы можем сделать, чтобы минимизировать нагрузку на процессор, это убедиться, что мы делаем минимально возможное при каждом переходе мыши / выходе и избегаем манипуляций с DOM, когда это возможно, поскольку они обычно являются самыми медленными типами операций.Здесь мы добавляем класс hover
только тогда, когда он еще не существует, и удаляем его только тогда, когда время истекло, и мышь больше не находится над ним.Все остальное - просто .data()
операций, которые являются просто манипуляциями с хеш-таблицами javascript, которые должны выполняться довольно быстро.Это должно инициировать перекомпоновку браузера только в случае необходимости, что является лучшим, что мы можем сделать.
Производительность селектора здесь не должна быть проблемой.Это делегированная обработка событий, и единственный селектор, который проверяется в реальном времени (во время событий), это .tile
, и это очень простая проверка (просто проверьте, есть ли у event.target
этот класс - никаких других объектов не нужноОдна вещь, которая была бы важна для производительности, - это выбрать предка как можно ближе к '.tile' для делегированной привязки события, потому что это будет тратить меньше времени на создание события, прежде чем оно будет обработано, и вы не получите условиегде существует множество делегированных событий, связанных с одним и тем же объектом, что может быть медленным, и поэтому .live()
устарело.