Класс SimpleGraph: первый пример
Приложение, созданное в этом примере, будет чертить графики двух "вшитых" в код функций, отслеживать положения точек на них, а также показывать расстояние между ними. Использование данного приложения должно помочь в нахождении самого большого расстояния между двумя кривыми - классической задаче из задачника (в реальной жизни данная задача решается с помощью производных).
Цель данного примера – показать возможности использования класса SimpleGraph, позволяющего создавать более сложные приложения.
Простейший пример использования класса SimpleGraph |
Самое важное свойство класса SimpleGraph – это свойство board, являющееся экземпляром другого класса – GraphingBoard. После обсуждения данного примера мы рассмотрим возможности использования методов класса GraphingBoard для усовершенствования внешнего вида графиков.
Настройки сцены
В этом приложении нам понадобится слайдер – slX и динамическое текстовое поле txtDistance.
Пишем код
Прежде всего, необходимо импортировать классы пакета flashandmath.as3.tools (SimpleGraph входит в состав данного пакета). Помните, что папка flashandmath должна быть в той же папке, что и исходный файл проекта. Ну и кроме этого импортируем дополнительные самого флеша
package { import flashandmath.as3.tools.*; import com.bit101.components.HSlider; import flash.display.Shape; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.text.TextField; import flash.text.TextFieldType; import flash.text.TextFormat; import flash.text.TextFormatAlign; import flash.ui.Keyboard; import teormech.utils.TextUtils; public class Main extends Sprite {
Объявляем необходимые переменные класса:
// Текстовое поле для отображения расстояния между кривыми private var txtDistance:TextField; // Горизонтальный слайдер для обеспечения возможности
// взаимодействия с графиками функций private var slX:HSlider; // Размеры области графика и сам объект класса SimpleGraph
// для отрисовки графиков private var bSize:Number = 300; private var gsimp:SimpleGraph; // Массивы для хранения координат точек графиков функций private var arrPx1:Array; private var arrPx2:Array; // Маркеры для обозначения текущих точек на графике
// и расстояния между ними private var sh1:Shape; private var sh2:Shape; private var shLine:Shape;
Рассмотрим упрощенно принципы построения графиков внутри класса SimpleGraph. Т.к. один объект SimpleGraph может отображать несколько графиков различных функций, то для доступа к ним введено понятие "уровня" (если угодно, "глубины") графика i. Для каждого графика создается и сохраняется массив значений координат точек, доступ к которому можно получить, вызвав метод gsimp.getPixData(i) (где i – "уровень" графика). Размер этого массива определяется свойством numPoints объекта SimpleGraph. Поэтому, если у нашего слайдера диапазон значений будет изменяться от 0 до numPoints, то мы сможем использовать значения положения слайдера, как индекс для точки графика, и тем самым обеспечим их прямую связь.
// Фрагмент метода init() var tempFormat:TextFormat =
new TextFormat("Arial", "14", "0x000000", true); tempFormat.align = TextFormatAlign.CENTER; txtDistance =
TextUtils.createTextField("", 415, 280, tempFormat, 120, 20); addChild(txtDistance); // Создаем экземпляр класса SimpleGraph с областью // для отрисовки графиков 300 на 300 пикселей gsimp = new SimpleGraph(bSize,bSize); gsimp.x = 25; gsimp.y = 10; addChild(gsimp); // Устанавливаем количество точек, по которым строится график, // равным диапазону значений нашего слайдера (см. далее) gsimp.setNumPoints(2*bSize); // Устанавливаем пределы изменения координат на графике gsimp.setWindow("-pi","sqrt(10)","-1.5","1.5"); // Строим графики двух функций // (один синего цвета, второй - зеленого) // Заметьте, что первому графику мы задаем значение глубины // равным 1, а второму 2. // Зная эти значения, мы имеем доступ к этим графикам gsimp.graphRectangular("sin(x)","x",1,2,0x0000AA); gsimp.graphRectangular("cos(x)", "x", 2, 2, 0x00AA00); // Здесь видно, как можно получить данные о координатах // точек графика, передавая методу getPixData в качестве // аргумента значения глубины графика arrPx1 = gsimp.getPixData(1); arrPx2 = gsimp.getPixData(2); // Создаем маркеры точек на графиках // и строим соединяющую их линию sh1 = new Shape(); sh1.graphics.lineStyle(1,0); sh1.graphics.beginFill(0x0000AA); sh1.graphics.drawCircle(0,0,6); sh1.graphics.endFill(); // Здесь видно, как можно получить данные // о координатах точек графика. // Они хранятся в виде вложенных массивов, // первыми элементами которых являются значения // координаты "x", а вторыми – значения "y" (в пикселях) sh1.x = arrPx1[0][0]; sh1.y = arrPx1[0][1]; sh2 = new Shape(); sh2.graphics.lineStyle(1,0); sh2.graphics.beginFill(0x00AA00); sh2.graphics.drawCircle(0,0,6); sh2.graphics.endFill(); sh2.x = arrPx2[0][0]; sh2.y = arrPx2[0][1]; shLine = new Shape(); shLine.graphics.lineStyle(2,0x000000); shLine.graphics.moveTo(sh1.x,sh1.y); shLine.graphics.lineTo(sh2.x,sh2.y); // Создаем слайдер, располагаем его под графиком функции, // устанавливаем его ширину равной ширине графика, а также // задаем ему нужный нам диапазон значений [0; 2 * bSize] slX = new HSlider(this, 25, 330, update); slX.setSliderParams(0, 2 * bSize, 0); slX.width = bSize;
Т.к. свойство board объекта SimpleGraph не является общедоступным, то мы не можем добавлять на него объекты отображения напрямую. Для этого нужно использовать метод addChildToBoard. Преимущество данного способа добавления пользовательской графики в том, что у объекта board есть маска и при использовании метода addChildToBoard она автоматически применяется к ней.
// Функция update вызывается при перетаскивании слайдера. // Используя его положение в качестве индекса в массиве // значений координат точек, мы можем динамически изменять // положения маркеров, отрисовывать линию соединяющую их, // и обновлять значение расстояния между точками графиков private function update(evt:Event):void { var i:int = slX.value; sh1.x = arrPx1[i][0]; sh1.y = arrPx1[i][1]; sh2.x = arrPx2[i][0]; sh2.y = arrPx2[i][1]; shLine.graphics.clear(); shLine.graphics.lineStyle(2,0x000000); shLine.graphics.moveTo(sh1.x,sh1.y); shLine.graphics.lineTo(sh2.x,sh2.y); txtDistance.text = getDistance(); }
Функция getDistance используется из-за того, что значение вертикального расстояния между точками должно выводится не в пикселях, а в математических единицах. Для этого используется метод yfromPix (у него есть "собрат" – метод xfromPix, преобразующий значения горизонтальной координаты).
private function getDistance():String { var dy:Number = Math.abs(gsimp.board.yfromPix(sh1.y) - gsimp.board.yfromPix(sh2.y)); return ("Distance = " + dy.toFixed(2)); }
Теперь рассмотрим некоторые методы класса GraphingBoard.
Настройка внешнего вида графиков с использованием класса GraphingBoard
Как мы видели у объектов класса SimpleGraph есть свойство board, являющееся объектом класса GraphingBoard. Объекты этого класса содержат прямоугольный фон и маску, а также обладают множеством свойств и методов для управления внешним видом графиков.
Немного усовершенствованный пример (внешний вид графика настраивается с помощью методов класса GraphingObject |
Пример «Вертикальное расстояние». Второй подход
Созданному нами приложению «Вертикальное расстояние» в том виде, в каком оно сейчас находится, явно не хватает деталей: мы не видим сетки, меток, обозначений осей и не можем оценить расстояния между точками на глаз. Покажем как все это сделать.
Откроем файл приложения, созданного в предыдущем примере, и добавим следующий код в метод init() (сразу за строкой var arrPx2:Array = gsimp.getPixData(2);):
gsimp.board.changeBackColor(0xFFEEEE); gsimp.board.changeBorderColorAndThick(0xDDDDDD,4); gsimp.board.setAxesColorAndThick(0x777777,2); gsimp.board.setCoordsBoxFormat( 0xEEEEEE, 0xDDDDDD, 0x000000, 12); gsimp.board.drawAxes(); gsimp.board.setGrid(0.5,0.25); gsimp.board.drawGrid(); gsimp.board.setTicks(1,1,10,10); gsimp.board.drawTicks(); gsimp.board.addLabels();
Имена методов класса GraphingBoard говорят сами за себя.
На сегодня, думаю, хватит. Вот исходники к рассмотренным здесь примерам.
В следующих нескольких постах мы закончим рассмотрение примеров использования классов пакета flashandmath и перейдем к чему-нибудь новому и, надеюсь, интересному не только мне.
Комментариев нет:
Отправить комментарий