voliuf.narod.ru

главная

друзья

помощь сайту

Flash MX Studio

Бесплатные учебники по темам

Партнерская программа

1.Представление сайта

2.Форматирование текста

3.Рисование API

4.Компоненты

5.Движемся дальше

6.Интерфейсы AсtionScript

7.Обнаружение коллизий

8.Математика и физика Flash

9.Анимация и интерактивность Drawing API

10.Реализация 3D-графики с помощью рисования API

11.Изучение SphereCage

12.Сайты с мультимедийным содержимым

13.Видеоданные

14.Аудио

15.Интеграция динамических данных

16.Динамический Flash: PHP

17.XML

18.Flash, ColdFusion и Remoting


 


Flash MX Studio
2.Форматирование текста
 
Внимание! Для работы с этой лекцией необходимы учебные файлы, которые Вы можете загрузить  здесь.

Одной из прекрасных возможностей Flash MX является широкий спектр средств управления параметрами текста. Если раньше для того, чтобы изменить шрифт в текстовом поле, нужно было присвоить тексту формат HTML, то теперь для этого есть объект textFormat. С помощью него можно избежать присутствия тегов среди переменных, если нужно отобразить их не как обычный текст.

 

Теперь мы можем указать определенную часть текста и установить формат независимо от самого текста. Также можно настраивать высоту и ширину определенных фрагментов текста, что позволяет лучше контролировать расположение и структуру текста. Теперь текстовое поле может интерпретироваться во многом аналогично фильму: отныне можно динамически создавать текстовые поля, устанавливать их позиции X и Y, а также присваивать им приемники, чтобы события происходили при изменении их содержимого.

 

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

 

Создание ваших собственных текстовых эффектов

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

 

Нам нужно, чтобы с каждым кадром в текстовом поле появлялась все большая часть строки текста. Этого можно добиться, введя переменную-счетчик и увеличивая ее значение с каждым кадром, и затем располагать текст в текстовом поле, используя этот счетчик для задания длины текста в каждом новом кадре. Во Flash 5 мы могли бы отображать текст в текстовом поле, присваивая ему переменную. Каждый раз при обновлении этой переменной текстовое поле также обновлялось бы соответствующим образом. Во Flash MX текстовое поле является объектом с параметром text. Чтобы текст отображался в текстовом поле, нам нужно присвоить фрагмент текста параметру text текстового поля.

 

Имейте в виду, что все еще можно добавить переменную текстовому полю (Var). Мы не будем использовать этот метод, так как, скорее всего, эта возможность была сохранена лишь для обеспечения корректной работы с файлами, созданными во Flash 5.

 

 


 

 

Создание эффекта пишущей машинки

  1. Откройте новый файл Flash и расположите текстовое поле на позиции (217,113). Теперь перетащите кнопку текстового поля, чтобы изменить размер поля примерно на 360 пикселей в ширину и на 150 в высоту.

    Всегда лучше изменять размер динамических текстовых полей, перетаскивая кнопку текстового поля. Если изменить размер текстового поля, указав значения W и H в Property inspector, текст будет искаженным.

     
  2. Выберите шрифт Verdana, размер шрифта 9 и черный цвет. Установите параметр текстового поля Dynamic Text, затем в ниспадающем списке Line Type выберите Multiline. Убедитесь в том, что опция Selectable не отмечена. (Selectable является опцией, определяющей, может ли пользователь делать изменения в тексте при просмотре фильма.) Назовите инстанс текстового поля tf_txt. Окно Property inspector должно выглядеть примерно следующим образом:

     


     
  3. Теперь создайте новый слой scripts и введите следующий ActionScript в кадре 1. Прежде всего мы присвоим текстовому полю некоторый текст:
    tf_txt.text = "When a vibrating source of waves is
     approaching an observer, the frequency observed is higher
     than the frequency emitted by the source. When the source is
     receding, the observed frequency is lower than that emitted.
     This is known as the Doppler effect, or Doppler's principle.";

               
  4. Запустив фильм, вы увидите, что Flash расположил текст внутри нашего текстового поля. На данном этапе имеет смысл выбрать команду меню Debug > List Variables и выяснить, в каком состоянии находится текстовое поле. В окне Output вы увидите примерно следующее:

     


     

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

     
  5. До сих пор мы выводили весь текст одновременно, а теперь нам нужно, чтобы он отображался посимвольно с каждым кадром. Чтобы добиться этого эффекта, возьмем наш фрагмент текста и присвоим его переменной вместо параметра текстового поля text. Просто замените tf_txt.text на text_str:
    text_str="When a vibrating source...

    Теперь мы создадим функцию enterFrame для добавления символов в текстовое поле один за другим с использованием метода substr объекта строки. Этот метод передает два аргумента - один из них позволяет указывать стартовую позицию, а другой указывает число символов. Затем метод получает фрагмент строки. Итак, имея в виду текстовую строку, рассмотренную выше, обратимся к следующему ActionScript:

     
    Text_str.substr (0, 6);

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

     
  6. Введите следующий ActionScript под имеющимся в слое scripts кодом:
    this.onEnterFrame = function() {
    // assign the portion of the string from 0 to count to the
    // textField.
      tf_txt.text = text_str.substr(0, count);
      count += 2;
    };
  7. Сохраните ваш фильм в файле typeWriter001.fla и запустите его. Вы можете ускорить появление текста, увеличив число, на которое возрастает значение count в каждом кадре. Одним из неприятных побочных эффектов является некорректный перенос. Мы можем обойти этот недостаток, вставив в текстовую строку символы новой строки (\n):
    text_str="When a vibrating source of waves is approaching
    an observer, the frequency observed is higher
    than nthe frequency emitted by the source.
    When the source is receding, the observed frequency is lower than
    that emitted. This is known as the Doppler effect,
    or Doppler's principle."

  8. Сохраните ваш файл под именем typeWriter001b.fla. Запустив его, вы увидите, что текст появляется в новой строке, начиная с того места, в которое вы добавили символ \n.
 

 


 

 

Несмотря на то, что этот эффект работает как надо, он далеко не идеален, так как он никогда не перестает выполняться: счетчик будет продолжать свое действие до бесконечности. Кроме этого, мы настроили функцию onEnterFrame в корневом уровне на управление эффектом. Гораздо лучше доверить тексту самостоятельное управление самим собой.

 

В идеале нам нужно уже настроенное текстовое поле, тогда мы бы просто указывали myTextField.typeIn (некоторый текст для ввода) и позволяли ему выполнять нужное действие. В предыдущих версиях Flash это можно было сделать посредством настройки функции onEnterFrame, или используя внутренний управляющий фильм, который выполнял бы нужные действия. У объекта textField, к сожалению, нет управляющего элемента onEnterFrame, поэтому нам следует использовать иной подход.

 

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

 

Повторение указанных функций с помощью setInterval

Сейчас мы будем анимировать два фильма. Один из них будет использовать onEnterFrame, а другой - метод setInterval.

 
  1. Откройте новый файл Flash и установите частоту кадров на значение 20.
  2. Нарисуйте изображение и преобразуйте его в фильм - в нашем примере мы нарисовали небольшой шарик. Расположите два инстанса объекта на рабочем месте и назовите один из них obja_mc, а другой obja2_mc.

     


     

     
  3. Теперь добавьте слой scripts в главную временную диаграмму и введите следующий код (мы будем создавать одну функцию для работы с onEnterFrame и другую для запуска под управлением setInterval).
    _root.onEnterFrame = function() {
      obja_mc._x++;
      trace("on enter frame");
    };
    function inter() {
      obja2_mc._x++;
      trace("interval function");
    }
    setInterval(inter, 50);

    Здесь мы использовали setInterval с двумя аргументами: вызываемой функции и интервала между вызовами. Функция inter будет вызываться каждые 50 миллисекунд. Мы выбрали значение 50 миллисекунд, так как оно будет соответствовать частоте смены кадров - в секунде 1000 миллисекунд, а наш фильм обновляется 20 раз в секунду, или один раз за 50 миллисекунд.

     
  4. Сохраните ваш файл под именем setInterval1.fla. Запустив его, вы заметите, что шарики двигаются примерно с одинаковой скоростью, однако расстояние между ними сильно увеличивается по мере их движения на экране.

    Два объекта должны оставаться синхронизированными, однако если обратить внимание на содержимое окна Output, то станет видно, что on enter frame и interval function изменяются, как положено, несмотря на то, что каждый второй инстанс interval function указывается дважды в строке.

     

     


     

     

    Чтобы увидеть, как изменяется инстанс, введите этот код в одной из функций; это покажет расстояние между двумя фильмами:

     
    trace (obja2_mc._x-obja_mc._x);

    Расстояние между ними не остается постоянным. Однако изменение интервала на 51 или 49 не имеет значения: в одном случае obja_mc движется быстрее, в то время как obja2_mc движется быстрее в другом. Функция setInterval работает и весьма полезна, однако если мы хотим, чтобы наши события были идеально синхронизированы, то для управления движением лучше использовать либо onEnterFrame, либо setInterval, но не использовать их вместе. Если точная синхронизация не критична для определенного приложения, тогда можно использовать оба подхода.

     
  5. Чтобы наглядно рассмотреть еще один момент, установите частоту кадров на значение 1. Теперь функция интервалов вызывается каждые 50 миллисекунд, однако рабочее место обновляется лишь один раз в 1000 миллисекунд.

    Запустив ваш фильм, вы обнаружите, что при обновлении рабочего места obja_mc каждую секунду перемещается на 1 пиксель, а obja2_mc двигается на 10 или 11 пикселей, так как функция setInterval вызывалась 10 или 11 раз между обновлениями рабочего места.

     
  6. Замените код в слое scripts следующим кодом и сохраните ваш файл под именем setInterval2.fla. Мы будем использовать его для принудительного обновления рабочего места с использованием updateAfterEvent().
    _root.onEnterFrame = function() {
      trace("on enter frame");
      obja_mc._x++;
      trace(obja2_mc._x);
    };
    function inter() {
      obja2_mc._x += 3;
      trace("interval function called");
      updateAfterEvent();
    }
    setInterval(inter, 30);

    updateAfterEvent является методом, вызываемым для обновления рабочего места независимо от частоты кадров. Он будет работать только как часть управляющего элемента clipEvent или внутри функции, присвоенной setInterval. Этот метод чаще всего используется для реализации более плавного перетаскивания при работе с перетаскиваемыми объектами. В нашем случае, мы используем его в управляющем элементе onMouseMove таким образом, что новое расположение перемещаемого объекта отображается немедленно, а не в начале следующего кадра. Рекомендуется быть осторожным и не использовать этот метод слишком много, так как вы можете видеть, насколько движение прерывисто при использовании его с setInterval. Для сравнения верните частоту кадров обратно на значение 30, и вы увидите, в чем заключается разница. В конечном счете, правильным решением будет не пытаться и не принуждать setInterval выполняться быстрее частоты смены кадров (несмотря на то, что это возможно). Flash позволяет использовать эту возможность, однако это не повод пользоваться ею при всяком удобном случае.

     
 

