В этой лекции мы будем рассматривать прорисовку API - новую возможность Flash MX, позволяющую создавать новое графическое содержимое "на лету". Мы начнем с описания основных принципов и методов работы, а затем рассмотрим, как можно расширить возможности рисования API, например, написав дополнительные методы для рисования квадратов.
Прежде всего, мы рассмотрим следующие случаи применения API-рисования.
Для рисования прямой линии с помощью API-рисования необходимо знать следующее.
moveTo. Каждый фильм инициализируется в позиции рисования по умолчанию (0,0).lineStyle, который определяет внешний вид всех линий, имеющихся в фильме. Если не настраивать параметр lineStyle, ни одна нарисованная нами линия не будет отображаться. (Иногда это бывает полезным, как мы убедимся далее при добавлении заливки.)Итак, чтобы нарисовать прямую линию, откройте панель Actions. Введите следующий код в кадр 1 вашего нового фильма и проверьте его работу.
this.lineStyle (3, 0x000000); this.lineTo (200, 100);

Это действие нарисует линию из левого верхнего угла рабочего места до позиции (200, 100). С помощью функции lineStyle мы настраиваем линию на ширину в три пикселя и черный цвет. Вы также можете добавить необязательный третий аргумент для установки интенсивности линии. По умолчанию это значение равно 100. Если не указать цвет линии, она будет нарисована черным цветом.
Если линия должна начинаться из какого-либо другого места, нужно использовать функцию moveTo:
this.lineStyle (3, 0x000000); this.moveTo (200, 0); this.lineTo (200, 100);

moveTo перемещает точку начала рисования без прорисовки линии, а lineTo рисует линию и перемещает точку рисования.
this.lineStyle (3, 0x000000); this.moveTo (200, 0); this.lineTo (200, 100); this.lineTo (400, 100);

Это все, что нужно для рисования прямой линии. Функцию lineTo мы позже будем использовать для определения края
Кривая линия рисуется аналогичным образом, однако здесь уже требуется указывать два набора точек.
this.curveTo (controlX, controlY, anchorX, anchorY);
Линия будет нарисована из текущей точки рисования в точку anchorX, anchorY со значением controlX и controlY, определяющим изгиб линии. Чтобы разобраться, каким образом значения controlX и controlY влияют на кривизну, нужно представить себе третью точку как своего рода магнит, "сгибающий" линию по направлению к себе. Попробуйте выполнить следующий код.
this.lineStyle (3, 0x000000); this.moveTo (50, 50); this.curveTo (100, 0, 250, 250);

Затем сравните его с результатом работы этой программы.
this.lineStyle (3, 0x000000); this.moveTo (50, 50); this.curveTo (200, 300, 250, 250);

Для большей наглядности того, как точка контроля влияет на кривизну линии, мы объединим фильм с тремя перетаскиваемыми управляющими элементами - по одному на каждый конец линии и третий для представления точки контроля.
_quality = "LOW";
this.attachMovie("point", "start_mc", 1);
this.attachMovie("point", "end_mc", 2);
this.attachMovie("point", "control_mc", 3);
Вы создали три точки на рабочем месте с именами start_mc, end_mc и control_mc. Теперь нам нужно настроить каждую точку таким образом, чтобы их можно было перетаскивать в любое место и перерисовывать кривую согласно их новым позициям.
onPress для начала перетаскивания, функция onRelease для завершения перетаскивания и функция onMouseMove для выполнения перетаскивания и перерисовки кривой линии. Добавьте следующий ActionScript под только что введенным кодом.function dragOn() {
// sets the mousemove handler of the movieclip to 'dragMe'
this.onMouseMove = dragMe;
}
function dragOff() {
// clears the mousemove handler of the movieclip.
delete this.onMouseMove;
}
function dragMe() {
// moves the movieclip to the position of the mouse
this._x = _root._xmouse;
this._y = _root._ymouse;
// calls the redraw function in the parent clip ie the _root
this._parent.reDraw();
}
start_mc.onPress = dragOn; end_mc.onPress = dragOn; control_mc.onPress = dragOn;
Однако существует способ, который в данном случае подойдет нам больше. Во Flash MX метод имеет полезное свойство, которое позволяет нам передавать объект при добавлении нового фильма. При добавлении фильма все параметры этого объекта копируются в новый фильм.
onPress, onRelease и onMouseMove, которую мы будем передавать в функцию attachMovie , после чего все присвоения будут производиться без нашего участия. Мы передаем объект в attachMovie в виде четвертого аргумента. Ниже жирным цветом выделен добавленный код._quality = "LOW";
// set up an init object
initObj = {onPress:dragOn, onReiease:dragOff, onReleaseOutside:dragOff,
useHandCursor:false};
// pass the init object when we call attachMovie
this.attachMovie("point" , "start_mc", 1, initObj);
this.attachMovie("point", "end_mc", 2, initObj);
this.attachMovie("point", "control_mc", 3, initObj);
Выполнив этот код, вы сможете перетаскивать ваши фильмы.

this.clear () для удаления уже имеющихся в текущем месте линий или заполнений. Далее нужно установить lineStyle на черный цвет и нарисовать кривую из точки start_mc в точку end_mc через точку control_mc, т.е. контрольную точку кривой. Наконец, мы нарисуем красную линию с интенсивностью 30 из точки end_mc в точку control_mc, и затем из control_mc в start_mc.function redraw() {
this.clear();
this.lineStyle(2, 0x000000);
this.moveTo(start_mc._x, start_mc._y);
this.curveTo(control_mc._x, control_mc._y, end_mc._x, end_mc._y);
this.lineStyle(2, 0xFF5555, 30);
this.lineTo(control_mc._x, control_mc._y);
this.lineTo(start_mc._x, start_mc._y);
}
Нарисовав набор линий, создающий путь, мы тем самым создадим заливку. Основным способом создания заливки является вызов функции beginFill и последующее рисование линий. Имейте в виду, что lineStyle может быть не указан. Тогда заливка будет прорисована без рамки. Ниже приведен ActionScript для заливки квадрата.
this.moveTo(100, 100); this.beginFill(0xFF0000); this.lineTo(200, 100); this.lineTo(200, 200); this.lineTo(100, 200); this.lineTo(100, 100); this.endFill();

Мы можем применить заливку, добавив вызов lineStyle:
this.moveTo(100, 100); this.lineStyle(2, 0x000000); this.beginFill(0xFF0000); this.lineTo(200, 100); this.lineTo(200, 200); this.lineTo(100, 200); this.lineTo(100, 100); this.endFill();

В словаре ActionScript такая возможность не оговорена, но вы можете обнулить все установки lineStyle, один раз вызвав lineStyle без параметров. Итак, мы можем залить половину рамки.
this.moveTo(100, 100); this.lineStyle(2, 0x000000); this.beginFill(0xFF0000); this.lineTo(200, 100); this.lineTo(200, 200); this.lineStyle(); this.lineTo(100, 200); this.lineTo(100, 100); this.endFill();

Таким образом, функции lineTo возвращают точки начала рисования на их исходные позиции. Здесь endFill в любом случае закрывает путь и проводит прямую линию обратно в начальную точку. Можно убрать строку кода, и будет по-прежнему выводиться красный квадрат.
this.moveTo(100, 100); this.beginFill(0xFF0000); this.lineTo(200, 100); this.lineTo(200, 200); this.lineTo(100, 200); this.endFill();
Применив заливку к curveTo, можно рисовать квадрат со сглаженными углами, как показано ниже:
this.moveTo(100, 100); this.beginFill(0xFF0000); this.curveTo(150, 50, 200, 100); this.curveTo(250, 150, 200, 200); this.curveTo(150, 250, 100, 200); this.curveTo(50, 150, 100, 100); this.endFill();

Прежде чем рассматривать градиентную заливку, мы вкратце рассмотрим один из способов использования функции beginGradientFill. Функция beginGradientFill должна иметь ряд параметров: необходимо передавать ей массивы, содержащие различные используемые цвета, интенсивности цветов, степени цветов, а также массив, содержащий значения для координат X и Y, наряду с шириной и высотой градиента. Вот как выглядит функция beginGradientFill в словаре ActionScript:
myMovieClip.beginGradientFill(fillType, colors, alphas, ratios, matrix);
С помощью первого метода использования функции, аргумент matrix обращается к матрице 3x3, используемой для управления внешним видом градиента, изгибами, размером, поворотом и переходом градиента. На данный момент мы закончим рассмотрение этого типа функции, так как она подробно описывается далее в этой книге.
При более простом способе передаваемый нами матричный объект содержит ширину, высоту, начальные координаты X и Y и значение поворота. В нем также содержится конечный параметр matrixType, который должен быть всегда установлен на значение box. При определении ширины и высоты градиента указывается область, к которой применяется градиент. Например, если мы определим линейный градиент с X=100, Y=100, шириной, равной 100 и высотой 100, градиент будет применен к области с 100 до 200 по оси X. Левая и правая области рядом с градиентом будут отображаться просто сплошным цветом.
Если вы посмотрите на следующий код, позиция X градиента равна 120, а его ширина равна 60. Рисуемая фигура отображается с позиции 100 по 200 по оси X, при этом со 100 по 120 имеет место сплошной розовый цвет, а с позиции 180 по 200 - сплошной оранжевый.
this.moveTo(100, 100);
colors = [0xFFE4E1, 0xFF6600];
alphas = [100, 100];
ratios = [23, 255];
matrix = {matrixType:"box", x:120, y:30, w:60, h:10, r:0};
beginGradientFill("linear", colors, alphas, ratios, matrix);
this.curveTo(150, 50, 200, 100);
this.curveTo(250, 150, 200, 200);
this.curveTo(150, 250, 100, 200);
this.curveTo(50, 150, 100, 100);
this.endFill() ;
Чтобы лучше разобраться, как градиент заполняет область, можно поэкспериментировать с различными значениями и посмотреть, как они влияют на результат. Например, в строке matrix в ActionScript выше приравняйте r к Math.PI. Вы увидите, что градиент развернется на 180 градусов (pi радиан).

Также интересно поменять местами X и Y. Здесь мы переместили радиальное заполнение на край нашей фигуры.
this.moveTo(100, 100);
colors = [0xFFE4E1, 0xff6600];
alphas = [100, 100];
ratios - [23, 255];
matrix = {matrixType:"box", x:100, y:30, w:100, h:100, r:1};
beginGradientFill("radial", colors, alphas, ratios, matrix);
this.curveTo(150, 50, 200, 100);
this.curveTo(250, 150, 200, 200);
this.curveTo(150, 250, 100, 200);
this.curveTo(50, 150, 100, 100);
this.endFill();

