В этом уроке мы
покажем вам различные способы общения Flash с
внешними источниками (получения и передачи
данных). Затем вы сможете воспользоваться
полученными знаниями при построении несложного
Flash-приложения, которое даст пользователям
возможность "голосовать" за фильм, причем
результаты голосования будут отображаться на
экране, и все полученные сообщения будут
сохраняться в журнале на вашем жестком диске.
Внимание!
Для работы этим уроком необходимы учебные
файлы, которые Вы можете загрузить
здесь.
Приложение-журнал (мы создадим его в этом
уроке) позволит добавлять новые записи,
просматривать предыдущие и сохранять их.
Источники
данных и форматы
Источник данных – это объект или место, из
которого Flash может загрузить внешние данные (то
есть данные, не запрограммированные
непосредственно внутри фильма). Например, Flash
может загружать данные из обычного текстового
файла – тогда этот файл будет считаться
источником данных. Обмен данными – это акт
получения данных из источника или пересылки
данных из Flash другому приложению. В этом
разделе вы узнаете о различных видах источников
данных, а также об объектах и методах Flash,
применяемых для взаимодействия с этими
источниками в процессе обмена данными.
Любые данные, которые вы собираетесь загружать
во Flash из внешнего источника, должны быть
определенным образом структурированы – иметь
определенный формат. Flash поддерживает
следующие форматы:
- Строка
URL. В этом формате данные представлены
в виде пар имязначение. Переменные и их
значения описываются текстовой строкой.
Например, текстовая строка
name=Jobe&website=http://www.electrotank.com&hairColor=brown
описывает три переменные (name,
website, hairColor) с
соответствующими им значениями (Jobe,
http://www.electrotank.com, brown).
После загрузки этой строки Flash
автоматически разделит ее на пары
имя-значение, и эти переменные можно будет
использовать так же, как переменные,
запрограммированные в фильме. Здесь, как
видите, знак равенства связывает имя
переменной с ее значением, а знак амперсанд
(&) указывает
конец описания одной переменной и начало
следующей. Число переменных, описываемых в
таком формате, неограниченно. Учтите, однако,
что в таком формате можно хранить лишь
простые переменные, для хранения данных в
виде массивов, объектов и т.п. такой формат
не годится.
- XML.
Этот популярный стандарт форматирования
позволяет хранить данные в структурированном
виде. Например:
<States>
<State>
<Name>North Carolina</Name>
<Capital>Raleigh</Capital>
</State>
<State>
<Name>Virginia</Name>
<Capital>Richmond</Capital>
</Sate>
</States>
После загрузки документа XML во Flash данные из
него извлекаются скриптом (который вы сами
должны написать).
Примечание Подробнее о формате XML смотри
Урок 12 – Применение XML во Flash.
- Общие
объекты. В этом уроке мы расскажем о них
подробнее; пока достаточно сказать, что
общие объекты в чем-то сродни
cookies: это
объекты (данные), которые хранятся локально,
на жестком диске пользователя. Что это
означает? Пользователь запустил и просмотрел
фильм (по сети либо в виде проектора). В
ходе воспроизведения фильма формируются и
сохраняются некие данные (имя пользователя,
последний посещенный им раздел и т.п.).
Впоследствии эти данные могут быть получены,
когда пользователь вновь запустит фильм на
том же компьютере. С помощью общих объектов
можно хранить не только переменные, но
данные любого типа – массивы, XML-объекты,
любые другие объекты. Сохранение данных
можно сделать "невидимым" для пользователя
либо предоставить ему возможность
самостоятельно инициировать этот процесс (с
помощью кнопки и т.п.). На одном компьютере
можно поместить несколько файлов с данными
общих объектов – каждый фильм обычно (хотя и
не обязательно) создает собственный файл.
Итак, вы познакомились с различными типами
форматов данных, поддерживаемых Flash. Теперь
рассмотрим источники, из которых Flash способен
загружать данные.
-
Текстовый файл. Flash может загружать
данные из текстовых файлов (*.txt),
содержащих данные в описанном выше формате
строки URL. Данные из текстовых файлов
загружаются с помощью методов
loadVariables()
или load()
объекта LoadVars.
В этом уроке мы с вами применим оба эти
метода. Создать такой источник данных можно
с помощью любого простейшего текстового
редактора, вроде Windows Notepad или Apple
SimpleText.
-
Серверные скрипты. Это скрипты,
размещаемые на страницах типа
ASP, CFM, CGI
или JSP и
выполняемые сервером. Эти страницы, будучи
невидимыми пользователю, генерируют
форматированные данные (в виде HTML, XML и
т.д.) и пересылают их по запросу. Например,
представьте себе страницу под названием
news.asp,
которая не имеет визуального содержания, а
содержит только выполняемый сервером скрипт.
При посещении пользователем этой страницы
скрипт динамически сформирует и передаст на
его браузер HTML-страницу, содержащую
последние новости (взятые, например, из базы
данных). Серверные скрипты могут возвращать
данные и в формате XML, и в виде URL-строки
– а это значит, что Flash, взаимодействуя со
страницей, содержащей такой скрипт, может
загружать данные, созданные динамически, "на
лету".
- Файлы
XML. Файлы XML – это обычные текстовые
файлы, содержащие данные в формате XML;
такие файлы обычно имеют расширение
*.xml.
- XML
socket. Сокет-серверы – это приложения,
выполняемые на сервере и обслуживающие
одновременно нескольких пользователей,
соединяя их друг с другом. Flash способен
передавать и получать информацию через сокет,
используя формат XML. О сокет-серверах и о
том, как строить приложения с их применением,
вы сможете узнать в Уроке 12.
- Общие
объекты. Как уже говорилось, общие
объекты применяются для создания файлов
данных, хранящихся на жестком диске
пользователя. Эти данные можно затем
получить и использовать в фильме (этому
посвящено последнее упражнение данного
урока).
Совет Во Flash встроена функция защиты,
запрещающая загрузку данных через домены.
Например, если фильм был загружен с
www.site1.com, то попытка загрузить данные с
www.site2.com не удастся.
Get и post
При
работе с серверными скриптами существует два
способа обмена данными между сервером и Flash:
посредством GET
или POST. Оба они
используются, как в обычных HTML-страницах, так
и во Flash, для передачи данных (переменных и их
значений), введенных в форму, на сервер для
обработки (специальные методы Flash для передачи
данных мы обсудим в следующих упражнениях).
При
посылке переменных с помощью
GET пары
имя/значение просто присоединяются к самой
адресной строке URL. Например, если я (автор
этой книги) желаю с помощью
GET послать свое
имя и адрес электронной почты скрипту,
расположенному на странице
register.asp, я
указываю URL так:
http://www.somedomain.com/register.asp?name=jobe&email=jobe@electrotank.com.
Знак вопроса говорит скрипту и серверу, что все
последующее есть описание переменных. Хотя
GET проще в
использовании, чем POST,
он годится не во всех ситуациях, поскольку
ограничен размером в 1024 символа.
Теперь посмотрим, как применяется
POST. При передаче
данных с помощью POST,
переменные и значения содержатся внутри
заголовка HTTP-запроса – то есть невидимы для
пользователя. POST
немного удобный способ передачи, поскольку не
ограничен числом символов.
Мы
вернемся к теме применения
GET и
POST в упражнении
к следующему разделу – "Применение объекта
LoadVars".
Совет Поскольку совместить
GET и
POST не всегда
легко, скрипты обычно пишутся так, что они
способны принимать либо
GET, либо POST,
но не то и другое
Применение
объекта loadVars
Объект LoadVars используется при работе с
данными в формате URL-строки. С помощью этого
объекта можно загружать данные из текстового
файла, а также осуществлять обмен (посылать и
загружать) данными с серверным скриптом.
Примечание Flash может загружать данные,
содержащиеся в текстовом файле, однако сохранить
данные в такой файл Flash не способен; для этого
следует использовать серверный скрипт.
Создать объект LoadVars во Flash легко.
Взгляните на этот пример:
container = new
LoadVars();
Этим создается новый объект класса
LoadVars с именем
container. Для
загрузки переменных с URL в объект LoadVars
применяется метод load():
container.load("http://www.myDomain.com/myFile.txt");
Совет В любой момент можно узнать общее
число байтов, которые необходимо загрузить, а
также число уже загруженных байтов – для этого
предназначены методы объекта
getBytesTotal() и
getBytesLoaded().
После того, как данные загружены в объект
LoadVars, для получения доступа к ним следует
указать имя объекта, и следом – имя переменной.
Предположим, мы загрузили в объект
LoadVars с именем
myData следующую
строку:
name=Jobe&age=25&wife=Kelly
Ссылки на эти переменные будут такими:
myData.name
myData.age
myData.wife
Например:
useAge = myData.age;
Здесь userAge
получит значение 25. Точно так же скрипт во
Flash может присвоить переменным, находящимся в
объекте LoadVars,
новые значения:
myData.age = 45;
Таким образом, значения переменных внутри
объекта LoadVars
можно задать не только путем загрузки из
внешнего источника, но также и прямым
присвоением с помощью скрипта в фильме.
Совет При загрузке переменных в объект
LoadVars Flash
перезаписывает все значения переменных, которые
уже существовали в этом объекте и добавляет
переменные, которых не было.
Если требуется переслать переменные из объекта
LoadVars для
обработки скрипту на сервере, применяется метод
send(). Синтаксис
следующий:
myLoadVarsObject.send("http://www.mydomain.com/process.cfm");
При использовании этого метода серверный скрипт
не посылает Flash никакого ответа – переменные
обрабатываются на сервере и там остаются.
Метод sendAndLoad()
позволяет отправить на сервер для обработки
содержимое объекта
LoadVars, и при этом загрузить "ответ"
сервера в другой объект
LoadVars:
myLoadVarsObject.sendAndLoad("http://www.mydomain.com/process.cfm",
receivingLoadVarsObject);
В
этом случае переменные из
myLoadVarsObject отсылаются на указанный
URL. Скрипт на сервере обрабатывает данные и
посылает результаты в
receivingLoadVarsObject. После этого
скрипты в фильме могут работать с данными,
присланными в последний объект. Если необходимо,
чтобы результаты обработки были загружены в тот
же самый объект LoadVars,
который послал данные на сервер, просто
воспользуйтесь методом
load().
C
помощью метода toString()
объекта LoadVars
можно создать форматированную URL-строку,
содержащую переменные/значения, содержащиеся в
объекте.
Объект LoadVars
имеет два свойства:
contentType и
loaded. Свойство
contentType (которое можно изменить перед
отсылкой переменных) просто дает тип содержания,
указанный в HTTP-заголовке загружаемого
документа. Свойство
loaded возвращает
true, если загрузка данных в объект
завершена, false –
если не завершена, и
undefined, если метод
load() для этого
объекта еще не вызывался.
Для объекта LoadVars
доступно только одно событие:
onLoad. Это
событие можно использовать, например, для вызова
функции, как только загрузка данных в объект
будет завершена. Данное событие наступает при
каждой загрузке данных в объект.
Для того, чтобы по завершении загрузки
переменных с определенного URL в объект
LoadVars, вызвать
функцию, следует:
- Описать
функцию.
- Создать
новый объект LoadVars
при помощи конструктора new
LoadVars().
- Указать
функцию, которую следует вызвать по
завершении загрузки.
- Вызвать
метод load()
объекта LoadVars.
Например:
function myFunction(){
trace("Данные загружены");
}
container = new LoadVars();
container.onLoad = myFunction;
container.load("http://www.somedomain.com/myFile.asp");
В
этом примере функция
myFunction() будет вызвана, как только
строка данных с указанного URL будет полностью
загружена в объект
LoadVars с именем
container.
Примечание Если вы знакомы с применением
метода loadVariables()
из Flash 5, вам следует знать, что, хотя этот
метод работает и во Flash MX, предпочтительнее
все же использовать объекты
LoadVars.
В
следующем упражнении мы с вами создадим
несложную систему голосования, применив при этом
объект LoadVars.
Этот обмениваться данными (отсылать и получать)
в формате URL-строки со страницей ASP. Эта
страница содержит серверный скрипт, умеющий
читать и записывать данные в базе данных
Microsoft Access. Скрипт интерпретирует данные,
посланные ASP-странице, и соответствующим
образом обновляет значения в базе данных. По
запросу объекта LoadVars
на загрузку данных с ASP-страницы, скрипт берет
данные из различных полей таблицы, формирует из
них URL-строку и отсылает ее объекту
LoadVars.
Страницу со скриптом (poll.asp)
и соответствующую базу данных (poll.mdb)
вы найдете на прилагающемся CD-ROM в папке
Lesson11. Для успешного выполнения упражнений
этого урока вы должны иметь доступ к серверу
Windows, чтобы серверный скрипт на ASP-странице
мог быть выполнен. До начала этого упражнения вы
должны выгрузить на сервер
poll.asp и
poll.mdb и
запомнить их расположение (адрес URL).
-
Откройте файл poll1.fla из папки
Lesson11/Assets.
Мы
уже создали все нужные слои, кадры, метки и
клипы, так что вам остается сосредоточиться на
программировании.
Если монтажный стол установлен на кадр 1, на
экране отображается надпись: "What was the best
movie of 2001?" ("Какой фильм был лучшим в 2001
году"). Под этим текстом оставлено свободное
пространство, а в нижней части – кнопка Submit
(Подтвердить). В пустое пространство мы поместим
четыре компонента
RadioButton. С их помощью пользователь
будет выбирать лучший, по его мнению, фильм 2001
года. После того, как он нажмет кнопку Submit,
фильм выполнит скрипт, который пошлет на сервер
данные (о том, какой из фильмов выбрал
пользователь) и переместит курсор
воспроизведения фильма на кадр 3, с меткой
waiting, и будет
ожидать ответа сервера. По получении ответа
(загрузке данных в объект
LoadVars) фильм перейдет к кадру с меткой
display. Этот кадр
будет содержать скрипт, интерпретирующий данные,
полученные с сервера. На основании этих данных
будет вычислено процентное соотношение голосов,
поданных за каждый из четырех фильмов. Это
соотношение будет затем отображено в текстовых
полях и графически, в виде диаграммы.
-
Установите курсор воспроизведения к кадру 1
и выделите кадр в слое Text and Buttons.
В
этот слой мы поместим четыре экземпляра
компонента RadioButton
(между вопросом и кнопкой Submit).
-
Откройте панель Компоненты (Components).
Найдите компонент RadioButton и перетащите
на сцену четыре его экземпляра. Расположите
их вертикальным столбцом под вопросом на
экране.
Итак, вы поместили на сцену четыре экземпляра
компонента Radio Button. Выделив один из них и
взглянув на инспектор Параметры (Property), вы
увидите список свойств данного компонента – все
их можно изменять. Первое свойство,
Label, – это
подпись, отображаемая рядом с кнопкой. Следующее
свойство, Initial State, имеет булево значение,
определяющее, должна ли эта опция быть
изначально включена (выбрана) или выключена.
Свойство Group Name
– имя группы таких компонентов, связанных между
собой. Четыре селективных кнопки, которые мы
добавили, будут составлять одну группу; значит,
все они должны иметь одно и то же значение
свойства Group Name
(мы используем для всех четырех стандартное
значение – radioGroup).
В каждый момент времени может быть включена
(выбрана) только одна селективная кнопка из
группы. Кроме того, каждой кнопке назначается
связанное значение (ее свойство
Data). Когда одна
из кнопок группы выбрана, значение ее свойства
Data становится
общим значением данных группы. Например, если
кнопка из группы выбрана, и ее свойство Data
равно 47, значение данных группы также
становится равным 47 (этот факт будет очень
важен для нашего проекта). После свойства
Data в инспекторе
Параметры мы видим свойство Label Placement. Оно
определяет, с какой стороны от кнопки должна
быть расположена подпись – слева или справа.
Наконец, свойство Change Handler позволяет
задать функцию, которая должна вызываться при
нажатии кнопки; оставьте это свойство пустым.
-
Выделите верхнюю из селективных кнопок и
измените его свойство Label на "A Beautiful
Mind". Также измените свойство Label для
остальных трех кнопок: соответственно, "Lord
of the Rings", "Harry Potter" и "American
Pie II".
Изменяя свойство Label в инспекторе Параметры,
вы увидите, что меняются подписи у экземпляров
компонентов на сцене.
Примечание Если этого не происходит,
выполните команду меню Управление > Включить
просмотр в реальном времени (Control > Enable
Live Preview).
-
Измените свойство Data для четырех
компонентов RadioButton – сверху вниз: 1, 2,
3 и 4.
Когда после опубликования фильма пользователь
выберет одну из наших селективных кнопок,
значение ее свойства Data
станет значением данных группы
radioGroup. Это
значение можно в любой момент получить, вызвав
метод getData()
компонента RadioButton.
Предположим, например, что выбрана кнопка со
значением свойства Data,
равным 3, и эта кнопка входит в состав группы с
именем radioGroup.
Тогда с помощью выражения
selectedValue =
radioGroup.getData();
переменной selectedValue
будет присвоено значение 3.
-
Откройте панель Действия, выделите кадр 1
слоя Actions и введите действие stop();.
Это действие предотвратит воспроизведение
следующих кадров фильма – до тех пор, пока фильм
не получит соответствующих инструкций.
-
По-прежнему при выделенном кадре 1, добавьте
следующую строку срипта:
pollURL =
"http://www.myDomain.com/poll.asp";
Этим будет создана переменная с именем
pollURL и
значением, представляющим расположение страницы
poll.asp, которую
вы должны были выгрузить на сервер перед началом
этого упражнения. Указанный здесь URL следует
заменить реальным адресом страницы
poll.asp на вашем
сервере.
-
Добавьте к скрипту следующую строку:
poll = new LoadVars();
Этим создается новый объект
LoadVars. C его
помощью мы сможем загружать данные из внешнего
источника и использовать их в фильме, применяя
описанные выше методы.
-
Добавьте в конец текущего скрипта описание
функции pollLoaded():
function pollLoaded()
{
_root.gotoAndStop("display");
}
Эта функция будет перемещать курсор
воспроизведения к кадру с меткой
display.
- Чтобы
связать только что описанную функцию с
событием onLoad объекта LoadVars poll,
добавьте следующую строку:
poll.onLoad =
pollLoaded;
Этот скрипт указывает, что как только в объект
LoadVars poll
будет загружен последний байт данных, следует
вызвать функцию
pullLoaded(). Таким образом, по окончании
загрузки данных монтажный стол будет перемещен к
кадру с меткой display.
Чуть позже мы добавим в этот кадр скрипт,
который будет использовать загруженные данные
для отображения результатов на диаграмме.
-
Добавьте к скрипту следующее описание
функции:
function
submitChoice() {
var choice = radioGroup.getData();
poll.load(pollURL + "?choice=" + choice);
_root.gotoAndStop("waiting");
}
Эта функция будет вызываться при нажатии кнопки
Submit, подтверждая сделанный пользователем
выбор лучшего фильма года.
Первая строка функции создает локальную
переменную choice.
Ей присваивается текущее значение данных группы
селективных кнопок radioGroup. Например, если
пользователь выбрал вторую кнопку, переменная
choice получит
значение 2.
Следующей строкой вызывается метод
load() объекта
LoadVars poll.
Выражение в скобках конструирует URL: берется
URL страницы poll.asp
(pollURL), к нему добавляется строка "?choice=",
и в конец – значение переменной
choice;
получившаяся в итоге строка используется для
обмена данными с сервером методом
GET. Если,
например, пользователь выбрал селективную кнопку
3, то аргумент метода
load() будет выглядеть так:
"http://www.mydomain.com/poll.asp?choice=3".
Напомним: все, что стоит здесь после
вопросительного знака – это переменные для
передачи серверу. В данном случае мы посылаем
странице poll.asp голос пользователя (choice=3).
В соответствии с этим голосом скрипт этой
страницы обновит значения в базе данных, чтобы
затем загрузить результат в объект
LoadVars poll. Эти
результаты мы используем на шаге 14.
Последняя строка в функции говорит, что фильм
должен перейти к кадру с меткой
waiting. Фильм
останется на этом кадре до тех пор, пока
результаты с сервера не будут загружены во
Flash. Как только это произойдет, будет вызвана
функция pollLoaded(),
переведя фильм к кадру с меткой
display.
-
Выделите кнопку Submit и введите в панели
Действия следующий скрипт:
on (release) {
submitChoice();
}
При нажатии этой кнопки выполняется функция
submitChoice(),
которую мы описали на предыдущем шаге.
-
Переместите курсор воспроизведения к кадру с
меткой display.
В
этом кадре вы видите на сцене четыре
горизонтальные планки – по одной на каждый
фильм. Эти планки – экземпляры одного и того же
фильма-символа; имена экземпляров –
barGraph1, barGraph2,
barGraph3 и
barGraph4. Обратите внимание, что имена
различаются лишь цифрами в конце – мы
воспользуемся этим при отображении результатов
голосования. Каждый из этих экземпляров включает
в себя два текстовых поля:
topPercent и
bottomPercent – в
них будет отображаться процент голосов, только в
текстовом виде. Оба текстовых поля будут
отображать один и тот же текст, поле
bottomPercent служит просто для создания
эффекта тени позади
topPercent. Также фильм-символ содержит
горизонтальную планку – клип с именем
bar. Она будет
отображать (при помощи масштабирования) процент
голосов графически.
-
Выделите кадр в слое Actions и присоедините
такой цикл:
for (i=1; i<=4; ++i) {
var graphName = "barGraph" + i;
var votes = poll["item" + i + "total"];
var totalVotes = poll.totalVotes;
var percent = Math.round((votes/totalVotes) * 100);
_root[graphName].bar._xscale = percent;
}
Если курсор воспроизведения переместится к этому
кадру (метка display),
значит, пользователь сделал свой выбор и
подтвердил его, сервер принял данные, добавил их
в базу данных и загрузил результаты в объект
LoadVars poll. Как
вы помните, на шагах 9 и 10 мы запрограммировали
наш фильм таким образом, что он перейдет к этому
кадру лишь после того, как данные с сервера
будут полностью загружены в объект
poll. Скрипт в
этом кадре использует эти данные. Переменные,
загружаемые удаленным (серверным) скриптом в
объект LoadVars,
называются totalVotes,
item1total, item2total, item3total и
item4total.
Переменная totalVotes,
естественно, имеет числовое значение,
представляющее общее число голосований (вскоре
мы воспользуемся им для расчета процентных
значений). Прочие переменные содержат количество
голосов, полученных каждым фильмом. Поскольку
все эти переменные загружены в объект
LoadVars poll,
обращаться к ним мы должны следующим образом:
poll.totalVotes
poll.item1total
poll.item2total
poll.item3total
poll.item4total
Цикл в последнем нашем скрипте вычисляет процент
голосов, полученных каждым фильмом, и, в
соответствии с полученным значением,
масштабирует горизонтальную планку
соответствующего фильма-символа. Первая строка
тела цикла объявляет локальную переменную
graphName. Ее
значение есть конкатенация строки "barGraph" и
текущего значения i,
что дает в результате имя экземпляра
фильма-символа, над которым будет вестись работа
на данной итерации цикла (barGraph1,
barGraph2 и т.д.). Таким же способом, с
помощью значения i,
в следующем действии цикла формируется ссылка на
переменную, содержащую число голосов, полученных
текущим фильмом (poll.item1total,
poll.item2total и т.д.). Ее значение
присваивается переменной
votes. Затем переменной
totalVotes
присваивается значение общего числа голосований.
После этого вычисляется значение переменной
percent: число
голосов за текущий фильм делится на общее число
голосов и умножается на 100, после чего
результат округляется при помощи метода
Math.round()
объекта Math. На
конец, клип bar в
текущем фильме-символе (на него указывает
текущее значение
graphName) масштабируется в соответствии
со значением percent.
Действия в теле цикла повторяются четыре раза,
масштабируя все четыре планки диаграммы.
Примечание Подробнее о циклах см. в Уроке
10 – Автоматизация скриптов с помощью циклов.
- В тело
цикла, в самый конец, добавьте еще две
строки ActionScript:
_root[graphname].topPercent.text = percent +
"%";
_root[graphname].bottomPercent.text =
percent + "%";
Текст, отображаемый в полях
topPercent и
bottomPercent,
поверх масштабированного экземпляра клипа
bar, формируется
из значения переменной percent и присоединенного
к нему знака "%".
-
Выполните команду Управление > Проверить
фильм (Control > Test Movie), чтобы
проверить свою работу. Выберите одну из
селективных кнопок и нажмите кнопку Submit.
После нажатия кнопки Submit ваш выбор будет
сообщен странице poll.asp, которая обновит базу
данных и вернет результат в объект
LoadVars poll.
Фильм перейдет к кадру с меткой
display и покажет
вам результаты голосования!
-
Закройте тестовый фильм и сохраните свою
работу как poll2.fla.
Итак, мы только что завершили простое
приложение, использующее объект LoadVars для
общения с внешним скриптом. Полученные знания вы
сможете применить для создания более сложных и
полезных приложений.
Применение
общих объектов
Файл SWF способен сохранять данные (как
переменные, так и массивы, XML и другие объекты
данных) на жесткий диск пользователя посредством
общих объектов: возможность, схожая с
cookies,
используемыми веб-браузерами, но более мощная.
Общие объекты могут хранить информацию,
генерируемую пользователем при просмотре фильма
(имя, последний посещенный кадр, музыкальные
установки и многое другое). Общие объекты могут
использоваться как фильмами, проигрываемыми в
браузере, так и теми, которые опубликованы как
самостоятельные проекторы.
Примечание Общие объекты также можно
использовать при посредстве Flash Application
Services от Macromedia (подробности о Flash
Application Services вы найдете на
macromedia.com).
Вот пример скрипта, создающего общий объект:
myObject =
SharedObject.getLocal("stuff_I_saved");
Если общий объект "stuff_I_saved" существует на
жестком диске пользователя, данные из него будут
загружены в myObject. Если "stuff_I_saved" не
существует, он будет создан – по-прежнему со
ссылкой на myObject.
В последнем случае
myObject может быть пустым, не содержащим
никаких данных.
Примечание Еще раз поясним, что один и
тот же метод – getLocal()
– и создает общий объект (если он не
существует), и получает данные из существующего
общего объекта.
Как вы видите в примере, настоящее имя общего
объекта – "stuff_I_saved". Однако в ActionScript
прямо обратиться к нему по этому имени нельзя;
ссылка на этот общий объект создается при помощи
myObject. Это
значит, что в скриптах все обращения к
myObject на самом
деле будут обращениями к общему объекту с именем
"stuff_I_saved" – концепция немного мудреная, но
понять ее важно для работы с общими объектами в
ActionScript.
Данные в общий объект помещаются посредством
использования свойства data. Например:
myObject.data.userName
= userName.text;
Эта строка сохраняет переменную
userName (и ее
значение – текст из поля
userName) в общем объекте. Так можно
сохранять не только переменные, но и целые
объекты. Например, если нужно сохранить
имеющийся в проекте массив, используется тот же
синтакис:
myObject.data.savedArray = nameOfArray;
Единственный общий объект может хранить
одновременно несколько элементов данных:
myObject.data.savedArray = nameOfArray;
myObject.data.savedXML = nameOfXMLObject;
myObject.data.userName = userName.text;
Удалить из общего объекта имеющийся элемент
данных можно при помощи
null, как в этом примере:
myObject.data.userName
= null;
Этот скрипт "сотрет" элемент userName из общего
объекта.
Извлечь данные из общего объекта так же просто,
как сохранить:
userName.text =
myObject.data.userName;
Этот скрипт отобразит в текстовом поле
userName значение
переменной userName
из общего объекта. Если в общем объекте такая
переменная не существует, в текстовом поле будет
отображено "undefined".
По
завершении сеанса SWF (то есть, когда фильм
закончится или будет закрыт пользователем) вся
информация свойства data
общего объекта автоматически записывается в файл
общего объекта, и может быть получена с помощью
метода getLocal(),
как мы описывали. Можно и специально сохранить
общий объект (записать в файл), применив метод
flush(). Например:
myObject.flush();
Эта строка скрипта вызывает сохранение общего
объекта и всех данных, которые он содержит.
Поскольку myObject
есть ссылка на общий объект "stuff_I_saved", под
этим последним именем и будет сохранен общий
объект.
Flash помещает все общие объекты в одно общее
"хранилище"; при этом точное расположение
каждого общего объекта зависит от того, где
находится фильм, создавший этот объект.
В
Windows все общие объекты помещаются в следующий
каталог:
Windows\Application
Data\Macromedia\Flash Player\
На
Macintosh:
System
Folder\Preferences\Macromedia\Flash Player\
Это – общие, основные каталоги, общие объекты,
создаваемые фильмами, помещается в
соответствующие подкаталоги основного каталога.
Предположим, что фильм был запущен с такого URL:
http://www.electrotank.com/fun/games/MiniGolf.swf
Все общие объекты, созданные этим фильмом, на
машине под Windows будут, по умолчанию,
сохранены в каталог:
Windows\Application
Data\Macromedia\Flash
Player\electrotank.com\fun\games\MiniGolf
Обратите внимание – структура создаваемых
подкаталогов соответствует URL.
Фильмы, запускаемые локально (как проекторы) не
имеют URL, и потому Flash сохраняет создаваемые
ими общие объекты в подкаталоге
localhost:
Windows\Application
Data\Macromedia\Flash Player\localhost
Все указанные здесь пути и каталоги используются
для сохранения общих объектов по умолчанию. Вы
обладаете полной свободой при размещении и
загрузке общих объектов – но в пределах
основного каталога. Как в предыдущем примере,
предположим, что воспроизведенный фильм
находится по URL
http://www.electrotank.com/fun/games/MiniGolf.swf
В
этом фильме имеется следующий общий объект:
myScores =
SharedObject.getLocal("scoreData");
При сохранении этого общего объекта путь к нему
(под Windows) будет таким:
Windows\Application
Data\Macromedia\Flash
Player\electrotank.com\fun\games\MiniGolf\scoreData.sol
Когда этот фильм будет вновь запущен с того же
URL, Flash будет искать общий объект именно в
этом месте. Однако метод
getLocal() позволяет дополнительно
указать путь, по которому следует сохранять и
впоследствии искать общий объект. Предположим,
что в том же фильме общий объект объявлен таким
образом:
myScores =
SharedObject.getLocal("scoreData", "/fun");
В
этом случае путь к общему объекту будет
следующим:
Windows\Application
Data\Macromedia\Flash
Player\electrotank.com\fun\scoreData.sol
Зная это, вы можете создавать фильмы, которые
расположены в разных местах, но при этом
используют один и тот же общий объект – очень
полезная возможность, если вы хотите, например,
чтобы все фильмы вашего сайта использовали один
общий объект, содержащий, скажем, информацию о
пользователе. Просто сохраните этот общий объект
в основной каталог ("/").
Примечание Будьте внимательны,
сопоставляя один общий объект нескольким при
этом фильмам: существует возможность того, что
данные, содержащиеся в общем объекте, будут
перезаписаны, заменены новыми.
Один фильм может одновременно работать –
создавать, сохранять и загружать – с несколькими
общими объектами.
Совет Можно ограничить количество данных,
которые данный URL имеет право поместить на ваш
жесткий диск посредством Flash Player. Щелкнув
правой кнопкой мыши в окне открытого SWF и
выбрав в меню Settings, перейдите в открывшемся
окне настроек на вкладку Local Storage. Здесь
можно для любого сайта ограничить или вообще
запретить сохранение информации на вашем жестком
диске.
Примечание На прилагаемом к книге CD-ROM,
в папке этого урока, имеется бонусный файл –
highscorelist.fla. Файл может показаться вам
довольно сложным, однако он весьма удобен для
локального хранения набранных очков в игре,
причем на одном компьютере может быть несколько
пользователей – для каждого из них ведется
отдельный счет. Для управления списком можно
использовать объект
highScoreList, описанный в этом файле.
Среди прочего, здесь можно отсортировать список
по возрастанию или убыванию, удалить список,
начать новый, исправить сущестующий счет в
списке и добавить новый.
В
этом упражнении мы создадим журнал, сохраняющий
текстовые записи в виде массива в общем объекте.
-
Откройте файл journal1.fla из папки
Lesson11/Assets на CD-ROM.
Как видите, здесь лишь один кадр и четыре слоя,
которые называются в соответствии с их
содержимым. На сцене имеется два текстовых поля
для отображения информации. Большое поле в
центре, journalBody,
будет содержать саму запись. Меньшее поле в
нижней части экрана,
entryNumber, будет отображать номер
текущей записи по журналу. Слой Buttons содержит
кнопки навигации – Prev, Next, New и Save.
Это приложение будет позволять вводить новую
запись, сохранять ее, просматривать уже
имеющиеся записи.
- Открыв
панель Действия, выделите кадр 1 слоя
Actions и ведите такой скрипт:
myJournal =
SharedObject.getLocal("JournalObject");
Эта строка создает ссылку на общий объект
JournalObject.
Теперь во всех скриптах этого фильма, обращаясь
к myJournal, мы
будем на самом деле иметь дело с общим объектом
под названием
JournalObject.
-
Добавьте в скрипт, после предыдущей строки,
условный оператор:
if
(myJournal.data.journal == undefined) {
myJournal.data.journal = [];
}
Этот оператор проверяет, имеется ли в общем
объекте массив с именем
journal. Если такого массива нет (undefined),
выполняется действие, создающее его.
Примечание Как только массив создан, он,
после выхода из фильма или сохранения общего
объекта, автоматически становится частью общего
объекта.
Массив journal
будет иметь значение
undefined лишь при самом первом
воспроизведении фильма. При последующих запусках
фильма массив уже будет существовать, и это
действие будет игнорироваться.
Совет Хорошая идея – проверять данные в
общем объекте на значение
undefined. Это позволит присвоить им
начальные стандартные значения, если фильм
воспроизводится пользователем впервые.
- В
конец скрипта поместите описание функции:
function
displayEntry(num) {
_root.entryNumber.text = num;
_root.journalBody.text = myJournal.data.journal[num - 1];
}
Эта функция устанавливает значения двух
текстовых полей –
entryNumber и
journalBody – на основе значения
num. Например,
если при вызове функции
num имеет значение 1, в текстовом поле
entryNumber
отобразится "1" (номер текущей записи журнала).
Во второй строке значение
num используется для определения элемента
массива journal
(из общего объекта), который должен быть
отображен в текстовом поле
journalBody. Если
num имеет значение 1, то эта строка скрипта
расшифруется так:
_root.journalBody.text =
myJournal.data.journal[1 - 1];
или
_root.journalBody.text =
myJournal.data.journal[0];
Почему здесь из num вычитается единица? Дело в
том, что первая запись журнала ("1" в поле
entryNumber) – это
нулевой элемент массива
journal. Конечно, можно было бы показать
для первой записи номер "0", но это было бы
как-то не совсем привычно. Поэтому запомните
этот принцип сопоставления номеров записей и
индексов элементов массива (запись с номером "3"
– это элемент массива с индексом 2, и так
далее).
- В
конец текущего скрипта добавьте вызов
функции:
displayEntry(myJournal.data.journal.length);
Этот вызов функции находится в кадре 1, и
значит, будет выполнен, как только начнется
воспроизведение фильма. Вызывается функция
displayEntry()
(которую мы описали на предыдущем шаге) с
передачей ей в качестве параметра значения
свойства length
массива journal из
общего объекта. В результате на экране будет
отображена последняя запись, сделанная
пользователем в предыдущем сеансе фильма. Если,
к примеру, в массиве
journal имеется три записи, функции
displayEntry()
будет передано значение 3, и на экране будет
показана третья запись журнала. Если же массив
journal создан
только что (как описано а шаге 3), он будет
содержать единственную, пустую, запись – длина
массива будет равна 1, и это значение станет
аргументом функции.
-
Добавьте к скрипту следующее описание
функции, сохраняющей данные:
function save() {
var num = Number(_root.entryNumber.text) - 1;
myJournal.data.journal[num] = _root.journalBody.text;
myJournal.data.flush();
}
Мы
уже упоминали, что при выходе из фильма данные
сохраняются в общий объект автоматически. А с
помощью метода flush()
можно сохранить данные в любое время в ходе
воспроизведения фильма. Эта функция будет у нас
вызываться при нажатии кнопки Save (см. шаг 11).
Давайте разберемся, как она работает.
Первая строка функции создает локальную
переменную num.
Значение этой переменной определяется так:
значение, отображенное в текстовом поле
entryNumber, минус
один. Для уверенности в том, что num получит
числовое, а не текстовое, значение, использована
функция Number().
Значение num используется в следующей строке – в
качестве индекса элемента массива,
соответствующего текущей записи журнала. Как мы
упоминали на шаге 4, число, отображенное в поле
entryNumber (номер
записи), на единицу больше, чем индекс
соответствующего элемента массива; поэтому и
вычитается единица в первой строке.
Итак, вторая строка тела функции помещает в
элемент с индексом num массива
journal текст,
отображенный в поле
journalBody. Как всегда, возьмем для
иллюстрации пример. Допустим, что номер текущей
записи (показанный в поле
entryNumber) – 9. При вызове данной
функции num получит значение 8 (девять минус
один). Вторая строка тогда получится такой:
myJournal.data.journal[8] = _root.journalBody.text;
Тем самым текст из поля
journalBody будет записан в элемент с
индексом 8 массива
journal. Еще раз повторим, что текущий
номер записи – 9, а индекс соответствующего
элемента массива – 8. Рассматриваемая строка
скрипта Таким образом, если 8-й элемент массива
был до этого пустым (undefined),
в него будет записан текст; если этот элемент
уже содержал текст, этот текст будет перезаписан
(измененным или тем же самым текстом).
Последнее действие в функции с помощью метода
flush()
принудительно сохраняет на жестком диске
пользователя общий объект вместе с данными – в
нашем случае это все записи, имеющиеся в массиве
journal.
-
Добавьте описание функции, создающей новую
запись журнала:
function newEntry() {
_root.entryNumber.text = myJournal.data.journal.length + 1;
_root.journalBody.text = undefined;
Selection.setFocus("_root.journalBody");
}
Первое действие в этой функции устанавливает
номер текущей записи журнала (текст в поле
entryNumber) –
длина массива journal
плюс один. Так, например, если в массиве
journal две
записи, он имеет длину 2. В результате
добавления единицы в текстовом поле entryNumber
будет отображено "3". Таким образом, все новые
записи будут добавляться в конец массива. Два
последних действия этой функции очищают
текстовое поле
journalBody и устанавливают в него фокус,
так что пользователь может сразу начать вводить
свою новую запись. Чтобы все стало понятнее,
давайте рассмотрим работу данной функции во
взаимодействии с функцией
save(), которую мы создали на предыдущем
шаге.
Предположим, в массиве
journal имеется две записи. Эти записи
хранятся в элементах массива с индексами 0 и 1,
длина массива (length)
равна 2. При выполнении данной функции в
текстовом поле
entryNumber отобразится "3" (свойство
length массива
journal плюс
один), текстовое поле
journalBody пусто. Теперь пользователь
вводит в это поле текст и нажимает кнопку Save –
происходит вызова функции save(). Эта функция
вычитает единицу из числа, отображенного в поле
entryNumber, и в
итоге помещает текст из поля
journalBody в
элемент с индексом 2 массива
journal. Теперь
массив содержит три записи – в элементах с
индексами 0, 1 и 2, и его длина (length)
равна 3. Если теперь вновь вызвать функцию
newEntry(),
процесс повторится.
-
Добавьте описание новой функции, которая
будет выводить на экран следующую запись
журнала:
function nextEntry ()
{
var num = Number(_root.entryNumber.text) + 1;
if (num > myJournal.data.journal.length) {
num = myJournal.data.journal.length;
}
displayEntry(num);
}
Эта функция отображает на экране следующую
запись из имеющихся в массиве. Первым делом
присваивается значение переменной
num – число,
отображенное в поле
entryNumber плюс один. Далее, чтобы не
случилось попытки отображения несуществующей
записи, значение num сравнивается с общим числом
записей, имеющихся в массиве
journal (свойство
length массива).
Если значение num
оказалось больше, выполняется действие в
операторе if,
присваивающее переменной
num значение свойства
length массива
journal – это
приведет к тому, что на экране будет отображена
последняя запись из массива. Последнее действие
– вызов функции
displayEntry() с передачей ей значения
num. В результате
на экран будет выведена нужная запись (следующая
либо последняя).
-
Создайте еще одну функцию, которая будет
выводить предыдущую запись журнала:
function
previousEntry() {
var num = Number(_root.entryNumber.text) - 1;
if (num < 1) {
num = 1;
}
displayEntry(num);
}
Эта функция похожа на предыдущую. Первым делом
num получает значение, равное номеру текущей
записи минус один. Оператор
if проверяет,
чтобы не произошло попытки вывести на экран
запись с номером меньше 1. Рассмотрим на
примере, как это работает.
Предположим, в данный момент на экране
отображена запись номер 6. При вызове данной
функции num получает значение 5 (шесть минус
один); затем оператор if
проверяет, чтобы значение num было не меньше 1.
В данном случае это не так, поэтому действие
внутри оператора if
игнорируется и вызывается функция
displayEntry() с
передачей ей в качестве аргумента значения 5 –
на экран выводится пятая запись журнала.
Теперь допустим, что на экране – запись номер 1.
Переменная num получает значение 0. Это меньше
1, поэтому оператор if
присваивает num значение 1. Первая запись и так
уже была выведена на экран, поэтому внешне не
происходит никаких изменений. Как уже было
сказано, этот механизм предотвращает попытки
вывода на экран записей с номерами меньше 1,
поскольку таковых попросту не может быть.
-
Выделите кнопку New и введите в панели
Действия следующий скрипт:
on (release) {
newEntry();
}
Когда пользователь нажмет эту кнопку, будет
вызвана функция
newEntry(), которая на единицу увеличит
номер текущей записи и очистит поле
journalBody,
подготовив его для ввода текста новой записи.
-
Выделите кнопку Save и введите в панели
Действия следующий скрипт:
on (release) {
save();
}
Когда пользователь нажмет эту кнопку, будет
вызвана функция save(),
в результате либо текст из поля
journalBody либо
заменит существующую запись, либо будет создана
новая запись в массиве
journal (как описано на шаге 6).
-
Выделите кнопку Prev и введите следующий
скрипт:
on (release) {
previousEntry();
}
Вызов функции
previousEntry() приведет к выводу на
экран записи, номер которой на единицу меньше
номера текущей записи.
-
Наконец, выделите кнопку Next и введите
такой скрипт:
on (release) {
nextEntry();
}
Скрипт просто вызывает функцию
nextEntry() при
нажатии данной кнопки. На экран будет выведена
следующая "по списку" запись журнала.
-
Командой Управление > Проверить фильм
(Control > Test Movie) запустите тест
проекта. Введите какой-нибудь текст – запись
в журнале. Нажатием кнопки Save сохраните
запись, затем, нажав кнопку New, создайте
новую запись. Вновь введите текст и нажмите
кнопку Save, и после этого перезапустите
фильм.
После перезапуска фильма общий объект будет
загружен с вашего жесткого диска (как описано в
шагах 2 и 3), и вы сможете просматривать
сохраненные данные, пользуясь кнопками Prev и
Next.
-
Закройте тестовый фильм и сохраните свою
работу как journal2.fla.
В
этом уроке вы изучили основы использования общих
объектов – их создание, сохранение в них данных
и получение этих данных.
Общие объекты хороши для сохранения таких
данных:
- Имя
пользователя
- Последний
"посещенный" кадр
- Дата
последнего визита пользователя
-
Пользовательские настройки музыки
- Другие
пользовательские установки
- Счет игры
- Заметки,
адреса, списки
- Значения
свойств (x, y, alpha,
поворот) элементов фильма
- И тому
подобное…
|