Динамическое создание текстового поля

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

 

Для этого мы используем метод createTextField.

 
this.createTextField ("tf_txt", 1, 50, 50, 360, 150);

Аргументы в скобках указывают имя, глубину, X, Y, ширину и высоту нового текстового поля. Это создаст стандартное текстовое поле со шрифтом, размером и т.д. по умолчанию. Теперь нам нужно включить перенос слов и запретить выделение текстового поля:

 
tf_txt.wordWrap = true;
tf_txt.selectable = false;

Затем мы создаем наш собственный объект textFormat для применения выбранных атрибутов текстового поля. Сделать это можно двумя способами. Одним из них является создание нового объекта textFormat и затем присвоение ему нужных параметров с помощью следующего ActionScript.

 
myTform = new textFormat() ;
// set properties of textFormat object
myTform.font = "Verdana";
myTform.size = 9;
myTform.color = 0xff3300;

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

 
new textFormat(font, size, color, bold, italic, underline,
Кurl, target, align, leftMargin, rightMargin, indent, leading) ;

Несмотря на то, что все эти аргументы необязательны, для того, чтобы установить какой-либо определенный параметр, нужно включить все аргументы, которые ему предшествуют. Если нам нужно опустить какие-либо из этих аргументов, то необходимо передать методу значение null. Например, если нам нужно присвоить шрифту наклонное начертание, но не жирное, то следует написать следующий код:

 
new textFormat ("Arial", 10, 0xff0000, null, true);

Таким образом, для textFormat имеем:

 
myTform = new textFormat ("Verdana", 9, 0xff3300);

Наконец, применяем объект textFormat к объекту текстового поля:

 
tf_txt.setNewTextFormat (myTform);

Обратите внимание, что мы использовали setNewTextFormat вместо setTextFormat, так как последний влияет лишь на символы, уже имеющиеся в текстовом поле, однако не на вводимые в него символы. Для демонстрации результата добавьте в конец вашего ActionScript следующий код:

 
tf_txt.text = "quick test";

Если вы используете setNewTextFormat, то текст будет отображаться красным цветом и шрифтом Verdana; если был использован setTextFormat, то символы будут черного цвета шрифтом Times New Roman.

 

Итак, приведем полный код для создания нашего текстового поля, настроенный, как необходимо:

 
this.createTextField("tf_txt", 1, 50, 50, 360, 150);
tf_txt. wordWrap = true;
tf_txt.selectable = false;
myTform = new textFormat("Verdana", 9, Oxff3300);
// apply the textFormat to the textField
tf_txt.setNewTextFormat(myTform);

Довольно сложно было добиться нужного результата, не правда ли? В большинстве случаев намного проще всего лишь перетаскивать текстовое поле на рабочее место и настраивать параметры с помощью Property inspector. Однако рекомендуется знать, как все это работает, так как может возникнуть ситуация, в которой эти знания очень вам пригодятся. Даже в этом случае мы можем установить точный размер текста, несмотря на то, что мы могли бы просто ввести следующий код:

 
    tf_txt._width = 360;
  tf_txt._height = 150;

Ввод текста

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

 
  1. Возьмите первые пять строк кода из предыдущего упражнения и введите под ними следующий код. Здесь сначала объявляется переменная для записи нашей строки, а затем идет вызов функции для ввода строки в текстовое поле:
    text_str = "vWhen a vibrating source of waves is approaching an
     observer, the frequency observed is higher than the
     frequency emitted by the source. When the source is
     receding, the observed frequency is lower than that emitted.
     This is known as the Doppler effect, or Doppler's principle." ;
    this.tf_txt.typeIn(text_str);

  2. Здесь нам понадобится функция typeIn в качестве метода объекта textField. Есть два способа определения функции: посредством присвоения ее свойству объекта
    tf_txt.typeIn = function(texta) {
      //etc. etc.
    };
      или внутри TextField.prototype:
    TextField.prototype.typeln = function(texta) {
      //etc. etc.
    };

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

     
  3. Теперь, когда мы выяснили, где будет располагаться функция в корневой временной диаграмме, нужно решить, какие именно действия она будет выполнять. Вообще говоря, ее функции будут такими же, как и ранее. Мы будем использовать аргумент texta, передаваемый функции, и записывать его в текстовое поле. Затем мы будем постепенно прибавлять символы к параметру текста нашего текстового поля до тех пор, пока текст не будет таким же, как texta. Итак, прежде всего, запишем текст в поле TextField. Для этого добавим следующий код вверху имеющейся программы.
    TextField.prototype.typeln = function(texta) {
      this.texta = texta;
    };

  4. Затем нам нужно создать функцию, которая будет выполняться через определенные интервалы времени для увеличения переменной-счетчика и соответствующего изменения текстового параметра:
    TextField.prototype.typeln = function(texta) {
      this.texta = texta;
      this.controlType = function() {
        this.count++;
        this.text = this.texta.substr(0, this.count);
      };
    };

    Это аналогично тому, с чем мы имели дело ранее - здесь к счетчику прибавляется единица и полученное значение используется для извлечения текстового фрагмента из this.texta с помощью метода substr.

     
  5. Все, что сейчас нам требуется добавить, это setInterval для повторения этой командой самой себя. Ранее, когда мы использовали setInterval, мы просто указывали имя функции для вызова. Теперь нам нужно указать имя метода и ссылку на объект, для которого нужно вызвать метод:
    setInterval (this, "controlType", 30);

    Ниже приведен окончательный код программы:

     
    TextField.prototype.typeln = function(texta) {
      this.texta = texta;
      this.controlType = function() {
        this.count++;
        this.text = this.texta.substr(0, this.count);
      };
      // call the controlType function every 30 milliseconds
      setInterval(this, "controlType", 30);
    };
    this.createTextField("tf_txt", 1, 50, 50, 300, 150);
    tf_txt. wordWrap = true;
    tf_txt .selectable = false;
    myTform = new textFormat("Verdana" , 9, 0xff3300);
    tf_txt.setNewTextFormat(myTform);

    text_str = "When a vibrating source of waves is approaching an
    Кobserver, the frequency observed is higher
    than the frequency emitted
    Кby the source. When the source is receding,
    the observed frequency is
    Кlower than that emitted. This is known as the Doppler effect,
    or Doppler's principle.";
    // initialize typeIn effect
    this.tf_txt.typeIn(text_str);

  6. Сохраните ваш файл под именем typeWriter002.fla и запустите его. Вы будете наблюдать тот же результат, что и в предыдущих примерах, однако на этот раз текстовое поле будет добавляться динамически.
 

Разделение метода на инициализацию и управление

Сначала отменим переопределение функции controlType при каждом вызове метода typeIn. Вместо этого можно было бы разделить наш метод на два отдельных метода - один для инициализации ввода, а другой для управления им:

 
TextField.prototype.typeIn = function(texta) {
  this.count = 0;
  this.texta = texta;
  setInterval(this, "controlType", 30);
};
TextField.prototype.controlType = function() {
  this.count++;
  this.text = this.texta.substr(0, this.count);
};

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

 

Завершение работы функции

Функция, настроенная с помощью setInterval, будет вызываться до тех пор, пока для нее не будет вызыван clearInterval. Когда setInterval вызывается первый раз, он возвращает идентификационный номер, который вы должны использовать следующий раз при обнулении интервала. До сих пор мы не использовали эту возможность, однако теперь настало время этим заняться.

 