На первый взгляд этот метод кажется сложным, но если разобраться в том, как влияют числа на конечный результат, все становится понятно. Вы можете создать функцию enterFrame, которая будет изменять эти значения. Немного поэкспериментировав, можно добиваться довольно необычных эффектов.
Представленные средства рисования очень полезны, но вам наверняка потребуется создание функций, которые будут комбинировать их возможности. Например, если нужно нарисовать квадрат, вовсе не обязательно выполнять каждый раз одну и ту же процедуру, заключающуюся в установке цвета заливки и lineStyle, перемещении точки рисования, рисовании линий и заливки. Проще создать функцию, которой будут передаваться все параметры для рисования квадрата, после чего мы будем получать уже готовый результат.
При создании таких функций первое, что нужно сделать - это выделить все параметры, которые нам могут понадобиться. Нам нужны координаты X и Y, ширина, высота, цвет заливки или ее интенсивность, цвет линий, ширина и интенсивность.
MovieClip.prototype.drawSquare = function(x, y, w, h, fillCol,
fillAlpha, lineCol, lineWeight, lineAlpha) {
};
Порядок расположения параметров в функции очень важен. Например, нам нужно просто отобразить квадрат без линии вокруг его края. Вместо создания отдельной функции для рисования квадрата без рамки мы можем передать все параметры нового стиля в конце определения нашей функции и пропускать их при вызове функции. В этом случае значения lineCol, lineWeight и lineAlpha будут отображаться как "undefined", и рамка не будет прорисовываться.
Внутри функции мы, во-первых, должны установить lineStyle и цвет заливки, а также переместить точку рисования на позицию (X, Y), которую мы указали.
MovieClip.prototype.drawSquare = function(x, y, w, h, fillCol,
fillAlpha, lineCol, lineWeight, lineAlpha) {
this.moveTo(x, y);
// check if a line colour has been specified
if (lineCol) {
this.lineStyle(lineWeight, lineCol, lineAlpha);
} else {
this.lineStyle();
}
this.beginFill(fillCol, fillAlpha);
};
Мы проверяем, был ли передан аргумент lineCol. Если это так, то настраиваем lineStyle соответствующим образом. Если нет, вызываем lineStyle без параметров для очистки lineStyle, которая уже может быть настроена для данного фильма.
Другим моментом, на котором основывается наше решение, является то, передает ли пользователь аргумент lineAlpha (будет ли lineAlpha по умолчанию нулем или нет). Мы, конечно, мы могли бы оградиться от этого и изменить функцию по умолчанию на 100, если lineCol передается, а lineAlpha - нет. Осталось проверить, определена ли lineAlpha, и предпринять соответствующие действия.
MovieClip.prototype.drawSquare = function(x, y, w, h, fillCol,
КfillAlpha, lineCol, lineWeight, lineAlpha) {
this.moveTo(x, y) ;
if (lineCol != undefined){
if (lineAlpha == undefined) {
lineAlpha = 100;
}
this.lineStyle(lineWeight, lineCol, lineAlpha);
} else {
this.lineStyle ();
}
this.beginFill(fillCol, fillAlpha);
};
Теперь нам нужно прорисовать линии, чтобы отгородить область для заливки. Мы начнем с левого верхнего угла и будем двигаться вокруг квадрата по часовой стрелке, прорисовывая линию каждого угла по очереди. Полезно разобраться в том, как здесь указываются координаты.
Теперь нам просто нужно нарисовать линию для каждой из этих точек по очереди и затем завершить заполнение.
MovieClip.prototype.drawSquare = function(x, y, w, h, fillCol,
КfillAlpha, lineCol, lineWeight, lineAlpha) {
this.moveTo(x, y);
if (lineCol != undefined) {
if (lineAlpha == undefined) {
lineAlpha = 100;
}
this.lineStyle(lineWeight, lineCol, lineAlpha);
} else {
this.lineStyle();
}
this.beginFill(fillCol, fillAlpha);
// top right
this.lineTo(x+w, y);
// bottom right
this.lineTo(x+w, y+h);
// bottom left
this.lineTo(x, y+h);
// top left.
this.lineTo(x, y);
// end the fill
this.endFill();
};
Наконец, нам нужно вызвать
_root.drawSquare (100, 100, 200, 100, 0xFF0000, 100, 0xdddddd, 20, 50) ;
Вы заметите, что рамка, созданная с помощью lineTo, выровнена по центру края квадрата, и если бы у нашей рамки была толщина в 20 пикселей, квадрат был бы на десять пикселей шире с каждой стороны. Углы рамки закруглены, что может быть излишним. Чтобы избежать этого, можно изменить метод так, чтобы сначала прорисовывался квадрат для рамки, а затем уже квадрат поверх него для заливки.
В конечном счете, настройка метода определяется тем, как вы собираетесь его использовать. Например, вы можете указывать значения для левого, правого, нижнего и верхнего краев вместо X, Y, ширины и высоты (если бы нужно было использовать его со значениями, возвращаемыми функцией ). Это несложно.
MovieClip.prototype.drawSquare = function(left, right, top, bottom,
КfillCol, fillAlpha, lineCol, lineWeight, lineAlpha) {
this.moveTo(left, top);
if (lineCol != undefined) {
if (lineAlpha == undefined) {
lineAlpha = 100;
}
this.lineStyle(lineWeight, lineCol, lineAlpha);
} else {
this.lineStyle();
}
this.beginFill(fillCol, fillAlpha);
this.lineTo(right, top);
// top right
this.lineTo(right, bottom);
// bottom right
this.lineTo(left, bottom);
// bottom left
this.lineTo(left, top);
// top left
this.endFill();
};
И далее вызов.
// a square with left edge at 100, right edge at 200, top at // 200 and bottom at 300: this.drawSquare(100,200,200,300,0xff0000,100)
Можно применять другие цвета, интенсивность заполнения и т.д. - все зависит от того, как вы планируете использовать данный метод. Здесь нет правильного или неправильного пути, вы просто конструируете его под ваши нужды.
Теперь мы рассмотрим метод, который позволяет рисовать окружности с помощью API- рисования. Он более "хитрый". Многие методы рисования окружностей зависят от использования curveTo для формирования круга посредством рисования дуг. Этот же метод основан на принципе закругления концов линии. Если нарисовать линию, имеющую ширину в 100 пикселей, она может послужить основой для круга радиусом 100; функция Дэна рисует 0,15 пикселей от текущей точки рисования, что формирует прекрасный круг.
Параметры, передаваемые функции, являются координатами X и Y центра круга, а cWidth - ширина окружности.
function drawCircle(x, y, radius, cWidth) {
me = _root.createEmptyMovieClip("circle"+cnt,++cnt);
me.lineStyle(radius, 0x000000, 100);
me.moveTo(x, y);
me.lineTo(x, y+.15);
me.lineStyle(radius-cWidth, 0xffffff, 100);
me.moveTo(x, y);
me.lineTo(x, y+.15);
}
drawCircle(100, 100, 100, 20);

В этом методе окружность расширена во внешнюю сторону от круга и включена в общий радиус. Мы также создаем фильм, в котором и рисуем круг.
Преобразуем эту функцию так, чтобы она работала как наши предыдущие функции, и затем добавим возможность указания цветов:
MovieClip.prototype.drawCircle = function (x, y, radius, cWidth) {
this.lineStyle(radius, 0x000000, 100);
this.moveTo(x, y);
this.lineTo(x, y+.15);
this.lineStyle(radius-cWidth, 0xffffff, 100);
this.moveTo(x, y);
this.lineTo(x, y+.15);
};
drawCircle(100, 100, 100, 20);
Теперь добавим цвета:
MovieClip.prototype.drawCircle = function(x, y, radius,
КcWidth, innerCol, outerCol) {
this.lineStyle(radius, outerCol, 100);
this.moveTo(x, y);
this.lineTo(x, y+.15);
this.lineStyle(radius-cWidth, innerCol, 100);
this.moveTo(x, y);
this.lineTo(x, y+.15);
};
drawCircle(100, 100, 100, 10, 0xff0000, 0x000000);

Здесь можно поэкспериментировать с порядком параметров, указав в первую очередь цвет заливки и радиус, а потом уже ширину окружности и ее цвет. Вы также можете изменить функцию так, чтобы можно было изменять цвет заполнения и рамки. Тогда можно нарисовать окружность без заливки.
Мы настроили работу функции curveTo, указали начальную точку, конечную точку и точку управления. Но иногда полезнее проводить кривую через указываемую точку, поэтому мы создадим функцию для достижения этого результата.
Функция curveTo во Flash создает то, что называется квадратным уравнением для кривой Безье. Раньше кривые линии рисовали, проставляя серию точек на кривой, а затем воспризводя линии фильмов между этими точками, что достигалось с помощью уравнения кривой Безье.
С помощью этого уравнения указывается конечная точка, точка контроля и начальная точка. Переменной в этом уравнении является t, которая изменяет значения от 0 до 1 от начала кривой и до ее конца. Мы можем вставлять различные значения t для выяснения координат любой отдельной точки на кривой.
| x | Положение по оси X, через которое проходит кривая за в t |
| x0 | Начальная точка кривой по оси X |
| x1 | Контрольная точка прохождения кривой по оси X |
| X2 | Конечная точка кривой по оси X |
| y | Положение по оси Y, через которое проходит кривая в t |
| Y0 | Начальная точка кривой по оси Y |
| Y1 | Контрольная точка прохождения кривой по оси Y |
| Y2 | Конечная точка кривой по оси Y |
| t | Время |
Приведем наше уравнение.
x = x0*t*t + x1*2*t*(1-t) + x2*(1-t)*(1-t) y = y0*t*t + y1*2*t*(1-t) + y2*(1-t)*(1-t)

