Думаю, все кто интересуется 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")); });
Скачать
Если эффект вас заинтересовал – качайте архив с примером. В нем находятся все необходимые библиотеки и скрипты.
Все вопросы и замечания буду рад почитать в комментариях 😉