В этом упражнении у нас будет текстовое поле, добавленное вручную.

 

 


 

 
  1. Чтобы установить интервал, добавим следующий выделенный код:
    TextField.prototype.typeIn = function(texta) {
      this.count = 0;
      this.texta = texta;
      this.myTypelD = setInterval(this, "controlType", 30);
    };
  2. Для обнуления интервала и прекращения вызова функции таймером интервалов добавим следующее выражение:
    clearInterval (this.myTypeID);
  3. Теперь добавим другой метод - typeDone, который будет обнулять вызов функции и затем удалять все временные переменные, которые были использованы:
    TextField. prototype. typeDone = function() {
      delete this.count;
      delete this.texta;
      // clear the interval that calls controlType
      clearInterval(this.myTypeID);
      delete this.myTypelD;
    };
  4. Затем нам нужно добавить вызов этой функции, который будет действовать по достижении переменной count длины texta:
    TextField. prototype. controlType = function() {
      this.count++;
      this.text = this.texta.substr(0, this.count);
      // if we reach the end of the string call typeDone
      if (this.count>=this.texta.length) {
      this.typeDone();
      }
    };
  5. Последним штрихом для ActionScript в этом примере будет текст, который должен отображаться:
    text_str = "When a vibrating...
    // rest of text goes here
    ... or Doppler's principle.";
    this.tf_txt.typeln(text_str);

  6. Сохраните ваш фильм в файле typeWriter004.fla и запустите его. Если вы выберете Debug > List Variables по окончании ввода, то увидите, что не осталось ни одной переменной или в объекте текстового поля вообще ничего не содержится. Вы могли бы добавить trace-выражение в функцию controlType, чтобы знать, когда действие завершается.
 

Дополнения к эффекту ввода текста

Приведем еще два дополнения для нашего набора функций.

 
  1. Прежде всего, мы можем добавить дополнительные параметры для вызова функции typeIn, расположенной в последней строке нашего ActionScript. Можно передавать ей количество символов, появляющихся в каждом кадре, а также частоту выполнения setInterval.
    this.tf_txt.typeIn(text_str, 3, 30);

    Итак, в каждом кадре будут добавляться 3 символа, а функция будет вызываться каждые 30 миллисекунд. Теперь нам нужно добавить эти параметры в функцию typeIn.

     
    TextField.prototype.typeIn =
     function(texta, typeSpeed, interval) {
      this.count = 0;
     //   store the typeSpeed inside the textField
      this.typeSpeed = typeSpeed;
      this.texta = texta;
      this.myTypeID = setInterval(this, "controlType", interval);
    };

  2. Теперь изменим функцию typeControl, чтобы применить переменную typeSpeed:
    TextField.prototype.controlType   =   function() {
      // increase the amount of text displayed by typeSpeed
      this.count += this.typeSpeed;
      this.text = this.texta.substr(0, this.count);
      if (this.count>=this.texta.length) {
        this.typeDone();
      }
    };

  3. Наконец, удалим дополнительную переменную в функции typeDone:
    TextField.prototype.typeDone = function() {
      delete this.count;
      delete this.texta;
      delete this.typeSpeed;
      clearInterval(this.myTypeID);
      delete this.myTypeID;
    };

  4. Сохраните файл под именем typeWriter005.fla. Мы можем легко изменить работу функции typeIn, просто передав ей различные значения. Можете попробовать:
    this.tf_txt.typeIn(tex, 30, 60);

    или

     
    this.tf_txt.typeIn(tex, 30, 30);
  5. По существу, нам нужно контролировать действие эффекта ввода текста, не внедряясь в функцию и не изменяя внутреннего кода. Это сделает наш метод намного более гибким и мощным.
 

Добавление функции обратной связи

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

 
  1. Добавим новые параметры в функцию typeIn.
    TextField.prototype.typeIn =
     function(texta, typeSpeed, interval, obja, func) {
      this.obja = obja;
      this.func = func;
      this.count = 0;
      this.typeSpeed = typeSpeed;
      this.texta = texta;
      this.myTypelD = setInterval(this, "controlType", interval);
    };

  2. Итак, здесь мы добавили две новые переменные - obja и func. Нам нужно вызывать их по окончании ввода текста, поэтому мы добавили их в функцию typeDone.
    TextField.prototype.typeDone = function() {
      delete this.count;
      delete this.texta;
      delete this.typeSpeed;
      clearInterval(this.myTypeID);
      delete this.myTypeID;
      // execute callback function
      this.obja[this.func]();
      delete this.obja;
      delete this.func;
    };

  3. Для проверки нам понадобится создать функцию для получения обратного вызова и затем изменить наш исходный вызов. Введите этот код под имеющимися функциями.
    function allDone() {
        trace("type done");
      }

  4. Наконец, нам нужно передать некоторые дополнительные значения функции typeIn. Добавьте следующий выделенный код в последнюю строку ActionScript:
    this.tf_txt.typeIn (text_str, 1, 30, _root, "allDone");
  5. 5. Сохраните фильм в файле typeWriter006.fla. При выполнении фильма в окне Output появятся слова type done, так как по окончании ввода была вызвана функция allDone.

     


     

     
 

О прототипах

При добавлении функций или параметров в прототипы объектов, необходимо быть осторожным. Если используется цикл for:in для нумерации параметров и методов объекта, на первый план выйдут новые методы и параметры объекта. В качестве примера рассмотрим следующий код:

 
_root.createEmptyMovieClip("blah", 1);
blah.myVariable = 20;
for (var i in blah) {
  trace(i+" : "+blah[i]);
}

Протокол выполнения этой процедуры в окне Output отобразит "myVariable : 20". Теперь, если мы добавим функцию в прототип Movieclip, которая так же будет выделена в отдельном инстансе фильма:

 
MovieClip.prototype.yada = function() {
};
_root.createEmptyMovieClip("blah", 1);
blah.myVariable = 20;
for (var i in blah) {
  trace(i+" : "+blah[i]);
}

протокол будет содержать следующее:

 
yada : [type Function]
myVariable : 20

Функция yada, которую мы определили для всех фильмов, выводится в инстансе blah. Нет оснований считать это проблемой, особенно когда мы ожидаем данное действие. Однако в определенных ситуациях это может стать проблемой, например, если вы используете еще какой-либо код, повторяющий применение параметров и методов MovieClip, и ожидаете определенного результата.

 

Чтобы предотвратить эти нежелательные последствия, можно использовать метод AsSetPropFlags. Он официально не поддерживается в ActionScript, поэтому лучше на него все же не надеяться, однако он позволяет "скрыть" любые дополнительные параметры или методы, добавленные в цикле for:in. Вызываем метод AsSetPropFlags, передаем ему имя объекта, параметр которого необходимо скрыть, имя параметра или метода и число 1:

 
AsSetPropFlags (MovieClip.prototype, "yada", 1);

Итак, если мы теперь поместим этот код в нашу предыдущую программу и выполним ее, метод yada больше не будет отображаться циклом:

 
MovieClip. prototype. yada = function() {
};
ASSetPropFlags(MovieClip.prototype, "yada", 1);
_root.createEmptyMovieClip("blah", 1);
blah.myVariable = 20;
for (var i in blah) {
  trace (i+" : "+blah[i]);
}

Это лишь один из результатов, который может быть получен с помощью AsSetPropFlags. Также можно защитить параметры от перезаписи и осуществлять многие подобные действия. За более подробной информацией обратитесь к странице http://chattyfig.figleaf.com/flashcoders-wiki/index.php?ASSetPropFlags.

 

Работа с объектом textFormat

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

 

Использование setTextFormat