Это уравнение полезно для поиска отдельной точки, через которую проходит кривая, в любой точке t, от 0 до 1, т.е. от начала и до конца кривой. Мы указываем точку начала, точку контроля, конечную точку и t для перехода к позиции (X, Y) (в которой кривая проходит через эту точку).
Нам нужно изменить функцию таким образом, чтобы можно было указывать значения для точки начала (x0,y0), конца (x2,y2) и отдельной точки кривой (X, Y) и перейти в нужную точку контроля (x1,y1). Другими словами, нужно переработать функцию так, чтобы она выглядела примерно следующим образом.
x1= умноженное на x0, x2, x и t y1= умноженное на y0, y2, y и t
Это разумное упрощение. Мы рассмотрим его для уравнения для X и затем продублируем наши результаты для Y, так как уравнения идентичны. Прежде всего, нам нужно получить значения x1 и y1 в левой части уравнения. Это мы сделаем взаимным уничтожением с обеих сторон:
x - x1*2*t*(1-t) = x0*t*t + x1*2*t*(1-t) + x2*(1-t)*(1-t) - x1*2*t*(1-t)
Значения плюс и минус x1*2*t*(1-t) в правой части взаимно компенсируют друг друга:
x - x1*2*t*(1-t) = x0*t*t + x1*2*t*(1-t) + x2*(1-t)*(1-t) х1*2*t(1-t) x - x1*2*t*(1-t) = x0*t*t + x2*(1-t)*(1-t)
Теперь вычтем x из обеих сторон:
x - x1*2*t*(1-t) - x = x0*t*t + x2*(1-t)*(1-t) - x x - x1*2*t*(1-t) -x = x0*t*t + x2*(1-t)*(1-t) - x -x1*2*t*(1-t) = x0*t*t + X2*(1-t)*(1-t) - x -1*x1*2*t*(1-t) = x0*t*t + x2*(1-t)*(1-t) - x
Умножим -1 на 2 в левой части уравнения:
x1* - 2*t*(1-t) = x0*t*t + x2*(1-t)*(1-t) - x
Далее, делим обе части уравнения на (-2*t*(1-t) ):
x1*(-2*t*(1-t)) / (-2*t*(1-t)) = =(x0*t*t + x2*(1-t)*(1-t) - x) / (-2*t*(1-t))
С левой стороны имеем (-2*t*(1-t)) / (-2*t*(1-t)), что дает 1, поэтому можно произвести сокращение:
x1 (- 2 * t * (1 - t)) / ( - 2 * t * (1 - t) ) = =(x0*t*t + x2*(1-t)*(1-t) - x) / (-2*t*(1-t)) x1 = (x0*t*t + x2*(1-t)*(1-t)-x) / (-2*t*(1-t))
Мы получили уравнение для нахождения x1, а уравнением для y1 будет следующее:
y1 = (y0*t*t + y2*(1-t)*(1-t) - y) / (-2*t*(1-t))
Теперь можно использовать полученные результаты для создания функции, которая будет передавать значения x, y, x0, y0, x2, y2 и t для рисования кривой из (x0,y0) в (x2,y2), проходящей через точку (x,y) в точке на прямой, указываемой t.
Истинная роль t станет вам понятнее, когда вы начнете вставлять числа, которые будут влиять на форму кривой. Переименуем значения на a, b и c в нашей функции, для простоты. Мы будем вызывать функцию aToBThroughC чтобы выяснить значение каждой из величин. Приведем уравнение с добавленными a, b и c:
controlX = (ax*t*t + bx*(1-t)*(1-t) - cx) / (-2*t*(1-t)) controlY = (ay*t*t + by*(1-t)*(1-t) - cy) / (-2*t*(1-t))
Теперь перейдем к самой функции. Для простоты предположим, что мы настроили lineStyle.
MovieClip.prototype.aToBThroughC =
function (ax, ay, bx, by, ex, cy,t) {
var controlX = (ax*t*t+bx*(1-t)*(1-t)-cx)/(-2*t*(1-t));
var controlY = (ay*t*t+by*(1-t)*(1-t)-cy)/(-2*t*(1-t));
this.moveTo(ax, ay);
// for security
this.curveTo(controlx, controly, bx, by);
};
Для проверки работы введите следующий код.
this.lineStyle (27, 0xff0000); this.aToBThroughC (100, 100, 250, 100, 200, 350, 0.5);
Сохраните ваш файл под именем AtoBthroughC.fla и запустите его. Мы создали сильно изогнутую кривую

Чтобы показать корректность работы нашей функции, мы откроем созданный нами ранее файл curve with anchor.fla, и изменим его так, чтобы третья, перетаскиваемая, точка была точкой, через которую проходит кривая, а не точкой контроля. Измененный код выделен жирным шрифтом:
_quality = "LOW";
MovieClip. prototype. aToBThroughC = function (ax, ay, bx, by, ex, cy, t) {
var controlX = (ax*t*t+bx*(1-t)*(1-t)-cx)/(-2*t*(1-t));
var controlY = (ay*t*t+by*(1-t)*(1-t)-cy)/(-2*t*(1-t));
this.moveTo(ax, ay);
// for security
this.curveTo(controlx, controly, bx, by);
};
initObj = {onPress:dragOn, onRelease:dragOff,onReleaseOutside:dragOff,
КuseHandCursor: false};
this.attachMovie("point", "start_mc", 1, initObj);
this.attachMovie("point", "end_mc" , 2, initObj);
this.attachMovie("point", "control_mc", 3, initObj);
function dragOn() {
this.onMouseMove = dragMe;
}
function dragOff() {
delete this.onMouseMove;
}
function dragMe() {
this._x = _root._xmouse;
this._y = _root ._ymouse;
this._parent.reDraw();
}
function reDraw() {
this.clear();
this.lineStyle(2, 0xFF5555, 100);
this.aToBThroughC(start_mc._x, start_mc._y, end_mc._x, end_mc._y,
Кcontrol_mc._x, control_mc._y, 0.5);
}
Вы увидите, что при перетаскивании точек кривая теперь всегда проходит через третью точку.

Задав другое значение t, вы увидите, что кривая изменила форму.
this.aToBThroughC(start_mc._x, start_mc._y, end_mc._x, end_mc._y, Кcontrol_mc._x, control_mc._y, 0.1); }
Переменная t может иметь любое значение между 0 и 1, поэтому здесь может быть огромное количество кривых, которые будут проходить через нашу точку c - по одной для каждого значения между 0 и 1.
В этом параграфе мы создадим несложное приложение, в котором можно будет рисовать изображения и сохранять результаты для дальнейшего просмотра. Задача разбивается на 3 этапа.
Вы не найдете ничего нового в этом приложении, однако оно поможет разобраться вам в методологии и поможет изучить работу общих объектов. Это новая мощная возможность Flash MX.
Простое приложение для рисования состоит из тринадцати строк кода. Вот принцип его работы:
Для этого нам нужны три функции: одна для обработки щелчка пользователя, другая для отпускания пользователем кнопки мыши, и третья для записи позиции указателя мыши при нажатой кнопке.
function drawOn() {
this.lineStyle (0x000000);
this.moveTo(this._xmouse, this._ymouse);
this.onMouseMove = addPoint;
}
function addPoint() {
this.lineTo(this._xmouse, this._ymouse);
}
function drawOff() {
delete this.onMouseMove;
}
this.onMouseDown = drawOn;
this.onMouseUp = drawOff;
С помощью onMouseDown устанавливается lineStyle и точка рисования перемещается туда, где находится мышь, а также onMouseMove устанавливается в addPoint.
В тот момент, когда пользователь двигает мышь, рисуется линия к новой позиции указателя мыши. Когда пользователь отпускает кнопку мыши, управляющий элемент onMouseMove удаляется.
Введите код в панель Actions нового фильма, сохраните его в файле doDrawing.fla и запустите его.

Мы получили простой интерфейс рисования, состоящий всего лишь из тридцати строк.
Теперь рассмотрим возможность сохранения и воспроизведения создаваемых рисунков. Для этого нам нужно помещать координаты, соответствующие рисунку, в массив. Нам также нужно будет записывать передвижение пользователем указателя мыши без рисования линии. С этой целью мы введем специальное значение "break", которое будет означать, что карандаш не задействован и перемещен в какое-либо место. Добавленный код выделен жирным шрифтом.
function drawOn() {
this.lineStyle(1, 0x000000);
this.moveTo(this._xmouse, this._ymouse);
// add the new point to the array
tempArr.push({x:_root._xmouse, у:_root._ymouse});
this.onMouseMove = addPoint;
}
function addPoint() {
// add the new point to the array
tempArr.push ({x:_root._xmouse, у:_root._ymouse});
this.lineTo(_root._xmouse, _root._ymouse);
}
function drawOff() {
// the pen is lifted so we add the value "break" to the array
tempArr.push("break");
delete this.onMouseMove;
}
tempArr = [];
this.onMouseDown = drawOn;
this.onMouseUp = drawOff;
Мы создали массив tempArr для хранения всех координат в объектах с параметрами X и Y.
Сохраните ваш фильм в файле doAndStoreDrawing.fla. Если вы запустите фильм и выберете команду меню Debug > List Variables, вы увидите все координаты нарисованных вами точек в окне Output.

