Думаю, все кто интересуется web дизайном видели тему для WordPress WP-Coda.
Меня прежде всего заинтересовал эффект со всплывающим блоком (появляется над первым пунктом в горизонтальном меню).
Эффект очень красивый и мне захотелось сделать всплывающие подсказки в таком же стиле.
Как оказалось – ничего сверх сложного 😉 .
Прежде всего, рассмотрим принцип работы эффекта.
При наведении указателя мышки на какой-то элемент страницы плавно появляется блок с текстом. При этом одновременно применяются два эффекта: перемещение и изменение прозрачности.
Если переместить мышку на другой элемент страницы – блок плавно исчезает.
В оригинальном варианте при наведении мышки на блок с текстом он остается видимым. Но, я решил, что для подсказок такое поведение не самое удачное, т.к. под ними могут оказаться нужные посетителю элементы страницы. Поэтому у меня блок исчезает, как только посетитель убирает мышку с элемента, для которого установлена подсказка.
Кроме того, подсказок может быть несколько, поэтому необходима возможность работы с ними одновременно. Причем одновременно две подсказки не должны быть видимы никогда.
В результате получилось два JavaScript класса. Плюс для их работы нужна библиотека jQuery.
Посмотреть демоверсию можно здесь. Я использовал такие подсказки для всех элементов горизонтального меню.
Первый класс (Popup) – создает подсказки и содержит методы для управления ими.
Второй (PopupContainer) – представляет собой контейнер для хранения экземпляров первого класса, и содержит только один метод addPopup. В качестве параметров он получает id элемента, которому принадлежит подсказка и id блока с самой подсказкой.
Теперь разберем порядок работы эффекта.
Как вы понимаете, переход подсказки из одного состояния в другое (видима/невидима) происходит при возникновении определенного события. В данном случае это mouseenter и mouseleave.
На следующей диаграмме я показал порядок работы эффекта при возникновении события mouseenter.