Начнем с краткого изучения использования setTextFormat как такового. Как уже было упомянуто ранее, объект textFormat содержит все данные форматирования для текстового поля. Даже если мы не укажем объект textFormat для текстового поля, у него есть такой объект по умолчанию, и он может быть вызван с помощью выражения TextField.getTextFormat (). Когда мы прежде работали с textFormat, мы использовали его для применения форматирования ко всему объекту textField. Теперь мы будем использовать его для форматирования определенного фрагмента текстового поля.

 
  1. Откройте новый фильм и создайте текстовое поле, как в предыдущих примерах.

     


     

    В данном текстовом поле установите красный цвет текста и дайте имя инстансу в Property inspector (tf_txt).

     
  2. Нам нужно выделить определенный фрагмент текста, поэтому сначала необходимо определить этот фрагмент и его форматирование. Добавьте новый слой scripts и в первом кадре введите следующий код.
    this.tf_txt.text = "The eidophor system is
    a projection television system,
    i.e. it enables Кenlarged television pictures to be projected
    on to a screen.
    An ordinary television picture Кderives its brightness
    from the fluorescence of
       a screen bombarded by electrons;
    with Кthe eidophor system, on the other hand,
    a very powerful source of light is controlled by
    Кthe television signal
       picked up by the receiver." ;
    // create textFormat object
    myForm = new TextFormat() ;
    myForm.color = 0x00000;
    myForm.font = "Verdana";
    myForm.size = 9;

  3. Итак, мы создали объект textFormat с именем myForm. Теперь применим его к текстовому полю. Давайте остановимся на слове "eidophor", первый символ которого стоит на 4 позиции, а последний - на 12-й. Мы передадим эти два значения в качестве аргументов, а также объект myForm, методу setTextFormat. Добавьте следующую строку кода под уже имеющимся кодом.
    // apply textformat to characters 4 to 12
    this.tf_txt.setTextFormat(4, 12, myForm);

  4. Сохраните фильм в файле setTextFormat.fla. При его запуске вы увидите слово "eidophor", выделенное черным цветом. Любые изменения в объекте textFormat будут отображены в тексте. Например, если вы добавите следующее выражение над строкой setTextFormat, наше слово будет выделено черным жирным шрифтом:
    myform.bold = true;

    Полезно знать, что если объект textFormat не имеет определенного свойства при применении к объекту textField, он будет использовать уже присутствующее значение. Проверим это.

     
  5. Замените весь код textFormat на следующее:
    myForm = new TextFormat ();
    myForm.color = 0x000000;

    Здесь нет никакой информации о шрифте или его размере, однако при применении к текстовому полю используется уже имеющееся форматирование (Verdana, 9 пикселей). При запуске фильма, если вы выберете команду Debug > List Variables, то увидите, что объект myForm содержит большое количество переменных со значением null.

     

     


     

     

    Когда объект textFormat применяется с использованием textField.setTextFormat, все эти null-значения просто отбрасываются и заменяются уже имеющимися значениями.

     
  6. Добавьте следующую строку кода. Мы будем использовать метод getTextFormat, чтобы передать textFormat фрагмент текста.
    // retrieve the textFormat for characters 4 to 12 in the text field
    post = this.tf_txt.getTextFormat(4, 12);

  7. Сохраните фильм в файле setTextFormat(post).fla, запустите его и выберите Debug > List Variables, и вы увидите, что все переменные присутствуют в post, даже те, которые мы не устанавливали в myForm.

     


     

     

    Теперь у вас есть представление о том, как использовать setTextFormat, и можно приступить к созданию метода для постепенного изменения textFormat. Мы будем делать это во многом аналогично тому, как поступали с функцией typeID. Мы передадим функции число параметров, включая объект textFormat, точку начала, конечную точку, скорость и интервал. Мы также настроим ее на работу с функцией обратной связи, которую применим во второй части данного примера.

     
  8. Вызов функции будет выглядеть так. Добавьте эту строку внизу ActionScript, под строками кода myForm.
    this.tf_txt.nooTextFormat (myForm, 4, 11, 1, 30);

    Теперь ваш ActionScript будет выглядеть следующим образом.

     
    this.tf_txt.text = "The eidophor system...by the receiver.";
    myForm = new TextFormat();
    myForm.color = 0x000000;
    this.tf_txt.nooTextFormat(myForm, 25, 43, 1, 30);

  9. Основное ядро функции вам знакомо, так как вы уже встречались с такой конструкцией. Добавьте следующий ActionScript над имеющимся кодом (мы добавим оставшуюся часть кода для nooTextFormatControl и cleanNooTextFormat одновременно).
    TextField.prototype.nooTextFormat =
      function(tForm, begin, end, speed, interval,
    Кobja, func) {
    // store parameters in text field
      this.begin = this.current= begin;
      this.end = end+1;
      this.speed = speed;
      this.end = end;
      this.obja = obja;
      this.func = func;
      this.nooTform = tForm;
    // set interval to call nooTextFormatControl
      this.myNooText = setlnterval
      (this, "nooTextFormatControl", interval) ;
    };
    TextField.prototype.nooTextFormatControl = function() {
    };
    TextField.prototype.cleanNooTextFormat = function() {
    };

    Мы делаем то же самое, что и раньше - берем все копии всех аргументов, передаваемых в аргумент, и помещаем их в само текстовое поле. Мы приравниваем this.end к end+1, так как второй аргумент, передаваемый setTextFormat, ссылается на символ после последнего символа, к которому применен другой формат, тогда как передаваемое нами значение ссылается на последний символ, формат которого мы хотим изменить.

     

    В функции управления nooTextFormatControl мы будем пошагово прибавлять значение переменной this.current и увеличивать строку текста, к которой применяется textFormat. Мы начинаем current со значения begin и продолжаем увеличивать его до тех пор, пока оно не достигнет значения end.

     
  10. Добавьте следующий выделенный код в nooTextFormatControl.
    TextField.prototype.nooTextFormatControl = function() {
      this.current + = this.speed;
      if (this.current>this.end) {
        this.setTextFormat(this.begin, this.end, this.nooTform);
        this. cleanNooTextFormat () ;
      } else {
        this.setTextFormat(this.begin, this.current, this.nooTform);
      }
    };

    При каждом вызове функции мы добавляем speed к значению переменной current. Если это значение меньше, чем конец области, на которую мы хотим оказать влияние, то мы меняем значение textFormat с begin на current. Если оно является конечной точкой или близко к ней по значению (в случае, если мы с каждым кадром прибавляем к current 3 или 4), то мы применяем формат к тексту с использованием начального и конечного значений, переданных в начале, и вызываем функцию cleanUp.

     
  11. Последнее, что мы сделаем, это добавим следующий выделенный код в cleanNooTextFormat.
    TextField.prototype.cleanNooTextFormat = function() {
      delete this.current;
      delete this.nooTform;
      delete this.begin;
      delete this.end;
      clearInterval(this.myNooText);
      delete this.myNooText;
      this.obja[this.func] ();
    };

  12. Сохраните новый файл под именем switchTextFormat1.fla. Как и раньше, эта функция удаляет все неиспользуемые переменные или свойства.
 

Применение данного подхода

Рассмотрим применение только что изученного нами подхода на практике. Мы напишем небольшое приложение, которое будет находить все вхождения определенного фрагмента текста внутри текста большего объема, и выделять их по очереди. Здесь вы поймете значение функций обратной связи.

 

Для начала нам понадобится функция для просмотра текста и возвращения позиций указанной нами строки. Так как эта функция будет работать со строками, нам нужно создать ее в виде метода объекта строкового типа. Функция findInstances выглядит так.

 
myString.findInstances (str);

 

 

Чтобы найти вхождение строки внутри другой строки, можно использовать indexOf. Сама по себе indexOf выглядит так:

 
var pos = myString.indexOf (str);

 

 

Функция indexOf возвращает номер-индекс первого вхождения str. Теперь нам нужно найти каждое вхождение str, и для этого можно применить другой способ использования indexOf, где указывается номер-индекс, с которого следует начать просмотр:

 
var pos = myString.indexOf (str, startIndex);

В этой функции должен быть цикл. По нахождении первого вхождения строки, она будет брать номер-индекс первого найденного вхождения str и использовать его в качестве точки начала следующей операции indexOf. Цикл будет повторяться до тех пор, пока не будут найдены все вхождения str, после чего indexOf возвратит значение -1. Цикл закончит свою работу и возвратит массив найденных значений.

 
String.prototype.findInstances = function(str) {
  var foundAt = [];
  var nextFound = 0;
  // while there are still instances of the string
  while (nextFound != -1) {
    nextFound = this.indexOf(smallStr, nextFound);
    if (nextFound != -1) {
      foundAt.push({begin:nextFound, end:nextFound+str.length});
      nextFound++;
    }
  }
  // return the array of beginning and end values
  return foundAt;
};

Разберем каждую строку этого кода. Сначала мы устанавливаем currIndex на ноль, т.е. на ту позицию, с которой начинается поиск. Далее создаем массив foundAt для добавления в него всех значений, которые нужно возвратить. Затем объявляется переменная nextFound для записи возвращаемого значения. При этом используется слово var для указания того, что переменная должна существовать только во время выполнения функции.

 

Для настройки цикла используется выражение while(nextFound!=-1), так как нам нужно, чтобы цикл завершал работу, когда больше не может быть найдено ни одно вхождение строки. Первая строка цикла дает нам номер-индекс следующего вхождения строки поиска в более объемной строке, после точки, указываемой currIndex.

 
nextFound = this.indexOf (str, currIndex);

Если значением nextFound не является -1, это означает, что найдено вхождение строки, и выражения, включенные в условие, будут выполнены. Будет добавлено следующее вхождение строки и увеличено значение nextFound, после чего продолжится выполнение следующего кода:

 
if (nextFound != -1) {
  foundAt.push({begin:nextFound, end:nextFound+smallStr.length});
  nextFound++;
}

Мы интерпретируем это как объект, содержащий начальное и конечное значения, поэтому можно указать начальную и конечную точки для фрагмента текста.

 
foundAt.push ({begin:nextFound, end:nextFound+str.length});

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

 
return foundAt;

Чтобы опробовать этот метод, создадим новый файл. Добавьте определенный нами метод над и под следующим текстом.

 
text_str="The eidophor system is a projection television system,
i.e. it enables enlarged Кtelevision pictures
to be projected on to a screen.
An ordinary television picture derives its
brightness from the fluorescence of
   a screen bombarded by electrons;
with the eidophor system, on the other hand,
a very powerful source of light is controlled by
the television signal
   picked up by the receiver."
vals=text_str.findlnstances("television")

Выполнив код и просмотрев переменные, вы увидите, что vals содержит массив с четырьмя объектами - по одному для каждого вхождения слова "television", указанного в строке выше. Однако чтобы этот метод работал при любых обстоятельствах, необходимо внести в него некоторые изменения.

 