Перед тем, как рассматривать восстановление рисунка из этих координат, изучим использование общих объектов для хранения переменных.
Общие объекты позволяют хранить данные локально, на жестком диске пользователя.
Грубо говоря, общие объекты являются своего рода cookies для Flash. Они позволяют нам локально хранить любые данные наших Flash-фильмов, и работают в любых браузерах, равно как и локальный Flash Player.
Итак, общие объекты могут быть использованы для хранения данных, представляющих собой рисунок, созданный в приложении при помощи рисования API. Общие объекты могут также использоваться в онлайн-формах для запоминания предыдущих записей пользователей и
Мы не будем разбираться в сложных деталях использования общих объектов, мы изучим создание общего объекта и обеспечение его работы. Если вы хотите узнать больше об общих объектах и их применении, вам стоит обратиться к сайту по этой ссылке: www.macromedia.com/support/flash/action_scripts/local_shared_object.
Мы начнем с очень простого приложения.
visit number.Мы используем общий объект для хранения числа просмотров страницы. Это элементарное приложение, но оно содержит все необходимое для продолжения работы с приложением рисования.
sharedObject с помощью SharedObjec.getLocal. Это действие вернет объект, если он уже был создан, а если он еще не создавался, он будет создан. Введите следующий код на панели Actions:mySharedObj = SharedObject.getLocal ("visits");
Теперь мы имеем копию общего объекта в переменной mySharedObj. mySharedObj - это объект, которому вы можете присваивать параметры, как любому другому объекту. Это могут быть переменные, массивы и т.д. Переданный параметр "visits" является именем общего объекта, что позволяет иметь несколько общих объектов для каждого проекта.
mySharedObj = SharedObject.getLocal("visits");
//we increment a variable "visitCount" inside "data" where
//all the data resides in a shared object
mySharedObj.data.visitCount++;
visited.text = mySharedObj.data.visitCount;
sharedObject, синхронизируя его, если нужно, с использованием метода flush, который возвращает все из mySharedObj обратно в текущий общий объект. Добавьте последнюю строку сценария в панель Actions.mySharedObj = SharedObject.getLocal("visits");
mySharedObj.data.visitCount++;
visited.text = mySharedObj.data.visitCount;
mySharedObj.flush();
sharedObj basics.fla. Если вы запустите фильм несколько раз, вы увидите, что число будет увеличиваться (если вы не игнорировали запрос безопасности, который мы будем рассматривать и обрабатывать в реальных условиях).
На примере рассмотренного приложения становится ясно, что сохранение рисунков в приложении заключается просто в сохранении массива данных в общем объекте.
Мы создадим интерфейс, содержащий все локально сохраненные изображения, и затем обеспечим возможность либо рисования нового рисунка, либо просмотра старого.
Приведем структуру того, что мы хотим сделать:
Главная страница:
Возможности:
Панель, содержащая список рисунков из sharedObject с полосой прокрутки.
Опции:
Выбрать имеющийся рисунок - перейти к странице перерисовки.
Создать новый рисунок - перейти к странице создания.
Страница перерисовки:
Возможности:
Перерисовка прежнего рисунка.
Опции:
Вернуться на главную страницу.
Страница создания:
Возможности:
Рисование мышью.
Опции:
Сохранить текущий рисунок - сохранить рисунок в общем объекте - перейти на главную страницу.
Вернуться - возврат на главную страницу.
У нас есть три основных задачи: меню, рисование и перерисовка. Мы можем предположить, какие функции нам потребуются для создания приложения:
| Имя функции | Цель |
|---|---|
init |
Установка некоторых основных управляющих элементов кнопок и вызов drawPanel. |
drawPanel |
Получение данных из объекта sharedObject и отключение кнопки возврата и сохранения. Вызов listDrawings и initScrollers. |
listDrawings |
Добавление текстового поля в меню. |
initScrollers |
Установка полос прокрутки для текстового поля. |
initDraw |
Выключение меню, включение кнопки возврата и сохранения и установка управляющих элементов событий onMouseDown и onMouseUp для реализации рисования. Настройка lineStyle и создание временного массива для хранения точек. |
drawOn |
Начало рисования линии, установка onEnterFrame и addPoint. |
addPoint |
Рисование линии и добавление текущей точки в массив. |
drawOff |
Выключение addPoint. |
save |
Добавление текущего массива точек в sharedObject и вызов backToMain. |
backToMain |
Удаление всех событий кадра и мыши на _root. Вызов drawPanel. |
redraw |
Отключение меню и включение кнопки возврата. Установка onEnterFrame. |
drawNextPoint |
Рисование следующей точки в текущем рисунке. |
Перейдем к работе над полнофункциональным приложением рисования и сохранения рисунков.

saverButton с помощью Property inspector, а инстанс кнопки Return - backButton.Можно было бы использовать для этого программный компонент прокрутки, но компоненты мы будем рассматривать в следующей лекции и пока не будем забегать вперед. Создание фильма почти завершено, осталось только добавить в него заголовок. Мы создали новый слой с именем title и добавили

listingsPanel.Сейчас мы поочередно разберем функции, использованные нами выше, с объяснением некоторых моментов.
function drawPanel() {
// turn off the back button and the save button
backButton._visible = false;
saverButton._visible = false;
// make the menu panel visible
this.listingsPanel._visible = true;
// retrieve the shared object
myPictureObj = SharedObject.getLocal("pictures");
// list any drawings
listDrawings(myPictureObj.data.arrays);
// check if we need to turn on the scrollers
initScrollers();
}
Здесь мы инициализировали общий объект и сохранили его в myPictureObj, а также настроили отображение некоторых элементов рабочего места. Далее мы вызовем listDrawings для просмотра myPictureObj и выяснения количества находящихся там рисунков. Мы запишем наши массивы точек в массив с именем arrays объекта sharedObject и затем передадим этот массив функции listDrawings. Внутри массива arrays будет находиться один массив для каждого рисунка. Вместо создания кнопки для каждого рисунка мы используем функцию asfunction, позволяющую представлять фрагмент текста HTML в виде ссылки на функцию ActionScript. Вот как это делается.
asfunction:functionName, parameter;
_root.redraw и передачи номера записи массива.function listDrawings(pictureArray) {
listingsPanel.lista.htmlText = "";
// loop through the picture array
for (var i = 0; i<pictureArray.length; i++) {
// for each entry in the picture array add another line
// to the text in the textfield
var nexta = "<A HREF='asfunction:_root.redraw,"+i+"'>"+"
Drawing Number "+(i+1)+"</A><b/>";
listingsPanel.lista.htmlText += nexta;
}
}
drawPanel. Она просто настроит отображение кнопок прокрутки в зависимости от того, где мы находимся - вверху или внизу текстового поля, а также от того, может ли поле вместить все содержащиеся в нем строки текста. С помощью with мы перейдем внутрь фильма listingsPanel. Параметр visible инстанса кнопки downScroll устанавливаем на значение on, если значение прокрутки меньше, чем максимально возможное значение прокрутки. Этот же параметр устанавливается на значение on, если текстовое поле было полностью прокручено.function initScrollers() {
with (this.listingsPanel) {
downScroll._visible = lista.scroll<lista.maxscroll;
upScroll._visible = lista.scroll>l;
}
}
Наш список будет выглядеть примерно так.

initDraw - функцию, которая будет вызываться при щелчке пользователя на кнопке new:function initDraw() {
// turn on the back and save buttons
backButton._visible = true;
saverButton._visible = true;
// turn off the menu
_root.listingsPanel._visible = false;
// create an array for the points
tempArr = [];
_root.lineStyle(1, 0x000000);
// set up out mouse event handlers
_root.onMouseDown = drawOn;
_root.onMouseUp = drawOff;
}
Все это вам уже знакомо: сначала настраивается отображение элементов рабочего места так, чтобы были видны кнопки back и save, затем настраивается lineStyle и создается массив для наших точек.
function drawOn() {
this.moveTo(this._xmouse, this._ymouse);
tempArr.push({x:this._xmouse, y:this._ymouse});
this.onMouseMove = addPoint;
}
function addPoint() {
tempArr.push({x:this._xmouse, y:this._ymouse});
this.lineTo(this._xmouse, this._ymouse);
}
function drawOff() {
tempArr.push("break");
delete this.onMouseMove;
}
save и будет сохранять tempArr в общем объекте. Перед сохранением массива мы удаляем последний объект, так как объект точки записывается в массив, когда пользователь нажимает кнопку для ее сохранения (когда происходит onMouseDown ). Если не делать этого, можно столкнуться с проблемами потерянной строки в конце рисунка.function save() {
// remove final element
tempArr.pop();
if (!myPictureObj.data.arrays) {
// if our array for pictures has not yet been created,
// create it
myPictureObj.data.arrays = [];
}
// put the current picture array into the array
// containing all pictures
myPictureObj.data.arrays.push(tempArr);
// update the shared object
myPictureObj.flush();
// return to the menu screen
_root.backToMain();
}
Обратите внимание, что здесь сначала проверяется существование массива arrays, и если массив не существует, то он создается. Затем tempArr помещается в конец этого массива и вызывается flush для сохранения его в объекте. После этого вызывается backToMain для удаления всех управляющих элементов событий, а также весь рисунок в фильме, перед возвращением к началу.
function backToMain() {
delete _root.onEnterFrame;
delete _root.onMouseMove;
delete _root.onMouseDown;
delete _root.onMouseUp;
_root.clear();
_root.drawPanel();
}
redraw для начала перерисовки и drawNextPoint для покадрового продолжения. Перерисовка осуществляется посредством прохода через массив точек и рисования линии от предыдущей точки к текущей в каждом кадре. С помощью break осуществляется переход к точке без рисования линии.function redraw(num) {
backButton._visible = true;
this.listingsPanel._visible = false;
// set count to zero, used to keep track of current point
this.count = 0;
// the array which we are redrawing
this.currentArr = myPictureObj.data.arrays[num];
this.lineStyle (0x000000);
this.moveTo( this, currentArr [0] .x, this .currentArr [0] .y);
// every frame we draw the next point
this.onEnterFrame = drawNextPoint;
}
enterFrame на drawNextPoint.function drawNextPoint() {
this.count++;
// nextEntry is the next point object in the array
var nextEntry = this.currentArr[this.count];
if (nextEntry != "break") {
this.lineTo(nextEntry.x, nextEntry.y);
} else {
// if the nextEntry is "break", we increment count
// and move to the next point.
this.count++;
var nextEntry = this.currentArr[this.count];
this.moveTo(nextEntry.x, nextEntry.y);
}
if (this.count>this.currentArr.length) {
// we have drawn all available points
delete this.onEnterFrame;
}
}
Таким образом, с помощью drawNextPoint мы увеличиваем значение нашего счетчика и устанавливаем переменную nextEntry для указания на следующую запись в массиве. Мы проверяем, равно ли это значение "break" и, если это так, увеличиваем count и переходим к следующей точке в массиве с помощью moveTo. Если оно не равно "break", рисуем линию к новой точке. Наконец, проверяем, достигнут ли конец массива; если да, удаляем функцию onEnterFrame и завершаем выполнение действия.
textField в listingsPanel на HTML-текст и рисовать панель в первый раз.function init() {
this.saverButton.onPress = this.save;
this.backButton.onPress = this.backToMain;
with (this.listingsPanel) {
newButton.onRelease = this.initDraw;
// enable html text in the textfield
lista.html = true;
downScroll.onPress = function() {
// scroll the textfield down
lista.scroll++;
// check if the scrollers should still appear
_root.initScrollers();
};
upScroll.onPress = function() {
lista.scroll--;
_root.initScrollers();
};
}
drawPanel();
}
init ()
Весь код программы находится в файле drawingapp.fla.
Безусловно, можно реализовать все это с помощью готового кода, но знать, как все это выглядит в деталях в среде разработки, очень полезно.
В этой лекции мы будем рассматривать прорисовку API - новую возможность Flash MX, позволяющую создавать новое графическое содержимое "на лету". Мы начнем с описания основных принципов и методов работы, а затем рассмотрим, как можно расширить возможности рисования API, например, написав дополнительные методы для рисования квадратов.
Прежде всего, мы рассмотрим следующие случаи применения API-рисования.
Для рисования прямой линии с помощью API-рисования необходимо знать следующее.
moveTo. Каждый фильм инициализируется в позиции рисования по умолчанию (0,0).lineStyle, который определяет внешний вид всех линий, имеющихся в фильме. Если не настраивать параметр lineStyle, ни одна нарисованная нами линия не будет отображаться. (Иногда это бывает полезным, как мы убедимся далее при добавлении заливки.)Итак, чтобы нарисовать прямую линию, откройте панель Actions. Введите следующий код в кадр 1 вашего нового фильма и проверьте его работу.
this.lineStyle (3, 0x000000); this.lineTo (200, 100);

