Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > alatar

Рейтинг: 5.00. Голосов: 4.

[Spark] Стрелочный индикатор.

Запись от alatar размещена 06.12.2012 в 19:05

Этот компонент я написал примерно два года назад. А недавно выдалась свободная минутка и я решил причесать его код и исправить моменты написанные в спешке. Заодно выложил, что можно, в свободный доступ.

Картинка для привлечения внимания:
GaugeTest.swf   (293.6 Кб)


Фактически это набор базовых классов для создания индикаторов. Все классы намеренно сделаны как можно более простыми в расчете на их расширение для создания более сложных и универсальных.

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 следующего вида:
Код AS3:
function (value:Number):String
Количество минорных меток можно регулировать с помощью свойства 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>
CircularGaugeSimpleSkin:
Код:
<?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>
SimpleSkin.swf   (263.3 Кб)


В довесок, для помощи в скинировании, также были дописаны дополнительные примитивы EllipseSlice (рисует сектор круга) и DonutSlice (рисует сектор кольца).

Оба индикатора приведенные в начале, представляют собой один компонент с двумя меняющимися в рантайме скинами собранными из этих компонентов.

Исходники описанных классов можно найти на GitHub https://github.com/alatarus/gauges
Вложения
Тип файла: swf GaugeTest.swf (293.6 Кб, 1390 просмотров)
Тип файла: swf SimpleSkin.swf (263.3 Кб, 829 просмотров)
Размещено в Flex , Flex 4
Комментарии 4 Отправить другу ссылку на эту запись
Всего комментариев 4

Комментарии

Старый 06.12.2012 19:31 Astraport вне форума
Astraport
 
Аватар для Astraport
Спасибо. Уже знаю где буду использовать.
Старый 06.12.2012 19:33 alatar вне форума
alatar
 
Аватар для alatar
Пожалуйста. Но для мобильников надо допилить.
Старый 06.12.2012 19:45 Astraport вне форума
Astraport
 
Аватар для Astraport
Цитата:
Но для мобильников надо допилить.
В смысле? Что допилить?
Старый 06.12.2012 19:57 alatar вне форума
alatar
 
Аватар для alatar
Скины написать.
 

 


Часовой пояс GMT +4, время: 16:28.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.