При создании Flash-роликов можно рисовать практически
все из программы, используя специальный набор команд
(интерфейс), который называется Drawing API.
Он включает 8 функций, которые являются методами
клипа (MovieCLip):
clear() очистить все элементы, нарисованные
в этом клипе из программы;
lineStyle(...) установить стиль линии
(толщину, цвет, прозрачность и т.д.);
moveTo(x,y) переместить курсор (активную точку)
в точку c координатами (x,y);
lineTo(x,y) провести отрезок
от курсора в точку (x,y); при этом курсор
перемещается в точку (x,y);
curveTo(...) нарисовать кривую;
beginFill(...) начать одноцветную заливку;
beginGradientFill(...) начать градиентную заливку;
endFill() завершить заливку.
Функции, у которых в списке параметров стоит многоточие, будут подробно
изучаться далее.
к началу
2. Отрезки
В следующем упражнении мы получим результат, показанный на рисунке.
При наведении мыши квадрат с радиальной заливкой начинает
вращаться и центр заливки перемещается. Все это сделано
из программы на ActionScript.
Для рисования отрезков и ломаных нужно установить
параметры линии с помощью метода lineStyle.
Чаще всего она вызывается с тремя параметрами:
lineStyle(толщина,цвет,alpha);
Толщина линии задается в пикселях, цвет как целое число
в формате RGB (в шестнадцатеричной системе 0xRRGGBB),
параметр alpha определяет непрозрачность (от 0 до 100).
В справочной системе можно прочитать об остальных параметрах,
которые позволяют изменять все свойства линии, доступные через панель
Properties.
Создайте новый Flash-документ и сохраните его в папке PRACTICE\14 под именем draw.fla.
Установите размер поля 400 на 400 пикселей. Добавьте к первому кадру
код, рисующий треугольник с синей непрозрачной границей толщиной
1 пиксель:
В данном случае мы рисуем на главном монтажном столе _root,
поэтому не указывали имя клипа. Проверьте результат.
к началу
3. Заливки
Одноцветная заливка
Для создания заливки используются методы
beginFill (начать заливку) и endFill
(завершить заливку). Между ними нужно добавить команды,
рисующие контур фигуры.
Метод beginFill имеет два параметра (цвет и
непрозрачность):
beginFill (цвет, alpha);
Метод endFill вызывается без параметров.
Добавьте к кадру 1 код, рисующий еще один треугольник с зеленым контуром толщиной 5 пикселей и
заливкой красного цвета:
Далее мы будем рисовать прямоугольники. Для удобства
добавим к прототипу класса MovieClip новый метод
rectangle и сохраним его в отдельном файла
с расширением .AS. Такие файлы можно подключать
к программе, используя директиву
#include"имя файла"
Создайте новый файл типа ActionScript File, запишите в него код
Наша следующая задача залить его градиентной заливкой
с переходом от синего к зеленому цвету.
Градиентная заливка
Для создания градиентной заливки надо описать в виде массивов все
используемые цвета (массив colors), их непрозрачность
(массив alpha) и положение движков
на панели Colors (массив pos), соответствующее этой заливке:
Оба цвета полностью непрозрачны, движки находятся на концах
линейки, имеющей деления от 0 до 255.
Кроме того, для построения градиента нужна матрица
специального типа, которая задает размер и положение
прямоугольника, ограничивающего область градиента, а также его
поворот. Пусть границы нашей градиентной заливки совпадают с
границами квадрата, а угол поворота равен 45°. В этом случае
матрица задается так:
Мы задали все характеристики градиента, но не нарисовали сам
квадрат. Поскольку нужно сделать так, чтобы квадрат вращался,
и градиент перемещается при вращении, мы будем рисовать
в обработчике enterFrame. Перед рисованием нужно
очистить поле, вызвав метод clear.
При переходе к следующему кадру угол поворота квадрата
относительно точки (0,0) будет увеличивается на 1°.
Кроме того, координаты левого верхнего угла градиента
также будут смещаться по закону
Для рисования кривых из текущей активной точки вместо 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.
Переменная nomer будет обозначать номер шарика,
а функция drawBall, которая будет написана далее,
рисует сам шарик на экране. Поскольку эта функция будет достаточно
длинной, мы спрячем ее в отдельный файл ballfunc.as.
Создайте новый файл ballfunc.as типа ActionScript File и запишите в него код функции
Для создания объемного вида шарик заливается радиальным градиентом
от белого к темно-красному.
Двойной щелчок
При двойном щелчке шарик должен уменьшаться в размерах
и «пропадать» в центре поля. Кроме того, мы сделаем,
чтобы шарик можно было перетаскивать мышью.
Для фиксации двойного щелчка будем использовать функцию
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.
Величины dx и dy определяют смещение
шарика за 1 кадр так, чтобы через 20 кадров он
пришел в центр поля, то есть в точку (200,200).
В последней строчке определяется новый обработчик для
события enterFrame: функция moveCenter
будет вызываться при каждой смене кадра.
и проверьте, что будет при двойном щелчке на шарике.
Эта функция передвигает шарик к центру на вектор (dx,dy)
и уменьшает его размер на 5 процентов от первоначального.
Когда масштаб становится меньше 1%, размер шарика
возвращается к исходному (100%), он возвращается на прежнее место
с координатами (x0,y0), номер увеличивается на 1
и шарик перерисовывается. Кроме того, в обработчик
enterFrame записывается null, то есть функция
moveCenter уже не будет вызываться.
к началу
6. Текстовое поле
К шарику нужно добавить динамическое текстовое поле, в котором
будет отображаться номер. Для создания надписи используем
функцию createTextField клипа ball
Первый параметр название поля, второй
глубина, третий и четвертый координаты левого верхнего
угла относительно точки регистрации клипа, два последних
ширина и высота поля.
Поле имеет свойства, которые можно изменять.
Вот некоторые из них:
type тип поля, может принимать значения
"dynamic" (динамический текст) и "input"
(поле ввода);
text символы, которые выводятся;
selectable если равно true,
текст можно выделять мышкой;
autoSize если true, размеры поля
автоматически подстраиваются под текст;
multiline если true, используется
многострочный текст;
password если true, вместо символов
выводятся звездочки.
Мы запишем в это поле значение переменной nomer и
сделаем так, чтобы текст нельзя было выбрать мышкой, а
размер поля определялся автоматически:
Теперь нужно научиться настраивать шрифт. Для этого применим
новый объект
fmt = new TextFormat();
для которого можно установить свойства
font название шрифта;
size размер шрифта в пунктах;
color цвет в формате RGB;
bold если true, то шрифт жирный;
italic если true, то курсив.
В справочной документации можно найти описание остальных свойств текста.
В нашем случае выберем шрифт 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 строчки
Этим кодом мы создаем клип 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 этого слоя
добавьте код:
Кнопки панели инструментов (слева) строятся на основе
клипа Инструмент из библиотеки. Этот клип содержит
метки "pencil", "line",
"rect" и "oval" и имеет кодовое имя
toolBtn для использования в программе.
Очередная кнопка создается с помощью метода 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.
Кнопки создаются с помощью метода attachMovie
и расставляются вдоль нижней границы с интервалом 10 пикселей.
Обратите внимание, что кнопки имеют имена color0,
color1 и т.д.
С помощью кода
c = new Color(obj.back);
c.setRGB(colors[i]);
мы получаем ссылку на цвет фона кнопки и изменяем его,
выбирая цвет из массива colors.
Текущий цвет записывается в поле color клипа
canvas (сначала это черный цвет с RGB-кодом 0).
Теперь посмотрим, как применить к кнопкам фильтр, например,
Drop Shadow. Сначала нужно с помощью команды
import подключить пакет для работы с фильтрами
где можно задать все параметры, которые есть на панели
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:
При нажатии кнопки мыши нужно запомнить координаты начала отрезка
в переменных x1 и y1.
Добавьте в обработчик onMouseDown (внутри условного оператора) код
x1 = _xmouse;
y1 = _ymouse;
При перемещении мыши запоминаем текущее положение в
переменных x2 и y2. Кроме того,
клип temp очищается с помощью метода clear
и на нем рисуем отрезок из первой точки во вторую. Таким образом,
второй конец отрезка передвигается вслед за мышью,
а основной рисунок не портится.
Когда мышь отпущена, нужно очистить клип temp
и нарисовать отрезок «начисто», уже на
клипе canvas.
Добавьте в начало обработчика onMouseUp код
with ( this ) {
if ( drag ) {
temp.clear();
if (tool == "line") lineTo(x2,y2);
}
}
и проверьте работу инструмента «линия».
Самостоятельно добавьте в программу код, позволяющий рисовать прямоугольники и овалы с предварительным
просмотром на клипе temp.
Значки
Осталось добавить значки в нижней части сцены.
Все они строятся на основе клипа Значок, в котором есть три
кадра с изображениями дома, дерева и машинки. Этот клип имеет
кодовое имя icon для использования в программе.
Добавьте в конец программы цикл, расставляющий значки в нижнем ряду:
Программа внутри клипа Значок построена так, что
клип можно перетаскивать, а при окончании перетаскивания
вызывается функция _root.dropIcon, которую мы сейчас
и напишем.
Добавьте функцию, которая устанавливает на поле копию значка:
Если значок перетащен на поле, с помощью
duplicateMovieClip создается его копия,
ее масштаб увеличивается до 150%. С помощью команды
obj.gotoAndStop(_root[name]._currentFrame);
новый клип переводится на тот же кадр, что и образец.
Чтобы копию уже нельзя было перетаскивать, свойству
enabled внутренней невидимой кнопки btn
присваивается значение false:
obj.btn.enabled = false;
Эта кнопка находится внутри клипа Значок и обрабатывает
все события мыши. Если она заблокирована, перетаскивания
не произойдет.
Начальное положение клипа запоминается при его создании в
свойствах x0 и y0, поэтому команды
Теперь остается сделать кнопку для очистки экрана. Здесь
уже не обойтись одним вызовом метода canvas.clear(),
поскольку нужно еще удалить перетащенные на поле рисунки.
Общее количество рисунков хранится в переменной nIcons
(включая образцы), причем их имена obj1,
obj2 и т.д.
Клипы удаляются с помощью метода removeMovieClip,
причем первые три (образцы) остаются на месте.
Добавьте на сцену кнопку Корзина из библиотеки и присоедините к ней обработчик
on (release) {
canvas.clear();
while ( nIcons > 3 ) {
name = "obj" + nIcons;
removeMovieClip(_root[name]);
nIcons --;
}
}