Преобразование строк

  1. С нашими текущими настройками, если регистр (верхний/нижний) строки поиска не соответствует вхождению в тексте, оно не будет интерпретироваться как найденная строка. Чтобы избежать этого, преобразуем обе строки перед использованием в нижний регистр. Ниже приведены дополнения в коде.
    String.prototype.findlnstances = function(str) {
      var foundAt = [] ;
      var nextFound = 0;
    //   change both strings to lower case
      var largeStr = this.toLowerCase();
      var smallStr = str.toLowerCase();
      while (nextFound!=-1) {
        nextFound = largeStr.indexOf(smallStr, nextFound);
        if (nextFound != -1) {
          foundAt.push({begin:nextFound, end:nextFound+smallStr.length});
          nextFound++;
        }
      }
    return foundAt;
    };

    Теперь код будет работать при поиске любой строки внутри любой более объемной строки.

     
  2. Открываем switchTextFormat1.fla и добавляем на рабочее место текстовое поле и три функции: nooTextFormat, nooTextFormatControl и cleanNooTextFormat. После этого добавляем метод findInstances. Теперь создаем функции для поиска вхождений строки и выделяем их. Сначала нам понадобится функция для инициализации, которая будет вызывать findInstances и записывать результат в массив. После этого она будет вызывать функцию doNext.
    function nooFindAndReplace(textObj, str) {
      this.indices = textObj.text.findlnstances(str);
      this.doNext();
    }

    doNext будет использовать метод shift массива для извлечения первой пары индексов из массива indices и затем передавать их в nooTextFormat. Мы передаем doNext в виде функции с обратной связью таким образом, что когда формат одного слова изменится, doNext будет вызвана снова, и мы перейдем к следующему слову.

     
    function doNext() {
    // if there is another string
      if (indices.length>0) {
        var nexta = this.indices.shift();
        this.tf_txt.nooTextFormat
         (myForm, nexta.begin, nexta.end, 1, 30, this, "doNext");
      }
    }

  3. Наконец, мы определяем строку, в которой будет осуществляться поиск, и затем вызываем функцию.
    this.tf_txt.text = "The eidophor system is
    a projection television system,
    i.e. it enables enlarged television pictures
    to be projected on to a screen.
    An ordinary television picture derives
    its brightness from the fluorescence of
       a screen bombarded by electrons;
    with the eidophor system, on the other hand,
    a very powerful source of light is controlled
    by the television signal
       picked up by the receiver. " ;
    myForm = this.tf_txt.getTextFormat() ;
    myForm.color = 0x000000;
    myForm.size = 9;
    myForm. bold = true;
    // trigger find and replace
    nooFindAndReplace(this.tf_txt, "television", myForm);

    В окончательном виде весь код будет выглядеть так.

     
      В окончательном виде весь код будет выглядеть так.
    TextField.prototype.nooTextFormat = function(tForm, begin, end, speed, interval, obja, Кfunc) {
      this.begin = this.current=begin;
      this.end = end+1;
      this.speed = speed;
      this.end = end;
      this.obja = obja;
      this.func = func;
      this.nooTform = tForm;
      this.myNooText = setlnterval(this, "nooTextFormatControl", interval);
    };
    TextField.prototype.nooTextFormatControl = function() {
      this.current += this.speed;
      if (this.current>this.end) {
        this.setTextFormat(this.begin, this.end, this.nooTform);
        this.cleanNooTextFormat();
      }   else   {
        this.setTextFormat(this.begin, this.current, this.nooTform);
      }
    };
    TextField.prototype.cleanNooTextFormat = function() {
      delete this.current;
      delete this.nooTform;
      delete this.begin;
      delete this.end;
      clearlnterval(this.myNooText);
      delete this.myNooText;
      this.obja[this.func]();
    };
    String.prototype.findlnstances = function(str) {
      var foundAt = [] ;
      var nextFound = 0;
      var largeStr = this.toLowerCase();
      var smallStr = str.toLowerCase();
      while (nextFound!= -1) {
        nextFound = largeStr.indexOf(smallStr, nextFound);
        if (nextFound != -1) {
          foundAt.push({begin:nextFound, end:nextFound+smallStr.length});
          nextFound++;
        }
      }
    return foundAt;
    };
    function nooFindAndReplace(textObj, str) {
      this.indices = textObj.text.findlnstances(str) ;
      this.doNext();
    }
    function doNext() {
      if (indices.length>0) {
        var nexta = this.indices.shift();
        this.tf_txt.nooTextFormat(myForm, nexta.begin, nexta.end, 1, 30, this, "doNext");
      }
    }
    this.tf_txt.text = "The eidophor system is a projection television system, i.e. it enables enlarged television pictures to be projected on to a screen. An ordinary television picture derives its brightness from the fluorescence of a screen bombarded by electrons,- with the eidophor system, on the other hand, a very powerful source of light is controlled by the television signal picked up by the receiver.";
    myForm = this.tf_txt.getTextFormat();
    myForm.color = 0x000000;
    myForm.size = 9;
    myForm.bold = true;
    nooFindAndReplace(this.tf_txt, "television", myForm);

    Пример 2.1.

  4. Сохраните файл под именем switchTextFormat2.fla и запустите его. Вы увидите четыре вхождения слова "television", выделенные красным цветом.
 

The eidophor system is a projection television system, i.e. it enables enlarged television pictures to be projected on to a screen. An ordinary television picture derives its brightness from the fluorescence of a screen bombarded by electrons; with the eidophor system, on the other hand, a very powerful source of light is controlled by the television signal picked up by the receiver.

 

Используя этот метод, можно добиться большого количества разнообразных эффектов. Например, можно просто изменить некоторые значения в объекте textFormat, изменить скорость и т.д.

 

Существует несколько менее значимых, но полезных дополнений к этому подходу. Например, функция doNext намеренно написана для отдельного объекта текстового поля и textFormat. В идеале, мы имели бы дело с объектами текста и формата текста, передаваемыми ей в виде аргументов. Это можно реализовать, передавая в начале значения текстовому полю, и затем, когда каждое слово обработано, передавать эти аргументы в doNext для использования при ее следующем вызове. Мы не будем тратить время на то, чтобы разбираться в этом сейчас, однако в файле switchTextFormat3.fla есть комментарии, которые помогут вам уяснить все должным образом. По большому счету, это просто расширение нашей функции обратной связи для передачи аргументов.

 

Дополнительные текстовые эффекты

До сих пор мы рассматривали текстовые эффекты внутри текстового поля. Несмотря на то, что они могут быть полезны, на них накладывается ряд ограничений Flash MX позволяет создавать более содержательные текстовые эффекты. При создании текстового эффекта мы, как правило, будем располагать каждую букву в фильме и затем динамически позиционировать (или перемещать) ее на определенное местоположение. Во Flash 5 нельзя было динамически получать ширину текста и, как следствие, позиционировать отдельные символы. Для достижения таких эффектов во Flash 5 приходилось использовать дополнительное средство - строку с калькулятором из www.swfx.org.

 

Flash MX предоставляет два способа вычисления ширины строки так, что мы можем выяснить, в каком месте должен располагаться каждый символ. Сначала используется textFormat.getTextExtent (str). С помощью этого метода можно передавать ему строку, и он будет возвращать объект, содержащий ширину и высоту данного фрагмента текста, как если бы все они располагались в одной строке. Это очень удобно, но данный подход имеет несколько особенностей, которые мы сейчас рассмотрим. Второй способ получения ширины строки заключается в том, что строка помещается в текстовое поле (с необходимым форматированием), и затем используется параметр textWidth текстового поля. Несмотря на то, что этот метод более громоздкий (так как здесь приходится создавать текстовое поле, чтобы задействовать его), он более точен по сравнению с использованием getTextExtent при работе со встроенными шрифтами. Продемонстрируем теперь работу этого метода.

 

Вычисление ширины строки

  1. Откройте новый фильм Flash и разместите на рабочем месте поле DynamicText, причем сделайте так, чтобы его длина занимала большую часть рабочего места. Мы будем использовать шрифт Verdana.
  2. В Property inspector дайте инстансу имя tf_txt. Затем создайте слой scripts и введите следующий код.
    myTForm = new TextFormat();
    myTForm.size = 24;
    myTForm.font = "Verdana";
    str = "a piece of test text to check widths";
    tf_txt.text = str;
    tf_txt.setTextFormat(myTForm);
    // retrieve width with getTextExtent
    a = myTForm.getTextExtent(str).width;
    // retrieve width with textWidth
    b = tf_txt.textWidth;
    trace(a+" : "+b);
  3. Запустите ваш файл и посмотрите на результат в окне Output. Окно будет отображать 407 : 416. 407 представляет собой ширину getTextExtent, и 416 - это textWidth.
 

Мы нарисовали две линии на рабочем месте, чтобы вы могли сравнить их. Имя файла - textWidthTest.fla.

 

 


 

 

Присутствующая здесь проблема типична для установки интервалов между знаками: если мы располагаем текст с помощью getTextExtent, символы отображаются один за другим, и между ними нет никакого интервала. Другими словами, textWidth - это наилучший способ аккуратного размещения текста.

 

Определение местоположения символов

Теперь мы решили, что нам потребуется использовать TextField.textWidth для определения местоположения символа, и нам нужно написать функцию для вычисления этого параметра для любого данного нам объекта textFormat (например, для определенного размера текста и шрифта). Это намного проще сделать с использованием textFormat.getTextExtent, так как нам не нужно создавать текстовое поле для вычисления ширины. Остановимся на этом подходе, как на более аккуратном.

 

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

 

Нам нужно иметь возможность передавать функции объект textFormat и строку, что можно реализовать следующим образом.

 
  function charPositions(tFormat, str, depth) {
  . . .
  }

Мы также включим параметр depth, чтобы можно было указывать его извне, предотвращая запись поверх любых других объектов.

 

