Тема 14. Рисование из программы


  1. Введение
  2. Отрезки
  3. Заливки
  4. Кривые
  5. Проект
  6. Текстовое поле
  7. Кнопки
  8. Практикум

1. Введение

При создании Flash-роликов можно рисовать практически все из программы, используя специальный набор команд (интерфейс), который называется Drawing API. Он включает 8 функций, которые являются методами клипа (MovieCLip): Функции, у которых в списке параметров стоит многоточие, будут подробно изучаться далее.
к началу К началу страницы

2. Отрезки

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

Для рисования отрезков и ломаных нужно установить параметры линии с помощью метода lineStyle. Чаще всего она вызывается с тремя параметрами:

lineStyle(толщина,цвет,alpha);
Толщина линии задается в пикселях, цвет — как целое число в формате RGB (в шестнадцатеричной системе — 0xRRGGBB), параметр alpha определяет непрозрачность (от 0 до 100). В справочной системе можно прочитать об остальных параметрах, которые позволяют изменять все свойства линии, доступные через панель Properties.
  Создайте новый Flash-документ и сохраните его в папке PRACTICE\14 под именем draw.fla. Установите размер поля 400 на 400 пикселей. Добавьте к первому кадру код, рисующий треугольник с синей непрозрачной границей толщиной 1 пиксель:
 lineStyle (1, 0xFF, 100);
 moveTo (20, 100);
 lineTo (170, 20);
 lineTo (170, 180);
 lineTo (20, 100);
В данном случае мы рисуем на главном монтажном столе _root, поэтому не указывали имя клипа. Проверьте результат.
к началу К началу страницы

3. Заливки

Одноцветная заливка

Для создания заливки используются методы beginFill (начать заливку) и endFill (завершить заливку). Между ними нужно добавить команды, рисующие контур фигуры.

Метод beginFill имеет два параметра (цвет и непрозрачность):

beginFill (цвет, alpha);
Метод endFill вызывается без параметров.
  Добавьте к кадру 1 код, рисующий еще один треугольник с зеленым контуром толщиной 5 пикселей и заливкой красного цвета:
 lineStyle (5, 0xFF00, 100);
 beginFill (0xFF0000, 100);
 moveTo (360, 100);
 lineTo (190, 20);
 lineTo (190, 180);
 lineTo (360, 100);
 endFill ();

Добавление методов к MovieClip

Далее мы будем рисовать прямоугольники. Для удобства добавим к прототипу класса MovieClip новый метод rectangle и сохраним его в отдельном файла с расширением .AS. Такие файлы можно подключать к программе, используя директиву
#include "имя файла"
  Создайте новый файл типа ActionScript File, запишите в него код
 MovieClip.prototype.rectangle = function ( x1, y1, x2, y2) {
   with  ( this ) {
     moveTo ( x1, y1 );
     lineTo ( x2, y1 );
     lineTo ( x2, y2 );
     lineTo ( x1, y2 );
     lineTo ( x1, y1 );
   }
 }
Сохраните файл под именем figures.as в той же папке, что и SWF-файл.
Здесь блок with(this){...} служит для того, чтобы не писать this.moveTo(...) и this.lineTo(...).
  Добавьте в самое начало кода, связанного с кадром 1, строчку
 #include "figures.as"
Создадм (с помощью метода createEmptyMovieClip) новый клип-квадрат с именем sq1.
  Добавьте в конец кода кадра 1 строчки:
 createEmptyMovieClip ("sq1", 1);
 with ( sq1 ) {
   _x = 20;
   _y = 200;
   lineStyle (1, 0, 0);
   rectangle (0, 0, 150, 150);
 }
Наша следующая задача — залить его градиентной заливкой с переходом от синего к зеленому цвету.

Градиентная заливка

Для создания градиентной заливки надо описать в виде массивов все используемые цвета (массив colors), их непрозрачность (массив alpha) и положение движков на панели Colors (массив pos), соответствующее этой заливке:

Таким образом, массивы можно задать так:

