Опубликован: 14.08.2003 | Уровень: для всех | Доступ: платный | ВУЗ: Российский государственный гуманитарный университет
Лекция 7:

Программируем графику

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >

Мультипликация

Естественным продолжением идеи замещения значения атрибута SRC в контейнере IMG является мультипликация, т.е. последовательное изменение значения этого атрибута во времени. Для реализации мультипликации используют метод setTimeout() объекта window (см. лекцию "Программируем свойства окна браузера" ).

Существует два способа запуска мультипликации: по окончании загрузки страницы ( onLoad ) и при действиях пользователя ( onClick, onChange и т.д.). Наиболее популярный - первый, а именно использование onLoad() и setTimeout().

Обработчик события onLoad

Событие Load наступает в момент окончания загрузки документа браузером. Обработчик данного события ( onLoad ) указывается в контейнере BODY:

<BODY onLoad="программа JavaScript">

Рассмотрим сначала пример, в котором при загрузке документа начинает выполняться бесконечный цикл изменения картинки:

<SCRIPT>
var i=0;
function movie()
{
 document.i.src='images/crou00'+i+'.gif';
 i++; if(i>4) i=0;
 setTimeout('movie();',500);
}
</SCRIPT>
<BODY onLoad="movie();">
<IMG NAME=i>
</BODY>
7.1. Бесконечная мультипликация

Можно реализовать и конечное число циклов мультипликации, скажем 5:

<SCRIPT>
var i=0,
    n=5; // число циклов
function movie()
{
 document.i.src='images/crou00'+i+'.gif';
 i++; if(i>4) { i=0; n--; }
 if(n>0) setTimeout('movie();',500);
}
</SCRIPT>
<BODY onLoad="movie();">
<IMG NAME=i>
</BODY>
7.2. Мультипликация с числом циклов n=5

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

  1. скрипт movie() получает управление от обработчика события onLoad ;
  2. заменяет картинку;
  3. порождает новый скрипт movie() и откладывает его исполнение на 500 миллисекунд;
  4. текущий скрипт movie() уничтожается JavaScript-интерпретатором.

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

Запуск и остановка мультипликации

Постоянная мультипликация может быть достигнута и другими средствами, например многокадровыми графическими файлами. Однако движение на странице - не всегда благо. Часто возникает желание реализовать запуск и остановить движения по требованию пользователя. Удовлетворим это желание, модифицировав пример с бесконечной мультипликацией:

<SCRIPT>
var i=0, flag=true;
function movie()
{
 if(flag)
 {
  document.i.src='images/crou00'+i+'.gif';
  i++; if(i>4) i=0;
 }
 setTimeout('movie();',500);
}
</SCRIPT>
<BODY onLoad="movie();">
<FORM>
<INPUT TYPE=button VALUE="Start/Stop" 
       onClick="flag = !flag;">
</FORM>
<IMG NAME=i>
</BODY>
7.3. Остановка/запуск мультипликации (поток генерируется постоянно)

Мы ввели булевский flag и меняем изображение на странице, только если он принимает значение true. Нажатие на кнопку меняет значение флага на его отрицание.

Обратите внимание: когда flag имеет значение false, мы просто обходим изменение картинки, но не прекращаем порождение потока. Если бы мы поместили setTimeout() внутрь конструкции if(), то после нажатия на кнопку поток перестал бы порождаться, и запустить мультипликацию заново стало бы нельзя. Однако постоянное генерирование потока - это некоторая растрата ресурсов (памяти, процессора). Нельзя ли сделать оптимальнее? Можно. Этот способ основан на применении метода clearTimeout():

<SCRIPT>
var i=0, flag=true, m=null;
function movie()
{
 if(flag)
 {
  document.i.src='images/crou00'+i+'.gif';
  i++; if(i>4) i=0;
 }
 m = setTimeout('movie();',500);
}
</SCRIPT>
<BODY onLoad="movie();">
<IMG NAME=i>
<FORM>
<INPUT TYPE=button VALUE="Start/Stop" 
  onClick="flag = !flag;
  if(flag) movie();
  else clearTimeout(m);">
</FORM>
</BODY>
7.4. Остановка/запуск мультипликации (поток приостанавливается)