Это действие нарисует линию из левого верхнего угла рабочего места до позиции (200, 100). С помощью функции lineStyle мы настраиваем линию на ширину в три пикселя и черный цвет. Вы также можете добавить необязательный третий аргумент для установки интенсивности линии. По умолчанию это значение равно 100. Если не указать цвет линии, она будет нарисована черным цветом.
Если линия должна начинаться из какого-либо другого места, нужно использовать функцию moveTo:
this.lineStyle (3, 0x000000); this.moveTo (200, 0); this.lineTo (200, 100);

moveTo перемещает точку начала рисования без прорисовки линии, а lineTo рисует линию и перемещает точку рисования.
this.lineStyle (3, 0x000000); this.moveTo (200, 0); this.lineTo (200, 100); this.lineTo (400, 100);

Это все, что нужно для рисования прямой линии. Функцию lineTo мы позже будем использовать для определения края
Кривая линия рисуется аналогичным образом, однако здесь уже требуется указывать два набора точек.
this.curveTo (controlX, controlY, anchorX, anchorY);
Линия будет нарисована из текущей точки рисования в точку anchorX, anchorY со значением controlX и controlY, определяющим изгиб линии. Чтобы разобраться, каким образом значения controlX и controlY влияют на кривизну, нужно представить себе третью точку как своего рода магнит, "сгибающий" линию по направлению к себе. Попробуйте выполнить следующий код.
this.lineStyle (3, 0x000000); this.moveTo (50, 50); this.curveTo (100, 0, 250, 250);

Затем сравните его с результатом работы этой программы.
this.lineStyle (3, 0x000000); this.moveTo (50, 50); this.curveTo (200, 300, 250, 250);

Для большей наглядности того, как точка контроля влияет на кривизну линии, мы объединим фильм с тремя перетаскиваемыми управляющими элементами - по одному на каждый конец линии и третий для представления точки контроля.
_quality = "LOW";
this.attachMovie("point", "start_mc", 1);
this.attachMovie("point", "end_mc", 2);
this.attachMovie("point", "control_mc", 3);
Вы создали три точки на рабочем месте с именами start_mc, end_mc и control_mc. Теперь нам нужно настроить каждую точку таким образом, чтобы их можно было перетаскивать в любое место и перерисовывать кривую согласно их новым позициям.
onPress для начала перетаскивания, функция onRelease для завершения перетаскивания и функция onMouseMove для выполнения перетаскивания и перерисовки кривой линии. Добавьте следующий ActionScript под только что введенным кодом.function dragOn() {
// sets the mousemove handler of the movieclip to 'dragMe'
this.onMouseMove = dragMe;
}
function dragOff() {
// clears the mousemove handler of the movieclip.
delete this.onMouseMove;
}
function dragMe() {
// moves the movieclip to the position of the mouse
this._x = _root._xmouse;
this._y = _root._ymouse;
// calls the redraw function in the parent clip ie the _root
this._parent.reDraw();
}
start_mc.onPress = dragOn; end_mc.onPress = dragOn; control_mc.onPress = dragOn;
Однако существует способ, который в данном случае подойдет нам больше. Во Flash MX метод имеет полезное свойство, которое позволяет нам передавать объект при добавлении нового фильма. При добавлении фильма все параметры этого объекта копируются в новый фильм.
onPress, onRelease и onMouseMove, которую мы будем передавать в функцию attachMovie , после чего все присвоения будут производиться без нашего участия. Мы передаем объект в attachMovie в виде четвертого аргумента. Ниже жирным цветом выделен добавленный код._quality = "LOW";
// set up an init object
initObj = {onPress:dragOn, onReiease:dragOff, onReleaseOutside:dragOff,
useHandCursor:false};
// pass the init object when we call attachMovie
this.attachMovie("point" , "start_mc", 1, initObj);
this.attachMovie("point", "end_mc", 2, initObj);
this.attachMovie("point", "control_mc", 3, initObj);
Выполнив этот код, вы сможете перетаскивать ваши фильмы.

this.clear () для удаления уже имеющихся в текущем месте линий или заполнений. Далее нужно установить lineStyle на черный цвет и нарисовать кривую из точки start_mc в точку end_mc через точку control_mc, т.е. контрольную точку кривой. Наконец, мы нарисуем красную линию с интенсивностью 30 из точки end_mc в точку control_mc, и затем из control_mc в start_mc.function redraw() {
this.clear();
this.lineStyle(2, 0x000000);
this.moveTo(start_mc._x, start_mc._y);
this.curveTo(control_mc._x, control_mc._y, end_mc._x, end_mc._y);
this.lineStyle(2, 0xFF5555, 30);
this.lineTo(control_mc._x, control_mc._y);
this.lineTo(start_mc._x, start_mc._y);
}
Нарисовав набор линий, создающий путь, мы тем самым создадим заливку. Основным способом создания заливки является вызов функции beginFill и последующее рисование линий. Имейте в виду, что lineStyle может быть не указан. Тогда заливка будет прорисована без рамки. Ниже приведен ActionScript для заливки квадрата.
this.moveTo(100, 100); this.beginFill(0xFF0000); this.lineTo(200, 100); this.lineTo(200, 200); this.lineTo(100, 200); this.lineTo(100, 100); this.endFill();

Мы можем применить заливку, добавив вызов lineStyle:
this.moveTo(100, 100); this.lineStyle(2, 0x000000); this.beginFill(0xFF0000); this.lineTo(200, 100); this.lineTo(200, 200); this.lineTo(100, 200); this.lineTo(100, 100); this.endFill();

В словаре ActionScript такая возможность не оговорена, но вы можете обнулить все установки lineStyle, один раз вызвав lineStyle без параметров. Итак, мы можем залить половину рамки.
this.moveTo(100, 100); this.lineStyle(2, 0x000000); this.beginFill(0xFF0000); this.lineTo(200, 100); this.lineTo(200, 200); this.lineStyle(); this.lineTo(100, 200); this.lineTo(100, 100); this.endFill();

Таким образом, функции lineTo возвращают точки начала рисования на их исходные позиции. Здесь endFill в любом случае закрывает путь и проводит прямую линию обратно в начальную точку. Можно убрать строку кода, и будет по-прежнему выводиться красный квадрат.
this.moveTo(100, 100); this.beginFill(0xFF0000); this.lineTo(200, 100); this.lineTo(200, 200); this.lineTo(100, 200); this.endFill();
Применив заливку к curveTo, можно рисовать квадрат со сглаженными углами, как показано ниже:
this.moveTo(100, 100); this.beginFill(0xFF0000); this.curveTo(150, 50, 200, 100); this.curveTo(250, 150, 200, 200); this.curveTo(150, 250, 100, 200); this.curveTo(50, 150, 100, 100); this.endFill();

Прежде чем рассматривать градиентную заливку, мы вкратце рассмотрим один из способов использования функции beginGradientFill. Функция beginGradientFill должна иметь ряд параметров: необходимо передавать ей массивы, содержащие различные используемые цвета, интенсивности цветов, степени цветов, а также массив, содержащий значения для координат X и Y, наряду с шириной и высотой градиента. Вот как выглядит функция beginGradientFill в словаре ActionScript:
myMovieClip.beginGradientFill(fillType, colors, alphas, ratios, matrix);
С помощью первого метода использования функции, аргумент matrix обращается к матрице 3x3, используемой для управления внешним видом градиента, изгибами, размером, поворотом и переходом градиента. На данный момент мы закончим рассмотрение этого типа функции, так как она подробно описывается далее в этой книге.
При более простом способе передаваемый нами матричный объект содержит ширину, высоту, начальные координаты X и Y и значение поворота. В нем также содержится конечный параметр matrixType, который должен быть всегда установлен на значение box. При определении ширины и высоты градиента указывается область, к которой применяется градиент. Например, если мы определим линейный градиент с X=100, Y=100, шириной, равной 100 и высотой 100, градиент будет применен к области с 100 до 200 по оси X. Левая и правая области рядом с градиентом будут отображаться просто сплошным цветом.
Если вы посмотрите на следующий код, позиция X градиента равна 120, а его ширина равна 60. Рисуемая фигура отображается с позиции 100 по 200 по оси X, при этом со 100 по 120 имеет место сплошной розовый цвет, а с позиции 180 по 200 - сплошной оранжевый.
this.moveTo(100, 100);
colors = [0xFFE4E1, 0xFF6600];
alphas = [100, 100];
ratios = [23, 255];
matrix = {matrixType:"box", x:120, y:30, w:60, h:10, r:0};
beginGradientFill("linear", colors, alphas, ratios, matrix);
this.curveTo(150, 50, 200, 100);
this.curveTo(250, 150, 200, 200);
this.curveTo(150, 250, 100, 200);
this.curveTo(50, 150, 100, 100);
this.endFill() ;
Чтобы лучше разобраться, как градиент заполняет область, можно поэкспериментировать с различными значениями и посмотреть, как они влияют на результат. Например, в строке matrix в ActionScript выше приравняйте r к Math.PI. Вы увидите, что градиент развернется на 180 градусов (pi радиан).

Также интересно поменять местами X и Y. Здесь мы переместили радиальное заполнение на край нашей фигуры.
this.moveTo(100, 100);
colors = [0xFFE4E1, 0xff6600];
alphas = [100, 100];
ratios - [23, 255];
matrix = {matrixType:"box", x:100, y:30, w:100, h:100, r:1};
beginGradientFill("radial", colors, alphas, ratios, matrix);
this.curveTo(150, 50, 200, 100);
this.curveTo(250, 150, 200, 200);
this.curveTo(150, 250, 100, 200);
this.curveTo(50, 150, 100, 100);
this.endFill();