color = [0xFF,0xCC00];
alpha  = [100, 100];
pos = [0, 255];
Оба цвета полностью непрозрачны, движки находятся на концах линейки, имеющей деления от 0 до 255.

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

matrix = { matrixType:"box", x:0, y:0, w:150, h:150,
           r:45*Math.PI/180 };
Объект matrix имеет 6 полей (свойств): Когда все эти данных готовы, можно вызывать функцию beginGradientFill:
beginGradientFill("linear", color, alpha, pos, matrix);
Первый параметр определяет тип градиента:
  Добавьте перед вызовом метода rectangle код:
 color = [0xFF,0xCC00];
 alpha  = [100, 100];
 pos = [0, 255];
 matrix = { matrixType:"box", x:0, y:0, w:150, h:150,
            r:45*Math.PI/180 };
 beginGradientFill ("linear", color, alpha, pos, matrix);
а после него:
 endFill();
Теперь создадим второй квадрат и используем для него радиальную заливку из трех цветов: Желтый движок расположим в середине линейки, поэтому его позиция равна 127.
  Добавьте в конец программы код
 createEmptyMovieClip ("sq2", 2);
 with ( sq2 ) {
   _x = 190;
   _y = 200;
   color = [0xFF0000, 0xFFFF00, 0xFF];
   alpha  = [100, 75,  50];
   pos = [0, 127, 255];
   matrix = { matrixType:"box", x:0, y:0, w:150, h:150, r:0 };
 }
Мы задали все характеристики градиента, но не нарисовали сам квадрат. Поскольку нужно сделать так, чтобы квадрат вращался, и градиент перемещается при вращении, мы будем рисовать в обработчике enterFrame. Перед рисованием нужно очистить поле, вызвав метод clear.

При переходе к следующему кадру угол поворота квадрата относительно точки (0,0) будет увеличивается на 1°. Кроме того, координаты левого верхнего угла градиента также будут смещаться по закону

matrix.x = _rotation / 2;
matrix.y = _rotation / 2;
  Добавьте в конец программы код обработчика
 sq2.onEnterFrame = function() {
   with ( this ) {
     clear();
     _rotation += 1;
     matrix.x = _rotation / 2;
     matrix.y = _rotation / 2;
     beginGradientFill("radial", color, alpha, pos, matrix);
     rectangle(0, 0, 150, 150);
     endFill();
   }
 }
Проверьте работу фильма.
к началу К началу страницы

4. Кривые

Для рисования кривых из текущей активной точки вместо lineTo используется метод
curveTo ( x2, y2, x3, y3);
Здесь (x2,y2) — координаты второй точки, в которую уходит касательная из активной точки, а (x3,y3) — координаты третьей точки, в которую фактически приходит линия. Эту ситуацию иллюстрирует рисунок ниже (все точки можно перетаскивать мышью).

С помощью таких команд можно строить овалы и окружности. Если нарисовать овал с помощью инструмента и выделить ее инструментом (Subselection), вы увидите, что фигура строится с помощью 8 узловых точек. Не вдаваясь в утомительные вычисления, запишем добавим к прототипу MovieClp ее два метода: oval (овал) и circle (окружность).

  Добавьте в конец файла figures.as код двух методов:
 MovieClip.prototype.circle = function (x, y, r) {
   this.oval ( x, y, r, r );
 }
 MovieClip.prototype.oval = function (x, y, w, h) {
   with ( this ) {
     moveTo ( x+w, y );
     curveTo ( x+w, y+0.4142*h, x+0.7071*w, y+0.7071*h );
     curveTo ( x+0.4142*w, y+h, x, y+h);
     curveTo ( x-0.4142*w, y+h, x-0.7071*w, y+0.7071*h );
     curveTo ( x-w, y+0.4142*h, x-w, y );
     curveTo ( x-w, y-0.4142*h, x-0.7071*w, y-0.7071*h );
     curveTo ( x-0.4142*w, y-h, x, y-h );
     curveTo ( x+0.4142*w, y-h, x+0.7071*w, y-0.7071*h );
     curveTo ( x+w, y-0.4142*h, x+w, y );
   }
 }
