Опубликован: 07.11.2006 | Уровень: специалист | Доступ: платный
Лекция 10:

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

  1. Чтобы colorStop работал в качестве расширения объекта MovieClip, нам нужно сделать некоторые дополнения. Введите следующие строки кода.
    Object.registerClass("colorStopSymbol", ColorStop);
    makeColorStop = function (x, col) {
      well.attachMovie("colorStopSymbol", "h"+well.stopDepth,
      Кwell.stopDepth,{_x:x, _y:well.h, stopColor:col});
    };

    Object.registerClass позволяет нам ассоциировать символ, хранимый в Library, с новым определением класса. Вспомните о символе пустого фильма в Library, который мы создали в начале этого проекта. Его идентификатор Linkage является первым параметром метода registerClass. Вторым параметром является имя самого класса. Теперь, каждый раз при добавлении одного их этих фильмов на рабочее место, он будет автоматически становиться инстансом ColorStop Class!

    Функция makeColorStop вызывается каждый раз при щелчке на кнопке цвета нашей области (сейчас вы увидите этот процесс). Необходима всего лишь одна строка кода, которая добавляет наш пустой фильм на рабочее место и присваивает ему начальные параметры. Все остальное сделает определение нашего класса! Разумеется, чтобы позволить colorStop наследовать параметры и методы объекта MovieClip, нам нужно установить параметр prototype объекта colorStop на значение нового фильма. После этого мы регистрируем наш класс с именем Object, присваивая ему Linkage ID нашего символа в Library (colorStopSymbol).

    Мы проделали половину работы.

  2. Следующая часть программы работает с ползунками, которые, опять-таки, создаются целиком с помощью рисования API. Введите следующий код под всем уже имеющимся кодом программы.
    createSlider = function (instance, label, depth, x, y, height, width,  func) {
      this[instance] = gp.createEmptyMovieClip(instance+depth, depth);   
      var slider = this[instance];
      slider._x = x;
      slider._y = y;
      slider.createTextField("label", 0, -20, 0, 10, 10);
      slider.label.autoSize = "right";
      slider.label.text = label;
      slider.label.textColor = 0xFFFFFF;
      slider.label.bold = 1;
      slider.lineStyle(2, 0, 100);
      slider.moveTo(0, height/2);
      slider.lineTo(width, height/2);
      var s = slider.createEmptyMovieClip("slider", 10);
      s.lineStyle(1, 0, 100);
      s.moveTo(-height/4, 0);
      s.beginFill(OxCCCCCC, 100);
      s.lineTo(height/4, 0);
      s.lineTo(height/4, height);
      s.lineTo(-height/4, height);
      s.endFill();
      s.onPress = function() {
        this.startDrag(0, 0, 0, width, 0);
        this .onMouseMove = func;
      };
      s.range = width;
      var releaseMe = function () {
        delete this.onMouseMove;
        stopDrag();
      };
      s.onRelease = s.onReleaseOutside=releaseMe; 
      slider.getValue = function() { 
        return s._x/s.range;
      };
      slider.setValue = function(val) {
        s._x = val/100 *s. range; 
      }; 
    };
    Пример 9.3.

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

    Ползунок сам по себе является новым фильмом, так как нам необходимо перетаскивать его и проверять его параметр _x. Первый блок кода API просто рисует прямоугольник. Высота прямоугольника определяется переменной height. Его ширина будет равна половине высоты. После этого устанавливается его событие onPress для горизонтального перетаскивания.

    Функция, присваиваемая нами событию onMouseMove, отсылается в начальном вызове функции, что позволяет иметь различные ползунки с отдельными функциями. Говоря о методах, используемых в момент отпускания кнопки мыши, нужно иметь в виду два конечных метода, которые устанавливают и получают значение ползунка (в остальном здесь все то же самое). getValue, как и метод ColorStop.getValue, созданный нами выше, возвращает позицию _x ползунка в виде процентного значения от полной ширины ползунка. setValue просто обращает это значение, располагая ползунок на определенной позиции шкалы ползунка.

  3. Ниже приведены последние функции для наших ползунков.
    getSliderValues = function () {
      var r = redSlider.getValue() *255; 
      var g = greenSlider.getValue()*255; 
      var b = blueSlider.getValue()*255; 
      return  r << 16 | g  << 8 | b;
    };
    setSliderValues = function () {
      var hex = well.selected.stopColor.toString(16);
      while (hex.length<6) { 
        hex = "0"+hex;
      }
      var r = parselnt(hex.substr(0, 2), 16); 
      var g = parselnt(hex.substr(2, 2), 16); 
      var b = parselnt(hex.substr(4, 2), 16); 
      redSlider.setValue(r/2.55); 
      greenSlider.setValue(g/2.55); 
      blueSlider.setValue(b/2.55); 
      swatch.drawSolid();
    };

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

    Сдвиг разряда, являясь довольно сложной процедурой, передвигает наши значения на корректные позиции для складывания по десятичной системе с целью получения значений цвета. Например, десятичное значение для желтого цвета - 16776960, а его шестнадцатеричным эквивалентом является FFFF00. Шестнадцатеричное значение разбивается на три отдельных цветовых канала, и в итоге получаем 255(FF), 255 и 0 для красного, зеленого и синего цветов, соответственно. Как вернуться от этих значений к десятичному значению для всех трех каналов? Можно использовать оператор побитного сдвига влево для сдвига значений на их корректные позиции. Оператор побитного сдвига влево, который гораздо более полезен при работе с двоичной системой, умножает число на указанную степень числа 2. 255<<16 умножает 255 на 2 в степени 16, что нам и нужно для сдвига значения красного цвета для нашего шестнадцатеричного числа. Если вы введете эту операцию в калькулятор, то результатом будет число 16711680. Далее мы выполняем то же действие с зеленым значением, но умножаем его на 2 в степени 8 и получаем 65280. Нам не нужно осуществлять сдвиг значения синего цвета. Побитовый OR-оператор | складывает эти числа (это упрощенное объяснение, однако оно подходит в нашем случае). После сдвига нашими значениями 255, 255, 0 будут, соответственно, 16711680, 65280 и 0.

    Вернемся к нашей программе.

    setSliderValues выполняет обратное действие getSliderValues при каждом выборе colorStop (после чего образец цвета отображает цвет colorStop ). Сначала эта функция выясняет значение цвета выбранного colorStop, затем оно преобразуется в шестнадцатеричное значение, с добавлением дополнительных нулей до строки размером в шесть символов. Затем она отделяет каждый компонент цвета и устанавливает нужным образом соответствующие ползунки. Мы создавали точно такую же функцию в упражнении с превращением фрукта.

    Приближаемся к завершению программы!

  4. Следующий фрагмент кода просто создает все необходимые ползунки. Вспомним аргументы createSlider: (instanceName, labelText, depth, _x, _y, height, width, functionToBePerformed). Введите этот код под всеми предшествующими строками.
    createSlider("rotSlider", "rotation", 
     200, 200, 40, 20, 175, colorSample);
    createSlider("wSlider", "width", 
     201, 200, 70, 20, 175, colorSample);
    wSlider.setValue(100);
    createSlider("hSlider", "height", 
     202, 200, 100, 20, 175, colorSample);
    hSlider.setValue(100);
    createSlider("redSlider", "red", 
     203, 60, 200, 20, 200, colorSwatch);
    createSlider("greenSlider", "green", 
     204, 60, 235, 20, 200, colorSwatch);
    createSlider("blueSlider", "blue", 
     205, 60, 270, 20, 200, colorSwatch);

    Здесь мы вызываем функцию createSlider и отправляем необходимые параметры. В идеале, эти значения менялись бы посредством изменения начальных переменных paletteWidth и paletteHeight, расположенных в верхней части кода, но это бы требовало еще большего количества кода! Оставляю это на ваше усмотрение - если хотите, можете попробовать реализовать эту возможность.

  5. Осталось всего два фрагмента кода. Надо создать рисунки для всех наших функций. Введите следующий код.
    well = gp.createEmptyMovieClip ("well", 5);
    well._x = 10;
    well._y = 140;
    well.w = 380;
    well.h = 30;
    well .colorStops = [];
    well.stopDepth = 0;
    makeColorStop(0, 0xFFFFFF);
    makeColorStop(well.w, 0x000000);
    stopMaker = gp.createEmptyMovieClip("stopMaker", 0);
    stopMaker._x = well._x;
    stopMaker._y = well._y+well. h;
    stopMaker.onPress = function() {
      makeColorStop(this._xmouse, getSliderValues());
    };
    stopMaker.beginFill(0, 0); 
    stopMaker.lineTo(well.w, 0); 
    stopMaker.lineTo(well.w, well.h); 
    stopMaker.lineTo(0, well.h); 
    stopMaker.endFill();

    well будет областью градиента, и на ней мы устанавливаем два начальных объекта colorStops. stopMaker - это невидимая кнопка, которая будет находиться под well. Щелчок на ней будет создавать colorStops. Необходимо отделить эту функциональность от самой области, так как colorStops будут иметь свои собственные события onPress, и нам не нужно, чтобы они игнорировались из-за этой невидимой кнопки (по той же причине мы устанавливаем глубину stopMaker под глубиной well ).

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

  6. Это последняя часть кода программы.
    sample = gp.createEmptyMovieClip("sample", 10);
    sample._x = 10;
    sample._y = 10;
    sample.w = 120;
    sample.h = 120;
    swatch = gp.createEmptyMovieClip("swatch", 15);
    swatch._x = 290;
    swatch._y = 205;
    swatch.w = 80;
    swatch.h = 80;
    gradType = gp.attachMovie("FCoraboBoxSymbol", "gradType", 20);
    gradType._x = 250;
    gradType._y = 10;
    gradType.width = 130;
    gradType.addItem("linear");
    gradType.addItem("radial");
    gradType.setChangeHandler("changeGrad",this);
    sample.matrix = imatrixType:"box", x:0, y:0, 
     w:sample.w, h:sample.h, r:0};
    well.matrix = {matrixType:"box", x:0, y:0, 
     wrwell.w, h:well.h, r:0};
    sample.drawGrad = drawGrad;
    well.drawGrad = drawGrad;
    swatch.drawSolid = drawSolid;
    swatch.drawSolid();
    setGrad();

    Здесь, наконец, появляются фильмы, на которые мы ссылались на протяжении всего кода! sample и swatch предназначены для совместной работы с well, в результате которой мы получаем воистину впечатляющий результат. gradType - это наше поле ComboBox (Macromedia выполнила эту работу за вас!), в которое мы добавляем наши строковые значения градиента. Функция changeGrad выполняется каждый раз при щелчке мышью на ComboBox.

    После установки исходных матриц для градиентов, присваиваем им их методы drawGrad и вызываем методы рисования для всех образцов ( setGrad вызывает как sample.drawGrad, так и well.drawGrad() ).

  7. Вот и все! Запустите ваш фильм и проверьте работу палитры. Мы получили полнофункциональную палитру с практически пустой библиотекой Library. Согласитесь, рисование API - это очень удобно!

Игорь Хан
Игорь Хан

у меня аналогичная ситуация. Однако, если взять пример из приложения (ball_motion_04_click for trial.fla) то след остается. при этом заметил, что в моем проекте в поле "One item in library" виден кружок, в то время как в приложенном примере такого кружка нет.

Вопрос знатокам, что не так?

Александр Коргапольцев
Александр Коргапольцев

объект созданый мной упорно не желает оставлять след(единственное что добился, так это то что шарик резво гоняется за курсором) функция duplicateMovieClip остаётся не активной, т.е. следа от объекта не остаётся, но если я тоже самый код вбиваю в учебный файл всё работает, не могу понять где я ошибаюсь и почему в документе созданном заново, не работает код начиная от функции duplicateMovieClip? 

Наталья Алмаева
Наталья Алмаева
Россия
Светлана Казьмина
Светлана Казьмина
Россия, Волгодонск