Получение других данных о символах

  1. Создайте временное текстовое поле Dynamic Text в месте, отличном от вашего рабочего места. Установите для этого текстового поля шрифт Arial.
  2. Добавьте новый слой scripts и введите в нем следующий код.
    function charPositions(tFormat, str, depth) {
      _root.createTextField("temp", depth, 0, -300, 100, 400);
      temp.embedFonts = true;
      temp.autoSize = true;
      temp.setNewTextFormat(tFormat);
      temp.text = str;
    }

    Мы установили autoSize на значение True, поэтому поле будет изменять размер, чтобы вмещать любой помещаемый в него текст. Мы также установили параметр embedFonts на значение True, и textFormat на значение tFormat. Кроме этого, нам нужно присвоить переменную str параметру text текстового поля.

     

    При установке параметра embedFonts текстового поля на значение True помните, что шрифт, используемый в фильме, необходимо экспортировать. Для этого и понадобилось временное поле Dynamic Text в каком-либо другом месте. Также необходимо убедиться в том, что отмечена опция Embed Font Outlines For All Characters в диалоговом окне Character Options:

     

     


     

     
  3. Чтобы открыть диалоговое окно Character Options, просто нажмите кнопку Character: при настройке атрибутов текста в Property inspector. Для форматирования жирным или наклонным шрифтом вам понадобится другое текстовое поле, настроенное на жирный или наклонный шрифт. Вы можете сделать то же самое с помощью символа шрифта.
  4. Далее мы создадим временный массив для записи значений позиций, и тогда все будет готово для работы цикла и определения ширины строки.
    function charPositions(tFormat, str, depth) {
      _root.createTextField("temp", depth, 0, -300, 100, 400);
      temp.embedFonts = true;
      temp.autoSize = true;
      temp.setNewTextFormat(tFormat);
      temp.text = str;
      var arr = [] ;
    }
  5. Для определения позиции каждого символа надо сначала выяснять ширину всей строки, а затем местоположение каждого символа, которое будет вычисляться вычитанием ширины строки, начинающейся с данной точки, из ширины всей строки. Например, если нашей строкой является "In the manufacture", то позиция символа "m" в слове "manufacture" равна ширине "In the manufacture" минус ширина "manufacture". Добавим в цикл следующий код.
    function charPositions(tFormat, str, depth) {
      _root.createTextField("temp", depth, 0, -300, 100, 400);
      temp.embedFonts = true;
      temp.autoSize = true;
      temp. setNewTextFormat (tFormat);
      temp, text = str;
      var arr = [] ;
      //the total width of the text
      var totalWidth = temp.textWidth;
     
      for (var i = 0; i<str.length; i++) {
        temp.text = str.substr(i);
        // calculate the difference between the width to this point
        // and the total width
         arr[i] = totalWidth-temp. textWidth;
      }
    }

    В каждой итерации цикла мы перемещаемся на один символ вперед в строке и записываем строковое значение из этого символа в наше временное текстовое поле str.substr(i). Затем мы вычисляем ширину, вычитаем ее из полной ширины и записываем результат в наш массив.

     
  6. Далее нужно удалить созданное текстовое поле и возвратить массив:
    function charPositions(tFormat, str, depth) {
      _root.createTextField("temp", depth, 0, -300, 100, 400);
      temp.erabedFonts = true;
      temp.autoSize = true;
      temp.setNewTextFormat(tFormat);
      temp.text = str;
      var arr = [];
      var totalWidth = temp.textWidth;
      for (var i = 0; i<str.length; i++) {
        temp.text = str.substr(i);
        arr[i] = totalWidth-temp.textWidth;
      } 
      temp.removeTextField();
      return arr;
    }

  7. Наконец, вызываем функцию:
    mt = new TextFormat();
    mt.font = "Arial";
    mt.size = 45;

    str = "In the manufacture of safety matches,
     softwood logs are peeled into
       a thin continuous shaving,
    or veneer, about one tenth of an inch thick.
    The ribbon of wood is then cut up into splints at
    a rate of about two million per hour.
    These splints are soaked in a bath of sodium silicate,
    ammonium phosphate
       or sodium phosphate and then dried.
    This impregnation prevents afterglow.";
    posArray = charPositions(mt, str, 1);
 

Сохраните фильм в файле obtainCharPos.fla и запустите его. Если вы выберете команду меню Debug > List Variables, то увидите, что массив posArray содержит значение для каждой буквы в нашей строке.

 

Теперь у нас есть большой список позиций по X. Далее нам нужно каким-то образом использовать эту информацию.

 

 


 

 

Использование позиций символов

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

 

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

 

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

 

Прежде всего, получим позиции символов. Далее определим высоту каждой строки с помощью getTextExtent (точность здесь не очень важна). Затем мы создадим переменную currentLine для записи того, в какой строке находимся, и массив finalPositions со всеми конечными координатами.

 

Использование данных о символах для плавного появления текста

 
  1. Добавьте следующий ActionScript под функцией charPositions в файле
    obtainCharPos.fla.
    function setUpText(str, forma, lineLength) {
      var positions = charPositions(forma, str, 1000);
      var currentLine;
      var lineHeight = forma.getTextExtent(str).height;
      var finalPositions = [];
    }

    Далее мы добавим цикл для обработки каждой записи в массиве позиций. Этот цикл будет проверять, является ли позиция X большей, чем lineLength. Если это так, она будет сбрасываться на ноль и к переменной currentLine будет прибавляться единица для обновления позиции Y. Мы будем учитывать расстояние, на которое необходимо возвращать символы, так как все последующие символы также будут перемещены назад на то же расстояние. Это значение мы будем хранить в переменной с именем substracta.

     
  2. Если у нас есть символ на позиции 510, а значение lineLength равно 500, необходимо вернуть его и все последующие символы назад на 510. Если позиция X символа больше, чем 510 плюс длина строки, мы сбрасываем ее на ноль и прибавляем число позиций, которое было сброшено, в переменную substractа, для учета этого значения в сумме нарастающим итогом. Добавьте следующий выделенный код в функцию setUpText.
    function setUpText(str, forma, lineLength) {
      var positions = charPositions(forma, str, 1000);
      var currentLine;
      var subtracta;
      var lineHeight = forma.getTextExtent(str).height;
      var finalPositions = [] ;
      for (var i = 0; i<positions.length; i++) {
      // if the current position is off the right edge
        if (positions[i]>(lineLength+subtracta)) {
          subtracta = positions[i];
          currentLine++;
        }
        var x = positions[i]-subtracta;
        var у = lineHeight*currentLine;
        finalPositions[i] = {char:str.charAt(i), x:x, y:y};
      }
      return finalPositions;
    }

    Здесь мы добавили две следующие функциональности. Первая заключается в том, что мы вычисляем позицию Y, умножая значение currentLine на lineHeight; мы передвигаем вниз страницу на высоту текста для каждой добавленной строки текста. Мы также записали наши значения символов и позиции в массив в виде объекта. Таким образом, при возвращении массива у нас будет возможность использовать его без знания строки; теперь это просто список символов.

     
  3. Далее мы создадим небольшую функцию инициализации для вызова функции setUpText.
    function init(str, tForm, lineLength) {
      // retrieve character positions
      charPos = setUpText(str, tForm, lineLength);
      this.count = 0;
      // set drawNext to be called every frame
      this.onEnterFrame = drawNext;
    }

    Мы будем передавать ей все соответствующие данные, и функция будет получать позиции символов для строки. По завершении ее работы мы настраиваем функцию enterFrame для _root, drawNext. Это нужно для поочередного прорисовывания каждой буквы с использованием переменной count для протоколирования.

     
  4. После этого мы добавляем функцию drawNext. В каждом кадре при ее вызове она будет искать следующий символ в массиве и получать его позицию. Затем она будет создавать дубликат фильма на этой позиции, а в нем текстовое поле с соответствующим символом с корректным форматированием. Затем функция устанавливает параметр интенсивности alpha на значение 30 и применяет к нему функцию onEnterFrame для постепенного увеличения интенсивности. Это все должно быть вам понятно, если вы разбирали весь рассмотренный до данного момента код. Добавьте в фильм следующий код.
    function drawNext() {
      var noo = this .createEmptyMovieClip ("lett"+count, count) ;
      var nextObj = charPos[this.count];
      // a reference to the object in the array
      noo._x = nextObj.x;
      noo._y = nextObj.y;
      noo.createTextField("tex", 1, 0, 0, 100, 100);
      noo.tex.text = nextObj.char;
      noo.tex.embedFonts = true;
      noo.tex.selectable = false;
      noo.tex.setTextFormat(mt);
      noo._alpha = 30;
      noo.onEnterFrame = function() {
        // increase alpha until 100 is reached
        this._alpha += 5;
        if (this._alpha>=100) {
          delete this.onEnterFrame;
        }
      };
      count++;
      if (count>charPos.length) {
        delete this.onEnterFrame;
      }
    }

  5. Настраиваем текстовые форматы и добавляем вызов функции init.
    mt = new TextFormat();
    mt.font = "Arial";
    mt.size = 24 ;
    str = "In the manufacture of safety matches,
    softwood logs are peeled into
       a thin continuous shaving,
    or veneer, about one tenth of an inch thick.
    The ribbon of wood is then cut up into splints at
    a rate of about two million per hour.
    These splints are soaked in a bath of sodium silicate,
    ammonium phosphate or
       sodium phosphate and then dried.
    This impregnation prevents afterglow.";
    init(str, mt, 530);
  6. Сохраните файл под именем useCharPos.fla и запустите его. Помните, для его правильной работы необходимо иметь текстовое поле вне рабочего места, настроенное на используемый вами шрифт, в данном случае - Arial. Результатом вашей работы будет постепенное появление букв и плавное усиление их яркости.

     


     

     

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

     
 

Прочие возможности

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

 