В функции oval параметры x и y обозначают координаты центра, а w и h — длины полуосей (половина ширины и половина высоты).

В функции circle три параметра: координаты центра окружности и ее радиус.

к началу К началу страницы

5. Проект

Результат следующего упражнения показан на рисунке ниже. Щелкнув по кнопке, вы можете отправить шарик в «зеленую дыру», такой же эффект дает двойной щелчок по шарику. После этого на его месте появляется следующий шарик, его номер увеличивается. Шарик можно перетаскивать мышкой.

Квадраты

Сначала создадим фон из зеленых квадратов. Их размер изменяется от 200 до 0, причем сначала нужно рисовать большие квадраты, на которые накладываются маленькие. Это можно сделать с помощью такого цикла
N = 15;
hw = 200 / N;
w = 200;
while ( w > 0 ) {
    // здесь рисуем
  w -= hw;
}
В этом куске кода N —число квадратов, w — половина стороны квадрата, а hw — шаг изменения этой величины.

Цвет также должен изменяться от ярко-зеленого (0x00FF00) до черного (0x000000), причем не должен содержать ни красную, ни синюю составляющие. Мы будем изменять в цикле зеленую составляющую G от 255 до 0, а потом умножать ее на 0x100 для получения кода цвета в формате RGB. Учтем, что G — целое число, для округления используется функция round объекта Math:

hG = 255 / N;
G = 0xFF;
while ( w > 0 ) {
  rgb = Math.round(G) * 0x100;
    // здесь рисуем
  G -= hG;
}
Рисовать будем не на главном монтажном столе, а в новом клипе canvas (холст).
  Создайте новый Flash-документ размером 400 на 400 пикселей. Добавьте в код кадра 1 строки
 #include "figures.as"
 createEmptyMovieClip("canvas", 1);
 canvas._x = 200;
 canvas._y = 200;
 N = 200;
 hw = 200 / N;
 hG = 0xFF / N;
 w = 200;
 G = 0xFF;
 with (canvas) {
   lineStyle(1,0,0);
   while (w > 0) {
     rgb = Math.round(G) * 0x100;
     beginFill(rgb,100);
     rectangle(-w, -w, w, w);
     endFill();
     w -= hw;
     G -= hG;
   }
 }
Проверьте работу фильма
Для того, чтобы можно было использовать методы rectangle и circle, мы подключили файл figures.as. Новый клип canvas помещается в центр поля, далее устанавливается невидимая линия (с параметром alpha=0) и в цикле рисуются квадраты.

Шарик

Займемся рисованием шарика. Это будет новый клип с именем ball, расположенный в центре поля на глубине 2.
  Добавьте в код кадра 1 следующие команды:
 createEmptyMovieClip ("ball", 2);
 ball._x = 200;
 ball._y = 200;
 nomer = 1;
 drawBall();
Переменная nomer будет обозначать номер шарика, а функция drawBall, которая будет написана далее, рисует сам шарик на экране. Поскольку эта функция будет достаточно длинной, мы спрячем ее в отдельный файл ballfunc.as.
  Создайте новый файл ballfunc.as типа ActionScript File и запишите в него код функции
 function drawBall() {
   with (_root.ball) {
     clear();
     color = [0xFFFFFF, 0x990000];
     alpha = [80, 100];
     pos = [10, 245];
     matrix = {matrixType:"box", x:-75, y:-75, w:100, h:100, r:0};
     beginGradientFill("radial",color,alpha,pos,matrix);
     circle(0,0,50);
     endFill();
   }
 }
Сохраните этот и проверьте работу клипа.
Для создания объемного вида шарик заливается радиальным градиентом от белого к темно-красному.

Двойной щелчок

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

