[Spark] Стрелочный индикатор.
Запись от alatar размещена 06.12.2012 в 19:05
Этот компонент я написал примерно два года назад. А недавно выдалась свободная минутка и я решил причесать его код и исправить моменты написанные в спешке. Заодно выложил, что можно, в свободный доступ.
Картинка для привлечения внимания:
Фактически это набор базовых классов для создания индикаторов. Все классы намеренно сделаны как можно более простыми в расчете на их расширение для создания более сложных и универсальных.
GaugeBase. Базовый компонент.
Базовый класс для всех индикаторов, наследник SkinnableComponent. Максимально прост, но на его основе можно сделать как круговой, так и линейный индикатор. Все что он делает — это хранит минимальное, максимальное и текущее значение и может посчитать текущее значение в процентах (свойство utilization), а также интерполировать его для создания анимации.
Анимация осуществляется с помощью класса spark.effects.animation.Animation, а также в довесок к GaugeBase был написан вспомогательный класс AnimationTarget (точнее нагло скопирован, без чего можно было бы и обойтись не сделай Adobe свой класс с модификатором internal), который предоставляет для Animation колбеки реакции на события анимации.
CircularGauge.
Круговой стрелочный индикатор, дополняет базовый компонент свойствами startAngle и endAngle, которые ограничивают вращение маркера. Имеет две необязательные части скина: marker (стрелка) и scaleDisplay (шкала). При изменении utilization поворачивает marker на соответствующий угол. Также передает scaleDisplay значения minimum и maximum для построения меток. Marker это любой UIComponent, для которого с помощью свойств transformX и transformY можно задать точку вокруг которой он будет вращаться. Позиционируется всегда в центре компонента.
GaugeScale.
Шкала. Наследник SkinnableComponent, с пятью необязательными частями скина.
ticksDisplay — группа-контейнер для меток. Позиционирование меток определяется layout, присвоенным этой группе в скине. (При наследовании от этого класса можно задать layout в самом компоненте, по аналогии с VGroup/HGroup).
labelsDisplay — группа-контейнер для текстовых меток.
labelPart — фабрика текстовых меток. Текстовые метки должны быть наследниками TextBase.
majorTickPart и minorTickPart — фабрики меток. Метки должны реализовывать IVisualElement.
Текст для меток и мажорные метки генерируются на основании свойств minimum, maximum и stepSize. На текст также можно влиять с помощью задания свойства labelPrecision (задает количество знаков после запятой от 0 до 20) или задать функцию labelFunction следующего вида:
Количество минорных меток можно регулировать с помощью свойства minorTickCount (задает количество минорных меток между двумя мажорными).
EllipticalLayout
Лайаут для позиционирования элементов по кругу. Имеет пару свойств startAngle и endAngle для указания откуда начинать и где заканчивать размещение элементов, свойство rotateElements, указывающее следует ли ориентировать элемент к центру, а также свойство align, указывающее режим позиционирования (inside, outside и center). В дополнение можно задать округление позиции (свойство roundPositions), что приведет к позиционированию элемента по одному из его углов или по центру грани в зависимости от того в какой четверти круга он окажется.
Собственно этих классов уже достаточно для создания простенького индикатора. Примеры скинов:
GaugeScaleSkin:
Код:
<?xml version="1.0" encoding="utf-8"?> <s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:layouts="alatarus.layouts.*"> <!-- host component --> <fx:Metadata> [HostComponent("alatarus.components.GaugeScale")] </fx:Metadata> <!-- SkinParts name=ticksDisplay, type=spark.components.Group, required=false name=majorTickPart, type=mx.core.IFactory, required=false name=labelPart, type=mx.core.IFactory, required=true name=labelsDisplay, type=spark.components.Group, required=false name=minorTickPart, type=mx.core.IFactory, required=false --> <fx:Declarations> <fx:Component id="labelPart"> <s:Label/> </fx:Component> <fx:Component id="majorTickPart"> <s:Rect width="5" height="2"> <s:fill> <s:SolidColor color="0x000000"/> </s:fill> </s:Rect> </fx:Component> </fx:Declarations> <s:Group id="ticksDisplay" left="20" right="20" top="20" bottom="20"> <s:layout> <layouts:EllipticalLayout startAngle="-180" endAngle="0" align="inside" rotateElements="true"/> </s:layout> </s:Group> <s:Group id="labelsDisplay" left="20" right="20" top="20" bottom="20"> <s:layout> <layouts:EllipticalLayout startAngle="-180" endAngle="0" align="outside" rotateElements="false"/> </s:layout> </s:Group> </s:Skin>
Код:
<?xml version="1.0" encoding="utf-8"?> <s:Skin minHeight="50" minWidth="50" xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:components="alatarus.components.*"> <!-- host component --> <fx:Metadata> [HostComponent("alatarus.components.CircularGauge")] </fx:Metadata> <!-- SkinParts name=marker, type=spark.components.supportClasses.GroupBase, required=false name=scaleDisplay, type=alatarus.components.GaugeScale, required=false --> <s:Ellipse left="0" right="0" top="0" bottom="0"> <s:fill> <s:SolidColor color="0xbcd1da"/> </s:fill> </s:Ellipse> <s:Group id="marker" transformX="0" transformY="-5"> <s:Path left="0" right="0" top="0" bottom="0" data="M 0 0 L 60 3 L 65 5 L 60 7 L 0 10 Z"> <s:fill> <s:LinearGradient rotation="90"> <s:GradientEntry color="0xFF0131" ratio="0.4" alpha="1"/> <s:GradientEntry color="0xA00000" ratio="0.5" alpha="1"/> </s:LinearGradient> </s:fill> </s:Path> </s:Group> <components:GaugeScale id="scaleDisplay" left="0" right="0" top="0" bottom="0"/> </s:Skin>
В довесок, для помощи в скинировании, также были дописаны дополнительные примитивы EllipseSlice (рисует сектор круга) и DonutSlice (рисует сектор кольца).
Оба индикатора приведенные в начале, представляют собой один компонент с двумя меняющимися в рантайме скинами собранными из этих компонентов.
Исходники описанных классов можно найти на GitHub https://github.com/alatarus/gauges
Всего комментариев 4
Комментарии
06.12.2012 19:31 | |
Спасибо. Уже знаю где буду использовать.
|
06.12.2012 19:33 | |
Пожалуйста. Но для мобильников надо допилить.
|
06.12.2012 19:45 | |
Цитата:
Но для мобильников надо допилить.
|
06.12.2012 19:57 | |
Скины написать.
|
Последние записи от alatar
- Трансформации вокруг произвольной точки (05.02.2015)
- Декомпозиция матрицы. (25.12.2014)
- Баги TextField в iOS (29.07.2013)
- [Spark] Стрелочный индикатор. (06.12.2012)
- RSLs Monkey Patching (23.01.2012)