Главная страница   /   10.1. Использование базовых эффектов (Pro jQuery

Pro jQuery

Pro jQuery

Адам Фриман

10.1. Использование базовых эффектов

Большинство базовых эффектов предназначены для того, чтобы показать или скрыть элементы. Методы, которые можно использовать для этих целей, описаны в таблице 10-2.

Таблица 10-2: Базовые методы для создания эффектов
Метод Описание
hide() Прячет все элементы в объекте jQuery
hide(time)
hide(time, easing)
Прячет элементы в объекте jQuery на определенный период времени, опционально можно указать скорость анимации
hide(time, function)
hide(time, easing, function)
Прячет элементы в объекте jQuery на определенный период времени, опционально можно указать скорость анимации и функцию, которая будет вызвана после завершения эффекта (анимации)
show() Показывает все элементы в объекте jQuery
show(time)
show(time, easing)
Показывает элементы в объекте jQuery на определенный период времени, опционально можно указать скорость анимации
show(time, function)
show(time, easing, function)
Показывает элементы в объекте jQuery на определенный период времени, опционально можно указать скорость анимации и функцию, которая будет вызвана после завершения эффекта
toggle() Меняет (переключает) видимость всех элементов в объекте jQuery
toggle(time)
toggle(time, easing)
Переключает видимость всех элементов в объекте jQuery на определенный период времени, опционально можно указать скорость анимации
toggle(time, function)
toggle(time, easing, function)
Переключает видимость всех элементов в объекте jQuery на определенный период времени, опционально можно указать скорость анимации и функцию, которая будет вызвана после завершения эффекта
toggle(boolean) Переключает видимость всех элементов в объекте jQuery в одну сторону

В листинге 10-1 показан самый простой из этих эффектов, при котором используются методы show и hide без аргументов.

Листинг 10-1: Использование методов show и hide без аргументов
<!DOCTYPE html>
<html>
<head>
	<title>Example</title>
	<script src="jquery-1.7.js" type="text/javascript"></script>
	<link rel="stylesheet" type="text/css" href="styles.css" />
	<script type="text/javascript">
		$(document).ready(function () {
			$("<button>Hide</button><button>Show</button>").appendTo("#buttonDiv")
				.click(function (e) {
					if ($(e.target).text() == "Hide") {
						$('#row1 div.dcell').hide();
					} else {
						$('#row1 div.dcell').show();
					}
					e.preventDefault();
			});
		});
	</script>
</head>
<body>
	<h1>Jacqui's Flower Shop</h1>
	<form method="post">
		<div id="oblock">
			<div class="dtable">
				<div id="row1" class="drow">
					<div class="dcell">
						<img src="astor.png" /><label for="astor">Astor:</label>
						<input name="astor" value="0" required />
					</div>
					<div class="dcell">
						<img src="daffodil.png" /><label for="daffodil">Daffodil:</label>
						<input name="daffodil" value="0" required />
					</div>
					<div class="dcell">
						<img src="rose.png" /><label for="rose">Rose:</label>
						<input name="rose" value="0" required />
					</div>
				</div>
				<div id="row2" class="drow">
					<div class="dcell">
						<img src="peony.png" /><label for="peony">Peony:</label>
						<input name="peony" value="0" required />
					</div>
					<div class="dcell">
						<img src="primula.png" /><label for="primula">Primula:</label>
						<input name="primula" value="0" required />
					</div>
					<div class="dcell">
						<img src="snowdrop.png" /><label for="snowdrop">Snowdrop:</label>
						<input name="snowdrop" value="0" required />
					</div>
				</div>
			</div>
		</div>
		<div id="buttonDiv">
			<button type="submit">Place Order</button></div>
	</form>
</body>
</html>

В скрипте этого примера я работаю с DOM, чтобы добавить два элемента button и функцию, которая должна быть вызвана, когда любой из них будет нажат. Эта функция использует метод text, чтобы понять, какой элемент button (кнопка) был нажат, и вызывает, соответственно, метод hide или show. В обоих случая я вызывают этот метод для объекта jQuery с селектором #row1 div.dcell, и это обозначает, что видимыми или невидимыми будут те div элементы класса dcell, которые являются потомками элемента с id равном row1. На рисунке 10-1 показано, что случится, если я кликну на кнопку Hide.

Рисунок 10-1: Скрытие элементов при помощи метода hide

Нажатие на кнопку Show вызовет метод show, и это восстановит спрятанные элементы, как показано на рисунке 10-2.

Рисунок 10-2: Показ элементов при помощи метода show

Сложно показать переходы, используя рисунки, но стоит отметить несколько моментов. Во-первых, переход мгновенный. Тут нет каких-то задержек или эффектов, элементы просто появляются и исчезают. Во-вторых, вызов метода hide для элементов, которые уже спрятаны, не приведет ни к какому результату; также как и вызов метода show для видимых элементов. И наконец, когда вы прячете или показываете элемент, вы также прячете или показываете всех его потомков.

Совет

Можно выбрать элементы, используя селекторы :visible и :hidden. Для информации о расширенных CSS селекторах в jQuery смотрите главу 5.

Переключение элементов

Можно поочередно прятать и показывать элементы, если использовать метод toggle. В листинге 10-2 представлен пример.

Листинг 10-2: Использование метода toggle для переключения видимости элементов
<script type="text/javascript">
	$(document).ready(function () {
		$("<button>Toggle</button>").appendTo("#buttonDiv")
			.click(function (e) {
				$('div.dcell:first-child').toggle();
				e.preventDefault();
			});
	});
</script>

В этом примере я добавляю в документ одну кнопку, и когда она нажимается, я использую метод toggle, чтобы изменить видимость элементов div.dcell, которые являются первыми дочерними элементами своих родителей. Результат можно увидеть на рисунке 10-3.

Рисунок 10-3: Переключение видимости элементов

Совет

Обратите внимание, что структура документа вокруг скрытых элементов разрушается. Если вы хотите скрыть элементы и оставить пустое пространство на экране, тогда вам нужно задать CSS свойству visibility значение hidden.

Переключение в одном направлении

Методу toggle можно передать аргумент boolean, чтобы ограничить переключение видимости элементов. Если в качестве аргумента задать true, тогда будут показаны только спрятанные элементы (видимые элементы не будут спрятаны). Если в качестве аргумента задать false, получится обратный результат. Видимые элементы будут спрятаны, а спрятанные так и не станут видимыми. В листинге 10-3 показано такое использование метода toggle. Я хочу отметить, что я никогда не считал эту возможность полезной, но я включил ее для полноты картины.

Листинг 10-3: Использование метода toggle в одном направлении
<script type="text/javascript">
	$(document).ready(function () {
		$("<button>Toggle</button>").appendTo("#buttonDiv")
			.click(function (e) {
				$('div.dcell:first-child').toggle(false);
				e.preventDefault();
			});
	});
</script>

Анимация видимости элементов

Можно создать анимацию процесса показа и скрытия элементов, если задать в методах show, hide или toggle промежуток времени. Процесс показа и скрытия элементов будет тогда выполнятся постепенно за указанный период времени. В таблице 10-3 показаны аргументы для указания промежутка времени, которые можно использовать.

Таблица 10-3: Аргументы для указания промежутка времени
Аргумент Описание
milliseconds Указывает длительность в миллисекундах
slow Сокращение, эквивалентное 600 миллисекундам
fast Сокращение, эквивалентное 200 миллисекундам

В листинге 10-4 показано, как можно создать анимацию показа и скрытия элементов.

Листинг 10-4: Анимация видимости элементов
<script type="text/javascript">
	$(document).ready(function () {
		$("<button>Toggle</button>").appendTo("#buttonDiv")
			.click(function (e) {
				$('img').toggle("fast", "linear");
				e.preventDefault();
			});
	});
</script>

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

Совет

Если вы указываете длительность в миллисекундах, убедитесь, что значение не заключено в кавычки. То есть, используйте $('img').toggle(500), а не $('img').toggle("500"). Если вы поставите кавычки, то ваше значение будет проигнорировано, а использовано будет внутреннее значение по умолчанию.

Также я добавил дополнительный аргумент, который определяет стиль анимации, известный также как эффект ослабления (easing style) или функция ослабления. Доступны две функции ослабления, swing и linear. Если создать анимацию при помощи стиля swing, тогда анимация начнется медленно, потом ее скорость возрастет, а потом ее скорость снова снизится, когда анимация подойдет к концу. Стиль linear прогрессирует в постоянном темпе на протяжении всей анимации. Если аргумент опущен, то используется swing.

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

Рисунок 10-4: Анимация скрытия элементов

Как вы видите, эффект анимации уменьшает размер рисунков в обоих измерениях и увеличивает прозрачность. К концу анимации элементы img становятся невидимыми. Рисунки исчезают плавно и элегантно, но так случается не всегда. На рисунке 10-5 показано, что случится, если вы кликните на кнопку Toggle снова, чтобы сделать элементы img видимыми.

Рисунок 10-5: Анимация показа элементов

Элементы img возрастают только по вертикали почти что до самого конца анимации, а затем резко распрямляются по горизонтали. Это неудачное взаимодействие между тем, как jQuery создает анимацию видимости, и табличной версткой CSS, которую я использую в своем документе. Это некритичная проблема. Можно использовать один из других стилей анимации, который создает анимацию только в одном измерении, но я хочу обратить ваше внимание на то, что анимации нужно тщательно тестировать.

Использование функции обратного вызова

В качестве аргументов методам show, hide и toggle можно добавить функцию, и эта функция будет вызвана, когда эти методы закончат выполнять их эффект. Это может полезно для обновления других элементов, чтобы отобразить изменения в статусе, как показано в листинге 10-5.

Совет

Если вы хотите выполнить несколько последовательных эффектов для одного элемента, вы можете использовать обычное создание цепочки методов jQuery. Для подробной информации смотрите раздел "Создание и управление очередью эффектов" далее в этой главе.

Листинг 10-5: Использование функции обратного вызова
<script type="text/javascript">
	$(document).ready(function () {
		var hiddenRow = "#row2";
		var visibleRow = "#row1";

		$(hiddenRow).hide();

		$("<button>Switch</button>").insertAfter("#buttonDiv button")
			.click(function (e) {
				hideVisibleElement();
				e.preventDefault();
			});

		function hideVisibleElement() {
			$(visibleRow).hide("fast", showHiddenElement);
		}

		function showHiddenElement() {
			$(hiddenRow).show("fast", switchRowVariables);
		}

		function switchRowVariables() {
			var temp = hiddenRow;
			hiddenRow = visibleRow;
			visibleRow = temp;
		}
	});
</script>

Чтобы сделать этот пример более понятным, я разбил выполнение эффекта по отдельным функциям. Для начала, я спрятал один из элементов div, который представляет строку в моей табличной CSS-верстке, и определил две переменные, которые я использую, чтобы отслеживать, какая строка видима, а какая нет. В документ я добавил элемент button, при нажатии которого я вызываю функцию hideVisibleElement, которая использует метод hide для создания анимации скрытия видимой строки:

$(visibleRow).hide("fast", showHiddenElement);

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

Совет

Функция обратного вызова не получает никаких аргументов, но переменная this указывает на DOM элемент с анимацией. Если создается анимация для нескольких элементов, тогда функция будет вызвана один раз для каждого из них.

Эта функция использует метод show для создания анимации показа элемента:

$(hiddenRow).show("fast", switchRowVariables);

Еще раз, я указал функцию, которая должна быть выполнена в конце эффекта. В данном случае это функция switchRowVariables, которая меняет переменные, отслеживающие видимость элементов; таким образом, в следующий раз, когда будет нажата кнопка, эффект будет выполнен для правых элементов. В результате этого после нажатия кнопки текущая строка заменяется спрятанной строкой при помощи быстрой анимации, чтобы переход не бросался в глаза пользователю. На рисунке 10-6 показан результат (но еще раз, реальный результат станет очевидным, если вы загрузите пример в браузер).

Рисунок 10-6: Использование функций обратного вызова для сцепления эффектов

Переход между строками сглаженный, и нет конфликта с табличной CSS-версткой, потому что вы работаете со строками, а не с ячейками таблицы. Обычно вам не нужно будет делать разбивку на отдельные функции, как это сделал я; поэтому в листинге 10-6 показан тот же самый пример, переписанный с использованием более сжатого набора встроенных функций.

Листинг 10-6: Использование встроенных функций обратного вызова
<script type="text/javascript">
	$(document).ready(function () {
		var hiddenRow = "#row2";
		var visibleRow = "#row1";
		$(hiddenRow).hide();
		$("<button>Switch</button>").insertAfter("#buttonDiv button")
			.click(function (e) {
				$(visibleRow).hide("fast", function () {
					$(hiddenRow).show("fast", function () {
						var temp = hiddenRow;
						hiddenRow = visibleRow;
						visibleRow = temp;
					});
				});
				e.preventDefault();
			});
	});
</script>

Использование цикличных эффектов

Можно использовать функции обратного вызова, чтобы создать эффекты, выполняемые в цикле. В листинге 10-7 представлен пример.

Листинг 10-7: Использование функций обратного вызова для создания цикличного эффекта
<script type="text/javascript">
	$(document).ready(function () {
		$("<button>Toggle</button>").insertAfter("#buttonDiv button")
			.click(function (e) {
				performEffect();
				e.preventDefault();
			});
		function performEffect() {
			$('h1').toggle("slow", performEffect)
		}
	});
</script>

В этом примере нажатие на кнопку ведет к выполнению функции performEffect. Эта функция использует метод toggle, чтобы менять в документе видимость элемента h1, и передает саму себя в качестве аргумента обратного вызова. В результате этого элемент h1 циклично становится то видимым, то спрятанным.

Совет

Требуется осторожность при использовании текущей функции в качестве функции обратного вызова. В конце концов, вы можете исчерпать стек вызовов JavaScript, и ваш скрипт перестанет работать. Самым простым решением этой проблемы является использование функции setTimeout, которая будет планировать обратный вызов целевой функции без накручивания ее вызовов, например, вот так: $('h1').toggle("slow", setTimeout( performEffect, 1)). В принципе, исчерпать стек вызовов довольно сложно; обычно это обозначает, что страницу с запущенной анимацией нужно оставить открытой на очень долгое время, но нельзя сбрасывать этот момент со счета.

Ответственное использование эффектов

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

Например, я бегун на длинные дистанции (не особо преуспел, но все же). У меня есть наручные часы для бегунов, которые собирают данные о частоте сердечных сокращений, скорости, расстоянии, сжигаемых калориях и еще около 100 видов данных. После пробежки я загружаю данные на сайт производителя, где они хранятся и анализируются.

И тут начинаются проблемы. Каждый раз, когда я кликаю мышкой по странице, нужное мне содержание проходит долгую череду эффектов. Я знаю, что браузер получил нужные мне данные, потому что я вижу, как они постепенно появляются, но проходит несколько секунд, прежде чем я могу их прочесть. Возможно, "несколько секунд" – это и недолго, но они суммируются, особенно когда я хочу просмотреть пять или десять разных видов данных.

Я уверен, что дизайнер этого приложения думал, что эффекты будут выглядеть красиво и от них пользователи будут получать удовольствие. Но это не так. Они так долго тянутся, что надоедают до скрежета зубов. У этого веб приложения есть несколько полезных инструментов для анализа данных, но я уже дошел до того предела, когда оно меня настолько раздражает, что я просто не могу его использовать, и мои данные так и остаются непроанализированными. Я мог бы стать победителем марафона, если бы не эти эффекты (ну еще, возможно, пиво и пицца, которые я стал употреблять с завидной частотой).

Если вы считаете, что я преувеличил (про эффекты... насчет пиццы поверьте мне на слово), тогда просто возьмите один из примеров этой главы и установите интервал на 2 секунды. И тогда вы почувствуете, как же долго ждать конца анимации.

Мой совет заключается в том, что все эффекты нужно использовать в минимальных количествах. Я стараюсь использовать их только тогда, когда делаю изменения в DOM, если в противном случае это внесет диссонанс (элементы вдруг исчезнут со страницы). Если я их использую, я устанавливаю короткий интервал, обычно 200 миллисекунд. Я никогда не использую бесконечные циклы. Это верный способ доставить пользователю лишнюю головную боль. Я настаиваю на том, чтобы вы тщательно обдумывали тот момент, как пользователи видят и принимают ваше приложение или сайт, и удаляли все, что мешает простоте выполнения поставленных задач. Вылощенные сайты хороши, но вылощенные сайты, удобные в использовании, великолепны.