Для фиксации двойного щелчка будем использовать функцию getTimer, которая возвращает количество миллисекунд с начала работы клипа. В переменной tLast запомним время последнего щелчка, и если новый произошел менее, чем через 500 миллисекунд после предыдущего, запустим процедуру «удаления».

  Добавьте в конец кода кадра 1 строчку
 tLast = 0;
и обработчики событий
 ball.onMouseDown = function() {
   if (this.hitTest(_root._xmouse, _root._ymouse)) {
     t = getTimer();
     if (t - tLast < 500) this.vanish();
     tLast = t;
     startDrag(this);
   }
 };
 ball.onMouseUp = function() {
   stopDrag();
 };
Проверьте, как шарик перетаскивается мышкой.
Клип-шарик обрабатывает события mouseDown (нажатие клавиши мыши) и mouseUp (отпускание клавиши). Если при нажатии клавиши мышь находилась над шариком (метод hitTest вернул true), проверяем разницу между предыдущим и новым щелчком. Если она меньше 500 мс, запускается метод vanish (исчезнуть), который мы еще напишем. Кроме того, в переменной tLast запоминается время нового щелчка и разрешается перетаскивание. При отпускании мыши перетаскивание (если оно было) прекращается.

Функция vanish должна запустить процесс постепенного исчезновения шарика. Будем считать, что за 1 кадр он уменьшается в размере на 5 процентов. Для того, чтобы новый шарик установить в то же положение, запомним координаты в переменных x0 и y0.

  Добавьте к коду кадра 1 функцию
 ball.vanish = function() {
   x0 = this._x;
   y0 = this._y;
   dx = 0.05 * (200 - this._x);
   dy = 0.05 * (200 - this._y);
   this.onEnterFrame = this.moveCenter;
 }
Величины dx и dy определяют смещение шарика за 1 кадр так, чтобы через 20 кадров он пришел в центр поля, то есть в точку (200,200). В последней строчке определяется новый обработчик для события enterFrame: функция moveCenter будет вызываться при каждой смене кадра.
  В конец кода кадра 1 добавьте функцию
 ball.moveCenter = function() {
   with (this) {
     _xscale -= 5;
     _yscale -= 5;
     _x += dx;
     _y += dy;
     if (_xscale < 1) {
       _xscale = _yscale = 100;
       _x = x0;
       _y = y0;
       nomer ++;
       onEnterFrame = null;
       drawBall();
     }
   }
 }
и проверьте, что будет при двойном щелчке на шарике.
Эта функция передвигает шарик к центру на вектор (dx,dy) и уменьшает его размер на 5 процентов от первоначального. Когда масштаб становится меньше 1%, размер шарика возвращается к исходному (100%), он возвращается на прежнее место с координатами (x0,y0), номер увеличивается на 1 и шарик перерисовывается. Кроме того, в обработчик enterFrame записывается null, то есть функция moveCenter уже не будет вызываться.
к началу К началу страницы

6. Текстовое поле

К шарику нужно добавить динамическое текстовое поле, в котором будет отображаться номер. Для создания надписи используем функцию createTextField клипа ball
ball.createTextField("txt", 10, -15, -25, 30, 60 );
Первый параметр — название поля, второй — глубина, третий и четвертый — координаты левого верхнего угла относительно точки регистрации клипа, два последних — ширина и высота поля.

Поле имеет свойства, которые можно изменять. Вот некоторые из них:

Мы запишем в это поле значение переменной nomer и сделаем так, чтобы текст нельзя было выбрать мышкой, а размер поля определялся автоматически:
ball.txt.text = nomer;
ball.txt.selectable = false;
ball.txt.autoSize = true;
  Добавьте в блок with(...) в функции drawBall строчки
 txt.text = nomer;
 txt.selectable = false;
 txt.autoSize = true;
и проверьте работу клипа.
Теперь нужно научиться настраивать шрифт. Для этого применим новый объект
fmt = new TextFormat();
для которого можно установить свойства В справочной документации можно найти описание остальных свойств текста.

В нашем случае выберем шрифт Arial, размер 40 пунктов, жирный, белого цвета:

