[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
Комментарии
|
|
|
Спасибо. Уже знаю где буду использовать.
|
|
|
|
Пожалуйста. Но для мобильников надо допилить.
|
|
|
|
Цитата:
Но для мобильников надо допилить.
|
|
|
|
Скины написать.
![]() |
Последние записи от alatar
- Трансформации вокруг произвольной точки (05.02.2015)
- Декомпозиция матрицы. (25.12.2014)
- Баги TextField в iOS (29.07.2013)
- [Spark] Стрелочный индикатор. (06.12.2012)
- RSLs Monkey Patching (23.01.2012)