Реализация случайного появления символов

 
  1. Единственным изменением в данном файле будет функция drawNext. Откройте useCharPos.fla и приготовьтесь вносить в него изменения.

    Функция drawNext необходима для случайного выбора символа из массива и его прорисовки. Затем символ будет удаляться из массива, после чего будут оставаться только те символы, которые все еще должны быть прорисованы. Код реализации этой функциональности довольно прост. Сначала выбирается случайное число между 0 и числом записей в массиве. Затем эта запись переносится из массива во временную переменную. После этого элемент удаляется из массива с помощью метода splice.

     
    var next = Math.floor(Math.random()*charpos.length);
    var nextObj = charPos[next] ;
    charPos.splice(next, 1) ;
  2. Остальная часть функции более или менее похожа на предыдущую. Единственным отличием является способ выбора символа для создания дубликата.
    function drawNext() {
      this.count++;
      // pick a random character
      var next = Math.floor(Math.random()*charpos.length);
      var nextObj = charPos[next];
      charPos.splice(next, 1);
      var noo = this.createEmptyMovieClip
       ("lett"+this.count, this.count);
      noo._x = nextObj.x;
      noo._y = nextObj.y;
      noo._alpha = 30;
      noo.onEnterFrame = function() {
        this._alpha += 5;
        if (this._alpha>=100) {
          delete this.onEnterFrame;
        }
      };
      noo.createTextField("tex", 1, 0, 0, 100, 100);
      noo.tex.text = nextObj.char;
      noo.tex.embedFonts = true;
      noo.tex.selectable = false;
      noo.tex.setTextFormat(mt);
      if (charPos.length == 0) {
        delete this.onEnterFrame;
        return;
      }
    }

  3. Можно ускорить выполнение этой программы, заключив весь код в цикл, вследствие чего с каждым кадром будет создаваться больше дубликатов.
    function drawNext() {
      for (var i = 0; i<4; i++) {
        this.count++;
        var next = Math.floor(Math.random()*charpos.length);
        var nextObj = charPos[next];
        charPos.splice(next, 1);
        var noo = this.createEmptyMovieClip
          ("lett"+this.count, this.count);
        noo._x = nextObj.x;
        noo._y = nextObj.y;
        noo._alpha = 30;
        noo.onEnterFrame = function() {
          this._alpha += 5;
          if (this._alpha>=100) {
            delete this.onEnterFrame;
        }
      };
      noo.createTextField("tex", 1, 0, 0, 100, 100);
      noo.tex.text = nextObj.char;
      noo.tex.embedFonts = true;
      noo. tex. selectable = false;
      noo.tex.setTextFormat(mt);
      if (charPos.length == 0) {
        delete this.onEnterFrame;
        return;
        }
      }
    }

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

     

     


     

     

    Создав этот базис, очень легко продолжить работу и создать довольно сложные текстовые эффекты. Можно применить функцию slideTo, чтобы буквы скользили или "прыгали" по очереди на свои места.

     

    Зная конечную позицию каждой буквы, мы можем делать все, что нам нужно, с каждой буквой фильма перед тем, как она окажется на своем конечном месте. Три исходных файла, прилагаемые к этой главе, демонстрируют подобные эффекты, достигаемые изменением всего лишь нескольких строк кода. Первый файл - useCharPosSwingTo.fla - располагает все буквы довольно далеко от их позиций и использует колебательное движение, рассмотренное в первой лекции, для перемещения каждой буквы на свое место. Второй файл - useCharPosScaleTo.fla - представляет каждую букву в большем размере и на большем расстоянии от ее места, постепенно уменьшая и перемещая буквы на их места. Третий файл - useCharPosScaleTo2.fla - работает по такому же принципу, но обрабатывает буквы по порядку, а не случайным образом.

     

     


     

     
 

Улучшение интерфейса навигации для изображений

Теперь мы будем заново прорабатывать пример, рассмотренный в лекции 1, но используем другие фотографии. На этот раз мы сделаем пример более динамичным. Нам не придется вручную размещать все фотографии. Мы также добавим текстовый эффект, который будет начинать действовать при перемещении фотографии на свое место. Несмотря на то, что это новый файл, мы будем использовать часть кода из прежнего упражнения.

 

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

 