Как видите, достаточно ввести идентификатор потока m и сохранять в нем ссылку на поток при вызове setTimeout(). Тогда в случае необходимости (при нажатии пользователем кнопки) мы можем отменить запланированное выполнение movie() (которое произошло бы через 500 миллисекунд), вызвав метод clearTimeout(m).

Оптимизация отображения

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

Из всех способов оптимизации отображения картинок мы остановимся только на нескольких:

  • оптимизация отображения при загрузке;
  • оптимизация отображения за счет предварительной загрузки;
  • оптимизация отображения за счет нарезки изображения.

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

Оптимизация при загрузке изображений

Практически в любом руководстве по разработке HTML-страниц отмечается, что при использовании контейнера IMG в теле HTML-страницы следует указывать атрибуты WIDTH и HEIGHT. Это продиктовано порядком загрузки компонентов страницы с сервера и алгоритмом работы HTML-парсера. Первым загружается текст разметки. После этого парсер разбирает текст и начинает загрузку дополнительных компонентов, в том числе графики. При этом загрузка картинок, в зависимости от типа HTTP-протокола, может идти последовательно или параллельно.

Также параллельно с загрузкой парсер продолжает свою работу. Если для картинок заданы параметры ширины и высоты, то можно отформатировать текст и отобразить его в окне браузера. До тех пор, пока эти параметры не определены, отображения текста не происходит. (В современных браузерах текст обычно отображается сразу, оставляя картинке "небольшое" место; по окончании загрузки картинки (или когда становятся известными ее размеры) страница переформатируется "на лету". - Прим.ред.)

Таким образом указание высоты и ширины картинки позволит отобразить документ раньше, чем картинки будут получены с сервера. Это дает пользователю возможность читать документ или задействовать его гипертекстовые ссылки до момента полной загрузки документа.

С точки зрения JavaScript, указание размеров картинки задает начальные параметры окна отображения графики внутри документа. Это позволяет воспользоваться маленьким прозрачным образом, для того, чтобы заменить его полноценной картинкой. Идея состоит в передаче маленького объекта для замещения его по требованию большим объектом.

Предварительная загрузка изображений

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

Реальный эффект можно почувствовать только при отключении кэширования страниц на стороне клиента (браузера). Кэширование часто используют для ускорения работы со страницами Web-узла. Как правило, загрузка первой страницы - это достаточно длительный процесс. Самое главное, чтобы пользователь в этот момент был готов немного подождать. Поэтому, кроме графики, необходимой только на первой странице, ему можно передать и графику, которая на ней не отображается. Но зато при переходе к другим страницам узла она будет отображаться без задержки на передачу с сервера.

Описанный выше прием неоднозначен. Его оправдывает только то, что если пользователь нетерпелив, то он вообще отключит передачу графики.

Нарезка изображений

Нарезка картинок применяется довольно часто. Она позволяет достигать эффекта частичного изменения отображаемой картинки. Чаще всего он применяется при создании меню.

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

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >
Валерий Банатин
Валерий Банатин

function f() { var i=5; k=7; } f(); alert(k);

В примере выдается результат k=7, однако, хоть переменная и не объявлена, она внутри функции, т.е. локальная и не должна быть видима, или вторая и последующие все-таки становятся глобальными?

Дамир Кантюков
Дамир Кантюков

Изучаю курс введение в JavaScript. 4 уроке есть код, где метод присвоен переменной, почему у меня не работает, браузер гугл:

<HTML><HEAD> <SCRIPT> wid = window.open('','','width=750,height=100,status=yes'); wid.document.open(); R = wid.document.write; R('<HTML><HEAD><SCRIPT>var t;<\/SCRIPT></HEAD>'); R('<BODY><H1>Новое окно</H1></BODY></HTML>'); wid.document.close(); </SCRIPT> </HEAD> <BODY> <A HREF="javascript: wid.t=window.prompt('Новое состояние:',''); wid.document.write(wid.t); wid.focus(); void(0);" >Изменим значение переменной t в новом окне</A> </BODY></HTML>

Иван Ротанов
Иван Ротанов
Россия, Реутов, Школа №2, 2011
Светлана Железнякова
Светлана Железнякова
Россия, г.Новокуйбышевск