Создаем подсказки в стиле WP-Coda

Владимир | | CSS, HTML, JavaScript, Web дизайн, Web разработка.

Думаю, все кто интересуется web дизайном видели тему для WordPress WP-Coda.

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

Эффект очень красивый и мне захотелось сделать всплывающие подсказки в таком же стиле.

Как оказалось – ничего сверх сложного 😉 .

Прежде всего, рассмотрим принцип работы эффекта.

При наведении указателя мышки на какой-то элемент страницы плавно появляется блок с текстом. При этом одновременно применяются два эффекта: перемещение и изменение прозрачности.

Если переместить мышку на другой элемент страницы – блок плавно исчезает.

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

Кроме того, подсказок может быть несколько, поэтому необходима возможность работы с ними одновременно. Причем одновременно две подсказки не должны быть видимы никогда.

В результате получилось два JavaScript класса. Плюс для их работы нужна библиотека jQuery.

Посмотреть демоверсию можно здесь. Я использовал такие подсказки для всех элементов горизонтального меню.

Первый класс (Popup) – создает подсказки и содержит методы для управления ими.

Второй (PopupContainer) – представляет собой контейнер для хранения экземпляров первого класса, и содержит только один метод addPopup. В качестве параметров он получает id элемента, которому принадлежит подсказка и id блока с самой подсказкой.

Теперь разберем порядок работы эффекта.

Как вы понимаете, переход подсказки из одного состояния в другое (видима/невидима) происходит при возникновении определенного события. В данном случае это mouseenter и mouseleave.

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

muoseenter diagram

Прежде всего, обратите внимание на переменные 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, а при возникновении mouseleavehide.

Принцип работы метода 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"));
});

Скачать

Если эффект вас заинтересовал – качайте архив с примером. В нем находятся все необходимые библиотеки и скрипты.

Все вопросы и замечания буду рад почитать в комментариях 😉