На первый взгляд этот метод кажется сложным, но если разобраться в том, как влияют числа на конечный результат, все становится понятно. Вы можете создать функцию enterFrame, которая будет изменять эти значения. Немного поэкспериментировав, можно добиваться довольно необычных эффектов.
Представленные средства рисования очень полезны, но вам наверняка потребуется создание функций, которые будут комбинировать их возможности. Например, если нужно нарисовать квадрат, вовсе не обязательно выполнять каждый раз одну и ту же процедуру, заключающуюся в установке цвета заливки и lineStyle, перемещении точки рисования, рисовании линий и заливки. Проще создать функцию, которой будут передаваться все параметры для рисования квадрата, после чего мы будем получать уже готовый результат.
При создании таких функций первое, что нужно сделать - это выделить все параметры, которые нам могут понадобиться. Нам нужны координаты X и Y, ширина, высота, цвет заливки или ее интенсивность, цвет линий, ширина и интенсивность.
MovieClip.prototype.drawSquare = function(x, y, w, h, fillCol,
fillAlpha, lineCol, lineWeight, lineAlpha) {
};
Порядок расположения параметров в функции очень важен. Например, нам нужно просто отобразить квадрат без линии вокруг его края. Вместо создания отдельной функции для рисования квадрата без рамки мы можем передать все параметры нового стиля в конце определения нашей функции и пропускать их при вызове функции. В этом случае значения lineCol, lineWeight и lineAlpha будут отображаться как "undefined", и рамка не будет прорисовываться.
Внутри функции мы, во-первых, должны установить lineStyle и цвет заливки, а также переместить точку рисования на позицию (X, Y), которую мы указали.
MovieClip.prototype.drawSquare = function(x, y, w, h, fillCol,
fillAlpha, lineCol, lineWeight, lineAlpha) {
this.moveTo(x, y);
// check if a line colour has been specified
if (lineCol) {
this.lineStyle(lineWeight, lineCol, lineAlpha);
} else {
this.lineStyle();
}
this.beginFill(fillCol, fillAlpha);
};
Мы проверяем, был ли передан аргумент lineCol. Если это так, то настраиваем lineStyle соответствующим образом. Если нет, вызываем lineStyle без параметров для очистки lineStyle, которая уже может быть настроена для данного фильма.
Другим моментом, на котором основывается наше решение, является то, передает ли пользователь аргумент lineAlpha (будет ли lineAlpha по умолчанию нулем или нет). Мы, конечно, мы могли бы оградиться от этого и изменить функцию по умолчанию на 100, если lineCol передается, а lineAlpha - нет. Осталось проверить, определена ли lineAlpha, и предпринять соответствующие действия.
MovieClip.prototype.drawSquare = function(x, y, w, h, fillCol,
КfillAlpha, lineCol, lineWeight, lineAlpha) {
this.moveTo(x, y) ;
if (lineCol != undefined){
if (lineAlpha == undefined) {
lineAlpha = 100;
}
this.lineStyle(lineWeight, lineCol, lineAlpha);
} else {
this.lineStyle ();
}
this.beginFill(fillCol, fillAlpha);
};
Теперь нам нужно прорисовать линии, чтобы отгородить область для заливки. Мы начнем с левого верхнего угла и будем двигаться вокруг квадрата по часовой стрелке, прорисовывая линию каждого угла по очереди. Полезно разобраться в том, как здесь указываются координаты.
Теперь нам просто нужно нарисовать линию для каждой из этих точек по очереди и затем завершить заполнение.
MovieClip.prototype.drawSquare = function(x, y, w, h, fillCol,
КfillAlpha, lineCol, lineWeight, lineAlpha) {
this.moveTo(x, y);
if (lineCol != undefined) {
if (lineAlpha == undefined) {
lineAlpha = 100;
}
this.lineStyle(lineWeight, lineCol, lineAlpha);
} else {
this.lineStyle();
}
this.beginFill(fillCol, fillAlpha);
// top right
this.lineTo(x+w, y);
// bottom right
this.lineTo(x+w, y+h);
// bottom left
this.lineTo(x, y+h);
// top left.
this.lineTo(x, y);
// end the fill
this.endFill();
};
Наконец, нам нужно вызвать
_root.drawSquare (100, 100, 200, 100, 0xFF0000, 100, 0xdddddd, 20, 50) ;
Вы заметите, что рамка, созданная с помощью lineTo, выровнена по центру края квадрата, и если бы у нашей рамки была толщина в 20 пикселей, квадрат был бы на десять пикселей шире с каждой стороны. Углы рамки закруглены, что может быть излишним. Чтобы избежать этого, можно изменить метод так, чтобы сначала прорисовывался квадрат для рамки, а затем уже квадрат поверх него для заливки.
В конечном счете, настройка метода определяется тем, как вы собираетесь его использовать. Например, вы можете указывать значения для левого, правого, нижнего и верхнего краев вместо X, Y, ширины и высоты (если бы нужно было использовать его со значениями, возвращаемыми функцией ). Это несложно.
MovieClip.prototype.drawSquare = function(left, right, top, bottom,
КfillCol, fillAlpha, lineCol, lineWeight, lineAlpha) {
this.moveTo(left, top);
if (lineCol != undefined) {
if (lineAlpha == undefined) {
lineAlpha = 100;
}
this.lineStyle(lineWeight, lineCol, lineAlpha);
} else {
this.lineStyle();
}
this.beginFill(fillCol, fillAlpha);
this.lineTo(right, top);
// top right
this.lineTo(right, bottom);
// bottom right
this.lineTo(left, bottom);
// bottom left
this.lineTo(left, top);
// top left
this.endFill();
};
И далее вызов.
// a square with left edge at 100, right edge at 200, top at // 200 and bottom at 300: this.drawSquare(100,200,200,300,0xff0000,100)
Можно применять другие цвета, интенсивность заполнения и т.д. - все зависит от того, как вы планируете использовать данный метод. Здесь нет правильного или неправильного пути, вы просто конструируете его под ваши нужды.
Теперь мы рассмотрим метод, который позволяет рисовать окружности с помощью API- рисования. Он более "хитрый". Многие методы рисования окружностей зависят от использования curveTo для формирования круга посредством рисования дуг. Этот же метод основан на принципе закругления концов линии. Если нарисовать линию, имеющую ширину в 100 пикселей, она может послужить основой для круга радиусом 100; функция Дэна рисует 0,15 пикселей от текущей точки рисования, что формирует прекрасный круг.
Параметры, передаваемые функции, являются координатами X и Y центра круга, а cWidth - ширина окружности.
function drawCircle(x, y, radius, cWidth) {
me = _root.createEmptyMovieClip("circle"+cnt,++cnt);
me.lineStyle(radius, 0x000000, 100);
me.moveTo(x, y);
me.lineTo(x, y+.15);
me.lineStyle(radius-cWidth, 0xffffff, 100);
me.moveTo(x, y);
me.lineTo(x, y+.15);
}
drawCircle(100, 100, 100, 20);

В этом методе окружность расширена во внешнюю сторону от круга и включена в общий радиус. Мы также создаем фильм, в котором и рисуем круг.
Преобразуем эту функцию так, чтобы она работала как наши предыдущие функции, и затем добавим возможность указания цветов:
MovieClip.prototype.drawCircle = function (x, y, radius, cWidth) {
this.lineStyle(radius, 0x000000, 100);
this.moveTo(x, y);
this.lineTo(x, y+.15);
this.lineStyle(radius-cWidth, 0xffffff, 100);
this.moveTo(x, y);
this.lineTo(x, y+.15);
};
drawCircle(100, 100, 100, 20);
Теперь добавим цвета:
MovieClip.prototype.drawCircle = function(x, y, radius,
КcWidth, innerCol, outerCol) {
this.lineStyle(radius, outerCol, 100);
this.moveTo(x, y);
this.lineTo(x, y+.15);
this.lineStyle(radius-cWidth, innerCol, 100);
this.moveTo(x, y);
this.lineTo(x, y+.15);
};
drawCircle(100, 100, 100, 10, 0xff0000, 0x000000);

Здесь можно поэкспериментировать с порядком параметров, указав в первую очередь цвет заливки и радиус, а потом уже ширину окружности и ее цвет. Вы также можете изменить функцию так, чтобы можно было изменять цвет заполнения и рамки. Тогда можно нарисовать окружность без заливки.
Мы настроили работу функции curveTo, указали начальную точку, конечную точку и точку управления. Но иногда полезнее проводить кривую через указываемую точку, поэтому мы создадим функцию для достижения этого результата.
Функция curveTo во Flash создает то, что называется квадратным уравнением для кривой Безье. Раньше кривые линии рисовали, проставляя серию точек на кривой, а затем воспризводя линии фильмов между этими точками, что достигалось с помощью уравнения кривой Безье.
С помощью этого уравнения указывается конечная точка, точка контроля и начальная точка. Переменной в этом уравнении является t, которая изменяет значения от 0 до 1 от начала кривой и до ее конца. Мы можем вставлять различные значения t для выяснения координат любой отдельной точки на кривой.
| x | Положение по оси X, через которое проходит кривая за в t |
| x0 | Начальная точка кривой по оси X |
| x1 | Контрольная точка прохождения кривой по оси X |
| X2 | Конечная точка кривой по оси X |
| y | Положение по оси Y, через которое проходит кривая в t |
| Y0 | Начальная точка кривой по оси Y |
| Y1 | Контрольная точка прохождения кривой по оси Y |
| Y2 | Конечная точка кривой по оси Y |
| t | Время |
Приведем наше уравнение.
x = x0*t*t + x1*2*t*(1-t) + x2*(1-t)*(1-t) y = y0*t*t + y1*2*t*(1-t) + y2*(1-t)*(1-t)