with ( fmt ) {
  font = "Arial";
  size = 40;
  color = 0xFFFFFF;
  bold = true;
}
Для того, чтобы применить формат к существующему тексту, используется метод setTextFormat:
ball.txt.setTextFormat ( fmt );
Другое метод, setNewTextFormat, делает то же самое для нового текста, который будет добавлен или изменен.
  Добавьте в блок with(...) в функции drawBall строчки
 fmt = new TextFormat();
 with ( fmt ) {
   font = "Arial";
   size = 40;
   color = 0xFFFFFF;
   bold = true;
 }
 txt.setTextFormat ( fmt );
Остается выровнять текст по центру шарика. Учитывая, что его свойство autoSize установлено в true, размер (свойства _width и _height) будет автоматически изменен при изменении шрифта. Для центровки нужно сместить координаты _x и _y на половину ширины и высоты соответственно.
  Добавьте в блок with(...) в функции drawBall строчки
 txt._x = - txt._width / 2;
 txt._y = - txt._height / 2;
и проверьте работу клипа.
к началу К началу страницы

7. Кнопки

Теперь построим кнопку полностью программным способом. Для этого нужно
  Добавьте в конец кода кадра 1 строчки
 createEmptyMovieClip("btn", 3);
 btn._x = 175;
 btn._y = 350;
 btn.w = 50;
 btn.h = 30;
 drawUp();
 btn.onRollOver = drawOver;
 btn.onRollOut = drawUp;
 btn.onPress = drawDown;
 btn.onRelease = function() {
   drawUp();
   ball.vanish();
 }
Этим кодом мы создаем клип btn на глубине 3 главного монтажного стола. Объект btn устанавливается в точку (175,350) и к нему добавляются два свойства: w (ширина кнопки) и h (высота). Обработчики onRollOver, onRollOut и onPress устанавливаются на соответствующие (еще не написанные) функции. При отпускании кнопки мыши (событие release) кнопка перерисовывается в нормальном состоянии и запускается процесс удаления шарика. Все остальное делает метод vanish.

Функции, рисующие кнопку, мы поместим в отдельный файл.

  Создайте новый файл типа ActionScript File и добавьте в него код функций:
 function drawUp()   { drawBtn("up"); }
 function drawOver() { drawBtn("over"); }
 function drawDown() { drawBtn("down"); }
 
 function drawBtn ( state ) {
   d = 0;
   col1 = 0xFFFFFF;
   col2 = 0;
   if ( state == "up" ) color = 0;
   if ( state == "over" ) color = 0xFFFFFF;
   if ( state == "down" ) {
     color = 0xFF0000;
     d = 2;
     col1 = 0;
     col2 = 0xFFFFFF;
   }
   with ( btn ) {
     clear();
     beginFill ( 0xEEEEEE, 80 );
       lineStyle(2, col1, 100 );
       moveTo(d, d+h);
       lineTo(d, d);
       lineTo(d+w, d);
       lineStyle(2, col2, 100 );
       lineTo(d+w, d+h);
       lineTo(d, d+h);
     endFill();
     lineStyle(1, 0, 0 );
     beginFill ( color, 80 );
       moveTo(d+5, d+h-10);
       lineTo(d+w/2, d+5);
       lineTo(d+w-5, d+h-10);
       lineTo(d+5, d+h-10);
     endFill();
   }
 }
и сохраните его под именем button.fla.
Все состояния кнопки рисуются с помощью одной функции drawBtn, которой передается символьная строка, определяющая нужное состояние.

Переменная d обозначает смещение кнопки от нормального положения. Она равна нулю для состояний "up" и "over" и 2 для состояния "down" (кнопка как бы сдвигается вниз и вправо).

Цвет левой и верхней границ кнопки хранится в col1, а цвет правой и нижней — в col2. Это позволяет изменять вид с «выпуклого» на «утопленный».

В блоке with(btn){...} сначала рисуется фон кнопки с рамкой нужных цветов, а затем — треугольный значок, цвет которого определяется переменной color.

  Добавьте в начало кода, связанного с кадром 1, строчку
 #include "button.as"