Динамическое позиционирование изображений и добавление текстовых эффектов

  1. Импортируйте все изображения (pic1.jpeg - pic8.jpeg с компакт-диска) и разместите их в фильмах. Назовите их 'pic1' - 'pic8' и в диалоговом окне Linkage настройте экспорт для ActionScript. Используя имена 'pic1' - 'pic8', установите точку закрепления на левый верхний угол.
  2. Теперь на главном рабочем месте мы установим несколько основных переменных для фильма. Они будут представлять собой информацию о размере фильма и размере изображений. Мы будем использовать эти данные для центрирования изображений на рабочем месте.
    stageWidth=550;
    stageHeight=400;
    imageWidth=410;
    imageHeight=308;
    speed=3;

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

     
  3. При помощи переменных stageWidth и stageHeight можно выяснить, где должна располагаться картинка, чтобы оказаться по центру рабочего места. Если фильмы выровнены по центру, можно вычислить левую сторону картинки, вычтя ширину картинки из ширины рабочего места и затем разделив на два. stageWidth минус imageWidth даст нам расстояние до другой стороны изображения. Разделив этот результат на два, получим левую позицию.
    topPos= (stageHeight-imageHeight)/2;
    leftPos= (stageWidth-imageWidth)/2;
  4. Мы собираемся расположить изображение по центру рабочего места, а также добавить строку текстовых кнопок под картинкой. Нам нужны объекты textFormat для кнопок и для текстового эффекта, который будет располагаться вверху картинки.
    buttonTextFormat=new TextFormat ("_sans", 9, 0x87A7E2, true);
    captionTextFormat=newTextFormat ("Arial", 30, 0xffffff, true);
  5. Применим шрифт Arial, но не sans. Для этого поместите текстовое поле вне рабочего места, установите шрифт на Arial, настройте его на динамический текст и добавьте все символы, как мы это делали ранее. Убедитесь, что отмечен параметр жирности шрифта, как указано в объекте TextFormat. Вы можете выбрать любой шрифт, я указал Arial просто потому, что он имеется у всех пользователей.
  6. Далее мы определим массив, содержащий идентификаторы ссылок изображений, которые мы будем добавлять, и название, которое будет присвоено каждому из них. Мы создадим каждый элемент массива в виде объекта, имеющего два параметра - ссылку и название.
    images=[{link:"picl",title:"MAY 15 2002"},
        {link:"pic2",title:"MARCH 12 2002"},
        {link:"pic3",title:"JANUARY 23 2002"},
        {link:"pic4",title:"APRIL 30 2001"},
        {link:"pic5",title:"JUNE 07 2002"},
        {link:"pic6",title:"JULY 12 2002"},
        {link:"pic7",title:"AUGUST 25 2002"},
        {link:"pic8",title:"DECEMBER 01 2002"}
    ]

    Для расположения рисунков на рабочем месте нам нужно создать функцию. Как и в примере лекции 1, мы поместим каждый рисунок внутрь фильма для скольжения на нужные позиции. Прежде всего, в функции необходимо создать пустой фильм "imageHolder", координаты которого leftPos и topPos вычислены ранее. Теперь, чтобы добавить картинки, мы проходим циклически через наш массив рисунков и используем параметр ссылки для выбора нужных фильмов из библиотеки. Мы поместим ссылку на только что созданный фильм в нашем массиве рисунков в виде дополнительного параметра "mov", чтобы иметь всю необходимую информацию в центральном реестре. При добавлении каждого фильма мы будем увеличивать переменную currx на значение imageWidth. Это значение будет использоваться для установки позиции по оси X для каждого фильма, чтобы они были расположены впритык друг к другу.

     
    function populatelmages(imageArr,imageWid){
      _root.createEmptyMovieClip("imageHolder",++this.depth)
      imageHolder._x=leftpos;
      imageHolder._y=topPos;
      var currx=0;
      for(var i=0,-i<imageArr.length;i++) {
        imageHolder.depth++;
        //attach image movieclip at currx
        imageArr[i].mov=imageHolder.attachMovie(imageArr[i].link,
        К"image"+i,imageHolder.depth,{_x:currx,_alpha:102});
        //increase currx
        currx+=imageWidth;
      }
    }

    Мы использовали возможность передавать значения с attachMovie для установки позиции фильма по оси X и alpha.

     
    imageArr[i].mov=imageHolder.attachMovie(imageArr[i].link,
    К"image"+i,imageHolder.depth,{_x:currx,_alpha:102})

    Мы установили alpha, равное 102, во избежание дерганья изображения, которое может возникать во Flash во время перемещения картинок. Я не понимаю, как это срабатывает, но, тем не менее, это так. Вы можете попытаться исключить эти строки, когда мы закончим, и понять разницу. Если вы запустите код сейчас, то вы увидите по крайней мере два фильма, стоящие на рабочем месте один за другим.

     
 
  1. Теперь создадим кнопки.
    function createButtons(imageArr,tF){
      _root.createEmptyMovieClip("buttonHolder",++this.depth)
      buttonHolder._x=leftPos+10;
      buttonHolder._y=topPos+imageHeight+5;
      var currx;
      for(var i=0;i<images.length;i++){
        // attach empty movieclip for button to sit in
        var nooButton=buttonHolder.createEmptyMovieClip ("button"+i,i) ;
        // place button at currx
        nooButton._x=currx;
        nooButton.item=imageArr[i];
        nooButton.createTextField("texta",1,0,0,1,1);
        nooButton.texta.autoSize=true;
        var caption = i>9 ? i+1 :"0"+(i+1);
        nooButton.texta.text=caption;
        nooButton.texta.setTextFormat(tF);
        nooButton.onPress=function(){
          _root.centerPic(this.item)
        }
        currx+=nooButton.texta.textWidth+5
      }
    }

    Создадим другой пустой фильм "buttonHolder", который будет содержать все кнопки. Расположим этот фильм справа от левого края рисунков и значительно ниже нижнего края изображений (topPos+imageHeight).

     
    _root.createEmptyMovieClip("buttonHolder",++this.depth);
    buttonHolder._x=leftPos+10;
    buttonHolder._y=topPos+imageHeight+5;

    Далее мы повторно проходим массив с помощью цикла, добавляя кнопку для каждого его элемента, т.е. одну кнопку для каждого изображения. Внутри каждой кнопки создаем переменную "item", предназначенную для записи ссылки на элемент в массиве рисунков, к которому он относится. Это можно использовать для получения доступа к другой информации о картинке, например о фильме, который представляет данный рисунок. Далее добавляем textField в каждую переменную с помощью объекта textFormat, только что созданного нами. Мы используем значение i для установки текста в TextField. Если значение i меньше, чем один символ, добавляем 0 впереди него. Хотя в данный момент это не относится к делу (у нас только 8 картинок), в дальнейшем можно применить это следующим образом.

     
    var caption = i>9 ? i+1 :"0"+ (i+1);
    nooButton.texta.text=caption;

    Мы настраиваем функцию onPress для кнопки, чтобы вызывать функцию centerPic, передавая переменную "item", созданную нами ранее. Эта функция и будет перемещать изображения.

     
    nooButton.onPress=function(){
      _root.centerPic(this.item)
    }

    Теперь обеспечим правильное позиционирование, увеличивая значение текущей позиции по оси X на сумму ширины TextField и небольшого дополнительного места для уверенности.

     
  2. Теперь нам нужно реализовать движение. Мы будем использовать для этого созданную ранее функцию slideTo.
    MovieClip.prototype.slideTo=
      function(x,y,speed,callbackObj, callbackFunc) {
      if(this.slideControl){
        var noo=this.slideControl
      }else{
        var noo=this.createEmptyMovieClip ("slideControl",++this.depth)
      }
      noo.tx=x;
      noo.ty=y;
      noo.speed=speed;
      noo.callBackObj =callBackObj;
      noo.callBackFunc=callBackFunc;
      noo.onEnterFrame=function(){
        this._parent._x+=(this.tx-this._parent._x)/this.speed;
        this._parent._y+=(this.ty-this._parent._y)/this.speed;
        if(Math.abs(this.tx-this._parent._x)<0.2
         && Math.abs(this.ty-this._parent._y)<0.2){
          this._parent._x=this.tx;
          this._parent._y=this.ty;
          this.callBackObj[this.callBackFunc](this._parent)
          this.removeMovieClip ()
        }
      }
    }

  3. Далее добавляем функцию для инициализации процесса - centerPic.
    function centerPic(item){
      // if the picture is not already centered
      if(item!=_root.currentPicture){
        _root. currentPicture =item,-
        var mov=item.mov;
        var x=leftPos-mov._x;
        var y=imageHolder._y;
        imageHolder.slideTo(x,y,speed,this,"triggerText");
        clearText();
      }
    }

    В этой функции нам необходимо проверять, выровнена ли картинка по центру. Результат этой проверки записывается в переменную _root.currentPicture. Если это не так, берем значение _root.currentPicture и начинаем перемещать объект. Мы извлекаем фильм из переданного элемента (это была запись в массиве изображений, поэтому используем параметр mov). Затем выясняем позицию, на которую должен переместиться imageHolder, как мы делали это ранее (leftPos минус позиция фильма по оси X) и вызываем функцию slideTo для перемещения на эту позицию. При вызове функции slideTo мы передаем ей функцию "triggerText", которая инициализирует текстовый эффект по достижении фильмом конечной точки. Наконец, нам нужно удалить любой уже присутствующий текст. Для этого в конце программы вызываем функцию clearText.

     
  4. Запустив код, вы увидите, что изображения позиционируются корректно. Далее нам необходимо создать маску для сокрытия рисунков, расположенных вокруг выбранной фотографии. Это можно сделать посредством рисования api, но сейчас мы будем использовать фильм из библиотеки. Создайте новый фильм, установите параметр связывания на значение "square" и внутри него нарисуйте квадрат 100x100 пикселей с точкой закрепления в левом верхнем углу.
  5. Затем добавьте следующий код.
    function createMask(targ,x,y,wid,high){
    // create init object containing values for scale and //position
      var obj={_x:x,_y:y,_xscale:wid,_yscale:high};
      _root. attachMovie ("square","maska",++depth,obj );
      targ.setMask(maska);
    }

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

     
  6. Теперь рассмотрим элемент текстового эффекта. Прежде всего, мы считаем символы и позиции символов из каждой картинки. Далее проходим циклом наш массив изображений и вызываем функцию charPositions для каждого элемента, сохраняя результаты в виде characterArr внутри каждого объекта изображения.
    function setCharPositions(imageArr,tF){
      for(var i in imageArr){
        imageArr[i].characterArr=
         charPositions (tf,imageArr[i].title,10000)
      }
    }
  7. Функция charPositions была значительно изменена с тех пор, как мы имели с ней дело ранее. Я выделил те ее части, которые были изменены. В ней есть два основных отличия от прежней версии. Во-первых, функция использует textWidth и textHeight объекта TextField для выяснения места расположения всего фрагмента текста. Оно добавляется к координатам X и Y в виде смещения. Во-вторых, теперь возвращаемый функцией массив содержит объекты, у каждого из которых есть параметры для координат X и Y, а также релевантный символ.
    function charPositions(tFormat,str,depth){
      _root.createTextField("temp",depth,0,-300,100,400);
      temp.autoSize=true;
      temp.embedFonts=true;
      temp.setNewTextFormat(tFormat);
      temp.text=str;
      var arr= [];
      var totalWidth= temp. textwidth;
      var leftEdge=(stageWidth-totalWidth)/2;
      var height=temp.textHeight;
      var topEdge=(stageHeight-height)/2;
      for(var i=0;i<str.length;i++){
        temp.text=str.substr(i);
        var xp=totalWidth-temp.textwidth;
        arr[i]={x:xp+leftEdge,y:topEdge,char:str.charAt(i)};
      }
      return arr;
    }

  8. Теперь у нас есть дополнительная запись для каждого изображения в нашем массиве изображений. Далее нам нужно создать функцию triggerText для позиционирования букв. Вам уже знакомо, как это делается, из прошлого материала. Случайным образом выбирается символ из заголовка и применяется плавное увеличение интенсивности отображения. В коде ниже выделены некоторые строки, на которые следует обратить внимание.
    function triggerText(){
      depth++
      latestText=_root.createEmptyMovieClip ("textHolder"+depth, depth) ;
      latestText.characters=currentPicture.characterArr.slice();
      latestText.movs=[];
      latestText.onEnterFrame=function(){
        this.count++;
        var next=Math.floor(Math.random()* this.characters.length);
        var nextObj=this.characters[next];
        this.characters.splice(next,1);
        var noo=this.createEmptyMovieClip ("lett"+this.count,this.count);
        noo._x=nextObj.x;
        noo._y=nextObj.y;
        noo._alpha=30;
        noo.onEnterFrame=function(){
          this._alpha+=5;
          if(this._alpha>=100){
            delete this.onEnterFrame
          }
        }
        noo.createTextField("tex",1,0,0,100,100);
        noo.tex.text=nextObj.char;
        noo.tex.embedFonts=true;
        noo.tex.selectable=false;
        noo.tex.setTextFormat(_root.captionTextFormat);
          this.movs.push(noo);
          if(this.characters.length==0){
            delete this.onEnterFrame;
            return;
          }
        }
        latestText.remove=function(){
          var next=Math.floor(Math.random()*this.movs.length);
          this.movs [next] .removeMovieClip();
          this.movs.splice(next, 1);
          if(this.movs.length==0){
          this.removeMovieClip();
        }
      }
    }

    Пример 2.2.

    Следует заметить, что мы создали отдельный фильм для текстового эффекта. Он выступает как в роли главного фильма, содержащего отдельные фильмы для букв внутри себя, так и в роли управляющего фильма, т.к. буквы сначала создаются, а затем опять удаляются при переключении фотографий. Последний фильм textHolder хранится в переменной latestText. При переключении фотографий текст в latestText будет удаляться. При создании основного фильма нужно знать, какими являются все символы и в каком месте они должны быть размещены. Для получения этой информации мы используем массив символов текущей картинки. Так как мы собираемся удалять элементы этого массива, мы создаем копию массива с помощью slice в фильме, не трогая оригинал. Метод slice используется, в основном, для возврата элементов из массива между двумя точками, так, например, arr.slice (2,5) возвратит копию элементов массива с 2 по 5. При вызове его без аргументов будет возвращена копия всего массива.

     
    latestText.characters=currentPicture.characterArr.slice ()
  9. Последняя часть функции определяет функцию "remove" как onEnterFrame для удаления всех букв из фильма и затем самой себя по окончании данной операции. Для этого мы добавляем функцию clearText, которая и будет обеспечивать эту возможность:
    function clearText(){
      _root.latestText.onEnterFrame=_root.latestText.remove
    }
  10. Добавим строки кода, вызывающие определенные нами функции, для размещения изображений на рабочем месте, создания кнопок, вычисления позиций символов, создания маски и выравнивания по центру первого изображения.
    populatelmages(images,imageWidth);
    createButtons(images,buttonTextFormat);
    setCharPositions(images,captionTextFormat);
    createMask(imageHolder,leftPos,topPos,imageWidth,imageHeight);
    centerPic(images[0]);

Мы завершили создание расширенного интерфейса изображений. Сохраните его и запустите - все должно работать безупречно.

 

 


 

 

источник: http://www.INTUIT.ru


 

13 центов(0,13$) за клик, выплаты через WebMoney каждый вторник +10% с рефералов

Мы выкупаем 100% трафа! $12 за 1000 хостов (РФ), и до $4 за 1000 хостов (зарубежный траф) + 10% с дохода Ваших рефералов!
 Выплаты через
WebMoney

~80-100$ за1000 хостов 2.5$ за 1 смс.
реф. процент - 10 %Выплаты происходят раз в неделю, в четверг на
WebMoney
 
 

 

____________________________

Посмотреть порно видео в онлайне »

_______________________________

 

   
   
Сайт управляется системой uCoz