Это уравнение полезно для поиска отдельной точки, через которую проходит кривая, в любой точке t, от 0 до 1, т.е. от начала и до конца кривой. Мы указываем точку начала, точку контроля, конечную точку и t для перехода к позиции (X, Y) (в которой кривая проходит через эту точку).
Нам нужно изменить функцию таким образом, чтобы можно было указывать значения для точки начала (x0,y0), конца (x2,y2) и отдельной точки кривой (X, Y) и перейти в нужную точку контроля (x1,y1). Другими словами, нужно переработать функцию так, чтобы она выглядела примерно следующим образом.
x1= умноженное на x0, x2, x и t y1= умноженное на y0, y2, y и t
Это разумное упрощение. Мы рассмотрим его для уравнения для X и затем продублируем наши результаты для Y, так как уравнения идентичны. Прежде всего, нам нужно получить значения x1 и y1 в левой части уравнения. Это мы сделаем взаимным уничтожением с обеих сторон:
x - x1*2*t*(1-t) = x0*t*t + x1*2*t*(1-t) + x2*(1-t)*(1-t) - x1*2*t*(1-t)
Значения плюс и минус x1*2*t*(1-t) в правой части взаимно компенсируют друг друга:
x - x1*2*t*(1-t) = x0*t*t + x1*2*t*(1-t) + x2*(1-t)*(1-t) х1*2*t(1-t) x - x1*2*t*(1-t) = x0*t*t + x2*(1-t)*(1-t)
Теперь вычтем x из обеих сторон:
x - x1*2*t*(1-t) - x = x0*t*t + x2*(1-t)*(1-t) - x x - x1*2*t*(1-t) -x = x0*t*t + x2*(1-t)*(1-t) - x -x1*2*t*(1-t) = x0*t*t + X2*(1-t)*(1-t) - x -1*x1*2*t*(1-t) = x0*t*t + x2*(1-t)*(1-t) - x
Умножим -1 на 2 в левой части уравнения:
x1* - 2*t*(1-t) = x0*t*t + x2*(1-t)*(1-t) - x
Далее, делим обе части уравнения на (-2*t*(1-t) ):
x1*(-2*t*(1-t)) / (-2*t*(1-t)) = =(x0*t*t + x2*(1-t)*(1-t) - x) / (-2*t*(1-t))
С левой стороны имеем (-2*t*(1-t)) / (-2*t*(1-t)), что дает 1, поэтому можно произвести сокращение:
x1 (- 2 * t * (1 - t)) / ( - 2 * t * (1 - t) ) = =(x0*t*t + x2*(1-t)*(1-t) - x) / (-2*t*(1-t)) x1 = (x0*t*t + x2*(1-t)*(1-t)-x) / (-2*t*(1-t))
Мы получили уравнение для нахождения x1, а уравнением для y1 будет следующее:
y1 = (y0*t*t + y2*(1-t)*(1-t) - y) / (-2*t*(1-t))
Теперь можно использовать полученные результаты для создания функции, которая будет передавать значения x, y, x0, y0, x2, y2 и t для рисования кривой из (x0,y0) в (x2,y2), проходящей через точку (x,y) в точке на прямой, указываемой t.
Истинная роль t станет вам понятнее, когда вы начнете вставлять числа, которые будут влиять на форму кривой. Переименуем значения на a, b и c в нашей функции, для простоты. Мы будем вызывать функцию aToBThroughC чтобы выяснить значение каждой из величин. Приведем уравнение с добавленными a, b и c:
controlX = (ax*t*t + bx*(1-t)*(1-t) - cx) / (-2*t*(1-t)) controlY = (ay*t*t + by*(1-t)*(1-t) - cy) / (-2*t*(1-t))
Теперь перейдем к самой функции. Для простоты предположим, что мы настроили lineStyle.
MovieClip.prototype.aToBThroughC =
function (ax, ay, bx, by, ex, cy,t) {
var controlX = (ax*t*t+bx*(1-t)*(1-t)-cx)/(-2*t*(1-t));
var controlY = (ay*t*t+by*(1-t)*(1-t)-cy)/(-2*t*(1-t));
this.moveTo(ax, ay);
// for security
this.curveTo(controlx, controly, bx, by);
};
Для проверки работы введите следующий код.
this.lineStyle (27, 0xff0000); this.aToBThroughC (100, 100, 250, 100, 200, 350, 0.5);
Сохраните ваш файл под именем AtoBthroughC.fla и запустите его. Мы создали сильно изогнутую кривую

Чтобы показать корректность работы нашей функции, мы откроем созданный нами ранее файл curve with anchor.fla, и изменим его так, чтобы третья, перетаскиваемая, точка была точкой, через которую проходит кривая, а не точкой контроля. Измененный код выделен жирным шрифтом:
_quality = "LOW";
MovieClip. prototype. aToBThroughC = function (ax, ay, bx, by, ex, cy, t) {
var controlX = (ax*t*t+bx*(1-t)*(1-t)-cx)/(-2*t*(1-t));
var controlY = (ay*t*t+by*(1-t)*(1-t)-cy)/(-2*t*(1-t));
this.moveTo(ax, ay);
// for security
this.curveTo(controlx, controly, bx, by);
};
initObj = {onPress:dragOn, onRelease:dragOff,onReleaseOutside:dragOff,
КuseHandCursor: false};
this.attachMovie("point", "start_mc", 1, initObj);
this.attachMovie("point", "end_mc" , 2, initObj);
this.attachMovie("point", "control_mc", 3, initObj);
function dragOn() {
this.onMouseMove = dragMe;
}
function dragOff() {
delete this.onMouseMove;
}
function dragMe() {
this._x = _root._xmouse;
this._y = _root ._ymouse;
this._parent.reDraw();
}
function reDraw() {
this.clear();
this.lineStyle(2, 0xFF5555, 100);
this.aToBThroughC(start_mc._x, start_mc._y, end_mc._x, end_mc._y,
Кcontrol_mc._x, control_mc._y, 0.5);
}
Вы увидите, что при перетаскивании точек кривая теперь всегда проходит через третью точку.

Задав другое значение t, вы увидите, что кривая изменила форму.
this.aToBThroughC(start_mc._x, start_mc._y, end_mc._x, end_mc._y, Кcontrol_mc._x, control_mc._y, 0.1); }
Переменная t может иметь любое значение между 0 и 1, поэтому здесь может быть огромное количество кривых, которые будут проходить через нашу точку c - по одной для каждого значения между 0 и 1.
В этом параграфе мы создадим несложное приложение, в котором можно будет рисовать изображения и сохранять результаты для дальнейшего просмотра. Задача разбивается на 3 этапа.
Вы не найдете ничего нового в этом приложении, однако оно поможет разобраться вам в методологии и поможет изучить работу общих объектов. Это новая мощная возможность Flash MX.
Простое приложение для рисования состоит из тринадцати строк кода. Вот принцип его работы:
Для этого нам нужны три функции: одна для обработки щелчка пользователя, другая для отпускания пользователем кнопки мыши, и третья для записи позиции указателя мыши при нажатой кнопке.
function drawOn() {
this.lineStyle (0x000000);
this.moveTo(this._xmouse, this._ymouse);
this.onMouseMove = addPoint;
}
function addPoint() {
this.lineTo(this._xmouse, this._ymouse);
}
function drawOff() {
delete this.onMouseMove;
}
this.onMouseDown = drawOn;
this.onMouseUp = drawOff;
С помощью onMouseDown устанавливается lineStyle и точка рисования перемещается туда, где находится мышь, а также onMouseMove устанавливается в addPoint.
В тот момент, когда пользователь двигает мышь, рисуется линия к новой позиции указателя мыши. Когда пользователь отпускает кнопку мыши, управляющий элемент onMouseMove удаляется.
Введите код в панель Actions нового фильма, сохраните его в файле doDrawing.fla и запустите его.

Мы получили простой интерфейс рисования, состоящий всего лишь из тридцати строк.
Теперь рассмотрим возможность сохранения и воспроизведения создаваемых рисунков. Для этого нам нужно помещать координаты, соответствующие рисунку, в массив. Нам также нужно будет записывать передвижение пользователем указателя мыши без рисования линии. С этой целью мы введем специальное значение "break", которое будет означать, что карандаш не задействован и перемещен в какое-либо место. Добавленный код выделен жирным шрифтом.
function drawOn() {
this.lineStyle(1, 0x000000);
this.moveTo(this._xmouse, this._ymouse);
// add the new point to the array
tempArr.push({x:_root._xmouse, у:_root._ymouse});
this.onMouseMove = addPoint;
}
function addPoint() {
// add the new point to the array
tempArr.push ({x:_root._xmouse, у:_root._ymouse});
this.lineTo(_root._xmouse, _root._ymouse);
}
function drawOff() {
// the pen is lifted so we add the value "break" to the array
tempArr.push("break");
delete this.onMouseMove;
}
tempArr = [];
this.onMouseDown = drawOn;
this.onMouseUp = drawOff;
Мы создали массив tempArr для хранения всех координат в объектах с параметрами X и Y.
Сохраните ваш фильм в файле doAndStoreDrawing.fla. Если вы запустите фильм и выберете команду меню Debug > List Variables, вы увидите все координаты нарисованных вами точек в окне Output.