и проверьте работу кнопки.
к началу К началу страницы

8. Практикум

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

Сначала мы создадим новый клип, который будет полем для рисования, и зальем его белым цветом. Для рисования прямоугольника используем метод rectangle, описание которого находится в файле figures.as (этот файл нужно подключить через директиву #include).

  Откройте файл PRACTICE\14\paint.fla и создайте новый слой Программа. К кадру 1 этого слоя добавьте код:
 #include "figures.as"
 createEmptyMovieClip("canvas", 1);
 with ( canvas ) {
   _x = 84;
   _y = 32;
   beginFill(0xFFFFFF, 100);
   rectangle(0, 0, 440, 290);
   endFill();
 };

Инструменты

Кнопки панели инструментов (слева) строятся на основе клипа Инструмент из библиотеки. Этот клип содержит метки "pencil", "line", "rect" и "oval" и имеет кодовое имя toolBtn для использования в программе.
  Добавьте код создания кнопок-инструментов:
 labels = ["pencil", "line", "rect", "oval"];
 for (i=0; i<labels.length; i++) {
   attachMovie("toolBtn", labels[i], 100+i);
   obj = eval("_root." + labels[i]);
   obj._x = 20;
   obj._y = 30 + (obj._height + 10 )*i;
   obj.gotoAndStop(labels[i]);
 }
 pencil.gotoAndStop(2);
 pencil.down = true;
 canvas.tool = "pencil";
Очередная кнопка создается с помощью метода attachMovie, номера уровней начинаются со 100. Переменная obj используется для сокращения записи при обращении к новой кнопке. Верхняя кнопка имеет координаты (20,30), интервал между кнопками по вертикали — 10 пикселей.

Команда

obj.gotoAndStop(labels[i]);
направляет клип-кнопку на нужный кадр. После создания кнопок включается кнопка с инструментом Карандаш:
pencil.gotoAndStop(2);
pencil.down = true;
В поле tool объекта canvas записывается имя выбранного инструмента:
canvas.tool = "pencil";
Как же с помощью этих кнопок переключать инструмент? Оказывается, кнопки запрограммированы так, что при нажатии на них вызывается метод _root.changeTool и в параметрах этой функции передается ссылка на нажатую кнопку. Это так называемая функция обратного вызова (callback), ее нужно написать.
  Добавьте функцию для переключения инструмента
 function changeTool ( which ) {
   canvas.tool = which._name;
   for (i=0; i<labels.length; i++) {
     obj = _root[labels[i]];
     if ( obj != which ) obj.goUp();
   }
 }
Функция changeTool выполняет две основные операции: запоминает название выбранного инструмента в поле tool объекта canvas и переводит все остальные кнопки в выключенное состояние, вызывая их метод goUp.

Выбор цвета

Кнопки для выбора цвета строятся на основе клипа КнопкаЦвет из библиотеки. Этот клип имеет имя colBtn для использования в программе. Цвет кнопки определяется цветом фона — элемента, который имеет имя back.
  Добавьте код для создания цветовых кнопок:
 colors = ["0", "0xFF0000", "0xFF00", "0xFF"];
 for (i=0; i<colors.length; i++) {
   name = "color" + i;
   attachMovie("colBtn", name, 120+i);
   obj = _root[name];
   obj._x = 30 + (obj._width + 10)*i;
   obj._y = 350;
   c = new Color(obj.back);
   c.setRGB(colors[i]);
 }
 canvas.color = 0;
Кнопки создаются с помощью метода attachMovie и расставляются вдоль нижней границы с интервалом 10 пикселей. Обратите внимание, что кнопки имеют имена color0, color1 и т.д.

С помощью кода

c = new Color(obj.back);
c.setRGB(colors[i]);
мы получаем ссылку на цвет фона кнопки и изменяем его, выбирая цвет из массива colors.

Текущий цвет записывается в поле color клипа canvas (сначала это черный цвет с RGB-кодом 0).

Теперь посмотрим, как применить к кнопкам фильтр, например, Drop Shadow. Сначала нужно с помощью команды import подключить пакет для работы с фильтрами

import flash.filters.*;
Фильтр создается конструктором:
ds = new DropShadowFilter(
   5,         // distance
   45,        // angle
   0x000000,  // color
   100,       // alpha
   5,         // blurX
   5,         // blurY
   1,         // strength, 1 = 100%
   1,         // quality, 1 = Low
   false,     // inner
   false,     // knockout
   false);    // hideObject
где можно задать все параметры, которые есть на панели Filters (их названия показаны в комментариях).
  Примените фильтр Drop Shadow для цветовых кнопок. Перед циклом создайте фильтр, так, как показано выше, а в тело цикла добавьте команду
 obj.filters = [ds];
Свойство filters — это массив, в который можно добавлять несколько фильтров. Поэтому имя ds заключено в квадратные скобки.

Когда мышкой выбран некоторый цвет, кнопка вызывает функцию _root.changeColor (обратный вызов), передавая в параметре свой адрес. В этой функции нужно перевести все остальные кнопки, кроме нажатой, в состояние "normal", используя для этого метод setState.

  Добавьте код функции для изменения цвета:
 function changeColor ( which ) {
   for (i=0; i<colors.length; i++) {
     obj = _root["color"+i];
     if ( obj != which ) obj.setState("normal");
   }
   c = new Color(which.back);
   canvas.color = c.getRGB();
 }
В конце функции цвет фона кнопки (поля back) копируется в canvas.color.

Карандаш

Теперь можно «включать» инструменты. Начнем с самого простого — с инструмента Карандаш.

Нам будет нужна логическая переменная drag, которая равна true, если мы перетаскиваем мышь при нажатой кнопке, и вспомогательная функция inside, которая возвращает true, если мышь находится в пределах поля рисования canvas.

  Добавьте к кадру 1 код
 drag = false;
 function inside() {
   return canvas.hitTest(_root._xmouse, _root._ymouse);
 }
Если нажали кнопку мыши внутри поля, нужно установить нужный цвет и перевести графический курсор в эту точку с помощью метода moveTo. Кроме того, переменной drag присваивается значение true (началось перетаскивание). Эти операции выполняются в обработчике события mouseDown.
  Добавьте код обработчика
 canvas.onMouseDown = function() {
   with ( this ) {
     if ( inside() ) {
       lineStyle(1,color,100);
       moveTo(_xmouse, _ymouse);
       drag = true;
     }
   }
 }
При движении мыши проверяем, не вышла ли она за границы поля. Если идет перетаскивание и мышь находится в границах объекта canvas, рисуем отрезок в эту точку. Таким образом, линия состоит из маленьких отрезков.

При отпускании мыши нужно присвоить переменной drag значение false.

  Добавьте код обработчиков
 canvas.onMouseMove = function() {
   with ( this ) {
     if ( drag  &&  inside() ) {
       if ( tool == "pencil" )
         lineTo(_xmouse, _ymouse);
     }
   }
 }
 canvas.onMouseUp = function() {
   drag = false;
 }
и проверьте работу инструмента Карандаш.

Фигуры

При рисовании отрезков (инструмент Линия) мы хотели мы заранее видеть, как будет выглядеть отрезок, так делается во всех программах. Чтобы не испортить основной рисунок, этот вспомогательный отрезок будем рисовать на другом клипе с именем temp (temporary — временный). Клип temp разместим в том же месте, что и canvas.
  Добавьте в программу код, создающий вспомогательный клип temp:
 createEmptyMovieClip("temp", 2);
 temp._x = canvas._x;
 temp._y = canvas._y;
При нажатии кнопки мыши нужно запомнить координаты начала отрезка в переменных x1 и y1.
  Добавьте в обработчик onMouseDown (внутри условного оператора) код
 x1 = _xmouse;
 y1 = _ymouse;
При перемещении мыши запоминаем текущее положение в переменных x2 и y2. Кроме того, клип temp очищается с помощью метода clear и на нем рисуем отрезок из первой точки во вторую. Таким образом, второй конец отрезка передвигается вслед за мышью, а основной рисунок не портится.
  Добавьте в обработчик onMouseMove код
 x2 = _xmouse;
 y2 = _ymouse;
 temp.clear();
 temp.lineStyle(1,color,100);
 if (tool == "line") {
   temp.moveTo(x1,y1);
   temp.lineTo(x2, y2);
 }
Когда мышь отпущена, нужно очистить клип temp и нарисовать отрезок «начисто», уже на клипе canvas.
  Добавьте в начало обработчика onMouseUp код
 with ( this ) {
   if ( drag ) {
     temp.clear();
     if (tool == "line") lineTo(x2,y2);
   }
 }
и проверьте работу инструмента «линия».
  Самостоятельно добавьте в программу код, позволяющий рисовать прямоугольники и овалы с предварительным просмотром на клипе temp.

Значки

Осталось добавить значки в нижней части сцены. Все они строятся на основе клипа Значок, в котором есть три кадра с изображениями дома, дерева и машинки. Этот клип имеет кодовое имя icon для использования в программе.
  Добавьте в конец программы цикл, расставляющий значки в нижнем ряду:
 nIcons = 3;
 for(i=0; i<nIcons; i++) {
   name = "obj" + i;
   attachMovie ( "icon", name, 200+i );
   obj = _root[name];
   obj.gotoAndStop(i+1);
   obj._x = 270 + (obj._width + 10)*i;
   obj._y = 340;
 }
Программа внутри клипа Значок построена так, что клип можно перетаскивать, а при окончании перетаскивания вызывается функция _root.dropIcon, которую мы сейчас и напишем.
  Добавьте функцию, которая устанавливает на поле копию значка:
 function dropIcon ( name ) {
   if ( inside() ) {
     nIcons++;
     newName = "obj" + nIcons;
     duplicateMovieClip(name, newName, 200+nIcons);
     obj = _root[newName];
     obj.gotoAndStop(_root[name]._currentFrame);
     obj._xscale = obj._yscale = 150;
     obj.btn.enabled = false;
   }
   _root[name]._x = _root[name].x0;
   _root[name]._y = _root[name].y0;
 }
Если значок перетащен на поле, с помощью duplicateMovieClip создается его копия, ее масштаб увеличивается до 150%. С помощью команды
obj.gotoAndStop(_root[name]._currentFrame);
новый клип переводится на тот же кадр, что и образец. Чтобы копию уже нельзя было перетаскивать, свойству enabled внутренней невидимой кнопки btn присваивается значение false:
obj.btn.enabled = false;
Эта кнопка находится внутри клипа Значок и обрабатывает все события мыши. Если она заблокирована, перетаскивания не произойдет.

Начальное положение клипа запоминается при его создании в свойствах x0 и y0, поэтому команды

_root[name]._x = _root[name].x0;
_root[name]._y = _root[name].y0;
возвращают клип на прежнее место.

Теперь остается сделать кнопку для очистки экрана. Здесь уже не обойтись одним вызовом метода canvas.clear(), поскольку нужно еще удалить перетащенные на поле рисунки. Общее количество рисунков хранится в переменной nIcons (включая образцы), причем их имена — obj1, obj2 и т.д.

Клипы удаляются с помощью метода removeMovieClip, причем первые три (образцы) остаются на месте.

  Добавьте на сцену кнопку Корзина из библиотеки и присоедините к ней обработчик
 on (release) {
   canvas.clear();
   while ( nIcons > 3 ) {
     name = "obj" + nIcons;
     removeMovieClip(_root[name]);
     nIcons --;
   }
 }
Проверьте работу значков и Корзины.
к началу К началу страницы


Оглавление
 Объекты и классы Назад В начало Вперед ...


© 2007  К. Поляков


Сайт создан в системе uCoz