Прежде всего, обратите внимание на переменные visible и showBegin. В них мы сохраняем текущее состояние подсказки.
Если visible == true, то подсказка в данный момент показана.
showBegin == true означает, что в данный момент идет анимация.
Используя эти переменные, мы можем определить, когда нужно игнорировать событие mouseenter.
Представьте ситуацию. Посетитель навел мышку на элемент, начался показ анимации (изменяется прозрачность, и подсказка плавно смещается). В этот момент посетитель перемещает мышь. Что произойдет? Должна ли прерваться анимация?
Я решил сделать следующим образом. Анимация продолжается в любом случае, но если посетитель убирает мышку с элемента, то сразу же после ее завершения запускается обратный эффект. Т.е. в результате блок с подсказкой будет скрыт.
Для этого, используется переменная nextAction, в которой храниться название метода, который должен быть запущен после завершения анимации.
Таким образом, если посетитель уберет мышку с элемента после того как анимация завершилась, то метод hide спрячет подсказку. Если же анимация не завершилась, то метод hide просто установит значение переменной nextAction = 'hide'.
Перед завершением работы метод show проверит состояние nextAction и вызовет метод hide. Т.е. подсказка исчезнет.
Диаграмму работы при возникновении события mouseleave я не приводил, т.к. принцип работы такой же.
Теперь взгляните на исходный код класса Popup
function Popup(target, popup) {
var showBegin = false;
var visible = false;
var nextAction = 'none';
var target = target;
var popup = popup;
var curObj = this;
this.show = function() {
if (!visible && !showBegin) {
//сбрасываем предыдущее значение nextAction
nextAction = 'show';
showBegin = true;
//рассчитываем координаты всплывающей подсказки
var pWidth = popup.innerWidth();
var tHieght = target.innerHeight();
var tWidth = target.innerWidth();
var tOffset = target.offset();
var popupLeft = tWidth/2 + tOffset.left - pWidth/2;
var popupTop = tHieght/2 + tOffset.top;
//показываем подсказку
popup.removeClass("hide");
popup.css("top", popupTop);
popup.css("left", popupLeft);
popup.css("opacity", 0);
//запускаем анимацию (изменение прозрачности и положения)
popup.animate({
opacity: 1,
top: '+=' + 10 + 'px'
}, 1000, 'swing', function() {
//выполняется после завершения анимации
visible = true;
showBegin = false;
if (nextAction == 'hide') {
curObj.hide();
}
});
}
else {
//если подсказка уже показана или начата анимация
//сохраняем следующую операцию
nextAction = 'show';
return;
}
}
this.hide = function() {
if (!showBegin && visible) {
//сбрасываем предыдущее значение nextAction
nextAction = 'hide';
showBegin = true;
//убираем подсказку (изменяем прозрачность и смещаем)
popup.animate({
opacity: 0,
top: '-=' + 10 + 'px'
}, 1000, 'swing', function() {
//выполняется после завершения анимации
visible = false;
showBegin = false;
popup.addClass("hide");
if (nextAction == 'show') {
curObj.show();
}
});
}
else {
//если подсказка невидимая или идет анимация
//сохраняем следующую операцию и выходим
nextAction = 'hide';
return;
}
}
this.setEventHandlers = function() {
target.bind('mouseenter', this.show)
.bind('mouseleave', this.hide);
}
}
С помощью метода setEventHandlers мы устанавливаем обработчики событий. При возникновении mouseenter будет вызван метод show, а при возникновении mouseleave – hide.
Принцип работы метода show мы уже рассмотрели. Единственное, на что я хочу обратить ваше внимание – это способ размещения подсказки.
Нам нужно, поместить подсказку точно под элементом, к которому она относится.
Для этого мы определяем ширину подсказки, ширину и положение элемента и на основании этих данных вычисляем координаты левого верхнего угла подсказки.
Затем делаем подсказку видимой (убираем класс hide) и запускаем анимацию (функция animate). В данном случае мы плавно изменяем прозрачность, и смещаем подсказку вниз на 10 пикселов.
Примечание. Для определения положения и размеров блоков используется плагин jQuery Dimensions.
Теперь рассмотрим класс контейнера
function PopupContainer() {
var popups = [];
this.addPopup = function(target, popup) {
var newPopup = new Popup(target, popup);
newPopup.setEventHandlers();
popups.push(newPopup);
}
}
Как видите, он предельно прост. Единственный метод addPopup создает новый объект класса Popup и сразу же вызывает его метод setEventHandlers. Т.е. подсказка сразу же готова к работе.
Использование подсказки
1) Подключаем необходимые библиотеки и стили. Например:
<script src="js/jquery.js" type="text/javascript"></script> <script src="js/jquery.dimensions.js" type="text/javascript"></script> <script src="js/popups.js" type="text/javascript"></script> <script src="js/common.js" type="text/javascript"></script> <link href="css/styles.css" charset="UTF-8" rel="stylesheet" type="text/css" />
2) Создаем элемент, для которого будет вызвана подсказка.
<p><a id="targetblock" href="#">Наведите указатель мыши на этот текст чтобы увидеть подсказку</a></p>
3) Создаем подсказку
<div id="mypopup" class="hide popuptip"> <div class="tiptext"> Это всплывающая подсказка в стиле <strong>Coda</strong><br />Она появляется при наведении указателя мыши на ссылку. </div> <div id="tipfooter"></div> </div>
В принципе, разметка подсказки может быть практически любой. Но нужно выполнить два условия.
Во-первых, она должна быть абсолютно позиционирована.
Во-вторых, нужно иметь возможность ее спрятать. Обычно для этого используется правило display: none.
4) Оформление подсказки. Тут у вас полная свобода 😉 . Я использовал следующие правила.
.popuptip {
position: absolute;
z-index: 3000;
width: 160px;
}
.hide {
display: none;
}
.popuptip .tiptext {
background-image: url('../images/tooltip_back_transp.png');
padding: 20px 20px 5px 20px;
font-size: 0.8em;
}
#tipfooter {
background-image: url('../images/tooltip_back_transp.png');
height: 20px;
background-position: bottom left;
}
Обязательными являются только первые два (popuptip и hide).
Примечание. В качестве фона я использовал рисунок tooltip_back_transp.png и технику CSS спрайтов. Здесь на ней я останавливаться не буду, вы легко сможете найти подробные статьи на эту тему.
5) Создаем подсказку и «привязываем» ее к какому-нибудь элементу на странице.
$(document).ready(function() {
var pContainer = new PopupContainer();
pContainer.addPopup($("#targetblock"), $("#mypopup"));
});
Скачать
Если эффект вас заинтересовал – качайте архив с примером. В нем находятся все необходимые библиотеки и скрипты.
Все вопросы и замечания буду рад почитать в комментариях 😉