Перед тем, как рассматривать восстановление рисунка из этих координат, изучим использование общих объектов для хранения переменных.
Общие объекты позволяют хранить данные локально, на жестком диске пользователя.
Грубо говоря, общие объекты являются своего рода cookies для Flash. Они позволяют нам локально хранить любые данные наших Flash-фильмов, и работают в любых браузерах, равно как и локальный Flash Player.
Итак, общие объекты могут быть использованы для хранения данных, представляющих собой рисунок, созданный в приложении при помощи рисования API. Общие объекты могут также использоваться в онлайн-формах для запоминания предыдущих записей пользователей и
Мы не будем разбираться в сложных деталях использования общих объектов, мы изучим создание общего объекта и обеспечение его работы. Если вы хотите узнать больше об общих объектах и их применении, вам стоит обратиться к сайту по этой ссылке: www.macromedia.com/support/flash/action_scripts/local_shared_object.
Мы начнем с очень простого приложения.
visit number.Мы используем общий объект для хранения числа просмотров страницы. Это элементарное приложение, но оно содержит все необходимое для продолжения работы с приложением рисования.
sharedObject с помощью SharedObjec.getLocal. Это действие вернет объект, если он уже был создан, а если он еще не создавался, он будет создан. Введите следующий код на панели Actions:mySharedObj = SharedObject.getLocal ("visits");
Теперь мы имеем копию общего объекта в переменной mySharedObj. mySharedObj - это объект, которому вы можете присваивать параметры, как любому другому объекту. Это могут быть переменные, массивы и т.д. Переданный параметр "visits" является именем общего объекта, что позволяет иметь несколько общих объектов для каждого проекта.
mySharedObj = SharedObject.getLocal("visits");
//we increment a variable "visitCount" inside "data" where
//all the data resides in a shared object
mySharedObj.data.visitCount++;
visited.text = mySharedObj.data.visitCount;
sharedObject, синхронизируя его, если нужно, с использованием метода flush, который возвращает все из mySharedObj обратно в текущий общий объект. Добавьте последнюю строку сценария в панель Actions.mySharedObj = SharedObject.getLocal("visits");
mySharedObj.data.visitCount++;
visited.text = mySharedObj.data.visitCount;
mySharedObj.flush();
sharedObj basics.fla. Если вы запустите фильм несколько раз, вы увидите, что число будет увеличиваться (если вы не игнорировали запрос безопасности, который мы будем рассматривать и обрабатывать в реальных условиях).
На примере рассмотренного приложения становится ясно, что сохранение рисунков в приложении заключается просто в сохранении массива данных в общем объекте.
Мы создадим интерфейс, содержащий все локально сохраненные изображения, и затем обеспечим возможность либо рисования нового рисунка, либо просмотра старого.
Приведем структуру того, что мы хотим сделать:
Главная страница:
Возможности:
Панель, содержащая список рисунков из sharedObject с полосой прокрутки.
Опции:
Выбрать имеющийся рисунок - перейти к странице перерисовки.
Создать новый рисунок - перейти к странице создания.
Страница перерисовки:
Возможности:
Перерисовка прежнего рисунка.
Опции:
Вернуться на главную страницу.
Страница создания:
Возможности:
Рисование мышью.
Опции:
Сохранить текущий рисунок - сохранить рисунок в общем объекте - перейти на главную страницу.
Вернуться - возврат на главную страницу.
У нас есть три основных задачи: меню, рисование и перерисовка. Мы можем предположить, какие функции нам потребуются для создания приложения:
| Имя функции | Цель |
|---|---|
init |
Установка некоторых основных управляющих элементов кнопок и вызов drawPanel. |
drawPanel |
Получение данных из объекта sharedObject и отключение кнопки возврата и сохранения. Вызов listDrawings и initScrollers. |
listDrawings |
Добавление текстового поля в меню. |
initScrollers |
Установка полос прокрутки для текстового поля. |
initDraw |
Выключение меню, включение кнопки возврата и сохранения и установка управляющих элементов событий onMouseDown и onMouseUp для реализации рисования. Настройка lineStyle и создание временного массива для хранения точек. |
drawOn |
Начало рисования линии, установка onEnterFrame и addPoint. |
addPoint |
Рисование линии и добавление текущей точки в массив. |
drawOff |
Выключение addPoint. |
save |
Добавление текущего массива точек в sharedObject и вызов backToMain. |
backToMain |
Удаление всех событий кадра и мыши на _root. Вызов drawPanel. |
redraw |
Отключение меню и включение кнопки возврата. Установка onEnterFrame. |
drawNextPoint |
Рисование следующей точки в текущем рисунке. |
Перейдем к работе над полнофункциональным приложением рисования и сохранения рисунков.

saverButton с помощью Property inspector, а инстанс кнопки Return - backButton.Можно было бы использовать для этого программный компонент прокрутки, но компоненты мы будем рассматривать в следующей лекции и пока не будем забегать вперед. Создание фильма почти завершено, осталось только добавить в него заголовок. Мы создали новый слой с именем title и добавили

listingsPanel.Сейчас мы поочередно разберем функции, использованные нами выше, с объяснением некоторых моментов.
function drawPanel() {
// turn off the back button and the save button
backButton._visible = false;
saverButton._visible = false;
// make the menu panel visible
this.listingsPanel._visible = true;
// retrieve the shared object
myPictureObj = SharedObject.getLocal("pictures");
// list any drawings
listDrawings(myPictureObj.data.arrays);
// check if we need to turn on the scrollers
initScrollers();
}
Здесь мы инициализировали общий объект и сохранили его в myPictureObj, а также настроили отображение некоторых элементов рабочего места. Далее мы вызовем listDrawings для просмотра myPictureObj и выяснения количества находящихся там рисунков. Мы запишем наши массивы точек в массив с именем arrays объекта sharedObject и затем передадим этот массив функции listDrawings. Внутри массива arrays будет находиться один массив для каждого рисунка. Вместо создания кнопки для каждого рисунка мы используем функцию asfunction, позволяющую представлять фрагмент текста HTML в виде ссылки на функцию ActionScript. Вот как это делается.
asfunction:functionName, parameter;
_root.redraw и передачи номера записи массива.function listDrawings(pictureArray) {
listingsPanel.lista.htmlText = "";
// loop through the picture array
for (var i = 0; i<pictureArray.length; i++) {
// for each entry in the picture array add another line
// to the text in the textfield
var nexta = "<A HREF='asfunction:_root.redraw,"+i+"'>"+"
Drawing Number "+(i+1)+"</A><b/>";
listingsPanel.lista.htmlText += nexta;
}
}
drawPanel. Она просто настроит отображение кнопок прокрутки в зависимости от того, где мы находимся - вверху или внизу текстового поля, а также от того, может ли поле вместить все содержащиеся в нем строки текста. С помощью with мы перейдем внутрь фильма listingsPanel. Параметр visible инстанса кнопки downScroll устанавливаем на значение on, если значение прокрутки меньше, чем максимально возможное значение прокрутки. Этот же параметр устанавливается на значение on, если текстовое поле было полностью прокручено.function initScrollers() {
with (this.listingsPanel) {
downScroll._visible = lista.scroll<lista.maxscroll;
upScroll._visible = lista.scroll>l;
}
}
Наш список будет выглядеть примерно так.

initDraw - функцию, которая будет вызываться при щелчке пользователя на кнопке new:function initDraw() {
// turn on the back and save buttons
backButton._visible = true;
saverButton._visible = true;
// turn off the menu
_root.listingsPanel._visible = false;
// create an array for the points
tempArr = [];
_root.lineStyle(1, 0x000000);
// set up out mouse event handlers
_root.onMouseDown = drawOn;
_root.onMouseUp = drawOff;
}
Все это вам уже знакомо: сначала настраивается отображение элементов рабочего места так, чтобы были видны кнопки back и save, затем настраивается lineStyle и создается массив для наших точек.
function drawOn() {
this.moveTo(this._xmouse, this._ymouse);
tempArr.push({x:this._xmouse, y:this._ymouse});
this.onMouseMove = addPoint;
}
function addPoint() {
tempArr.push({x:this._xmouse, y:this._ymouse});
this.lineTo(this._xmouse, this._ymouse);
}
function drawOff() {
tempArr.push("break");
delete this.onMouseMove;
}
save и будет сохранять tempArr в общем объекте. Перед сохранением массива мы удаляем последний объект, так как объект точки записывается в массив, когда пользователь нажимает кнопку для ее сохранения (когда происходит onMouseDown ). Если не делать этого, можно столкнуться с проблемами потерянной строки в конце рисунка.function save() {
// remove final element
tempArr.pop();
if (!myPictureObj.data.arrays) {
// if our array for pictures has not yet been created,
// create it
myPictureObj.data.arrays = [];
}
// put the current picture array into the array
// containing all pictures
myPictureObj.data.arrays.push(tempArr);
// update the shared object
myPictureObj.flush();
// return to the menu screen
_root.backToMain();
}
Обратите внимание, что здесь сначала проверяется существование массива arrays, и если массив не существует, то он создается. Затем tempArr помещается в конец этого массива и вызывается flush для сохранения его в объекте. После этого вызывается backToMain для удаления всех управляющих элементов событий, а также весь рисунок в фильме, перед возвращением к началу.
function backToMain() {
delete _root.onEnterFrame;
delete _root.onMouseMove;
delete _root.onMouseDown;
delete _root.onMouseUp;
_root.clear();
_root.drawPanel();
}
redraw для начала перерисовки и drawNextPoint для покадрового продолжения. Перерисовка осуществляется посредством прохода через массив точек и рисования линии от предыдущей точки к текущей в каждом кадре. С помощью break осуществляется переход к точке без рисования линии.function redraw(num) {
backButton._visible = true;
this.listingsPanel._visible = false;
// set count to zero, used to keep track of current point
this.count = 0;
// the array which we are redrawing
this.currentArr = myPictureObj.data.arrays[num];
this.lineStyle (0x000000);
this.moveTo( this, currentArr [0] .x, this .currentArr [0] .y);
// every frame we draw the next point
this.onEnterFrame = drawNextPoint;
}
enterFrame на drawNextPoint.function drawNextPoint() {
this.count++;
// nextEntry is the next point object in the array
var nextEntry = this.currentArr[this.count];
if (nextEntry != "break") {
this.lineTo(nextEntry.x, nextEntry.y);
} else {
// if the nextEntry is "break", we increment count
// and move to the next point.
this.count++;
var nextEntry = this.currentArr[this.count];
this.moveTo(nextEntry.x, nextEntry.y);
}
if (this.count>this.currentArr.length) {
// we have drawn all available points
delete this.onEnterFrame;
}
}
Таким образом, с помощью drawNextPoint мы увеличиваем значение нашего счетчика и устанавливаем переменную nextEntry для указания на следующую запись в массиве. Мы проверяем, равно ли это значение "break" и, если это так, увеличиваем count и переходим к следующей точке в массиве с помощью moveTo. Если оно не равно "break", рисуем линию к новой точке. Наконец, проверяем, достигнут ли конец массива; если да, удаляем функцию onEnterFrame и завершаем выполнение действия.
textField в listingsPanel на HTML-текст и рисовать панель в первый раз.function init() {
this.saverButton.onPress = this.save;
this.backButton.onPress = this.backToMain;
with (this.listingsPanel) {
newButton.onRelease = this.initDraw;
// enable html text in the textfield
lista.html = true;
downScroll.onPress = function() {
// scroll the textfield down
lista.scroll++;
// check if the scrollers should still appear
_root.initScrollers();
};
upScroll.onPress = function() {
lista.scroll--;
_root.initScrollers();
};
}
drawPanel();
}
init ()
Весь код программы находится в файле drawingapp.fla.
Безусловно, можно реализовать все это с помощью готового кода, но знать, как все это выглядит в деталях в среде разработки, очень полезно.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.