因项目中需要表示一个业务流程中的3个阶段的状态,想到采用链式的表现方法,每个阶段的状态用一种颜色表示,当流程执行到该阶段后,对应的状态闪烁高亮。
最初的想法是直接继承自Ellipse,直接重写draw 方法,恩 没想到绘制出来的效果都偏离了中心位置。
最后发现是drawX、drawY忘记加上绘制圆圈的半径了~~导致直接基于0,0点绘制,图像整体向左上方偏移。
但是我想要效果更炫一点,给状态点增加点击事件、或者鼠标悬停事件,例如,点击状态改变颜色、或者悬停时提示之类的。
结果,因为Ellipse本身不是交互对象,未继承鼠标相关的事件,然后本人各种给自定义组件加自定义事件,都无法生效。最后,无奈之下将继承的父类改为Graphic,然后遇到了一个新问题,除了第一个绘制出来的图形位置正常外,其他阶段的状态无法正常显示。根据显示重绘区域,最终发现,除第一个组件中的graphics绘制正常外,其他阶段调用组件绘制均变成基于屏幕(舞台)左上角绘制。而本身自定义的State控件显示大小是有设定的,所以导致绘制的对象无法显示。详见下图:
各种debug调试,查看父容器的坐标,绘图坐标,均未发现异常,都是相对坐标啊,但是各种无法生效,被逼之下,又在该自定义控件内部定义了一个私有的group,作为绘图的舞台。
_content=new Group;
......
var cx:Number,cy:Number;
cx=radius;
cy=radius;
_content.graphics.beginFill(stateColor,0.8);
_content.graphics.drawCircle(cx,cy,radius);
_content.graphics.endFill();
这回终于成了!
绘制时调用内置group的graphics绘制,相对坐标正常,最终结果如下:
说明:实现以下功能
1、预定义了4种状态,分别是红#FF7F6B、黄#FFB66B、蓝#53A6BE、绿#58D27D(色表参照:http://paletton.com/#uid=72V0u0kiAFk8FVce5NUmrwOqVte),传入state(0、1、2、3)可以设定不同的状态;
2、通过changeState(_state:int) 方法可以调用批量更改状态、闪烁变化相关颜色赋值,然后重绘状态;
3、通过glowTween(color:uint=0x7CC3D8,maxBlur:int=10, duration:int=100)方法可以添加闪烁效果,cancelGlowTween()方法可以主动取消闪烁效果。
最后,上代码!
package com.css.jlry.suportCom
{
import flash.events.Event;
import flash.filters.GlowFilter;
import flash.utils.clearInterval;
import flash.utils.setInterval;
import spark.components.Group;
import spark.primitives.Graphic;
/**
* normal:#53A6BE\#AFE0EE\#7CC3D8
* state1:#FFB66B\#FFDDBA\#FFC78F
* state2:#FF7F6B\#FFC3BA\#FF9E8F
* state3:#58D27D\#B1F3C5\#80E49E
*/
public class StateSymbol extends Graphic
{
public var stateColor:uint=0x53A6BE;
public var extendColor:uint=0xAFE0EE;
public var radius:Number=10;
public var extendRadius:Number=12;
public var state:int=0;
private var _toggle:Boolean;
private var _blur:Number=2;
private var _glowColor:uint=0x7CC3D8;
private var _maxBlur:int=10;
private var _duration:int=100;
private var _interval:int;
private var _content:Group;
public function StateSymbol()
{
super();
}
override protected function createChildren():void
{
super.createChildren();
changeState(state);
}
override protected function measure():void{
super.measure();
var l:Number=radius*2;
measuredMinHeight=measuredMinWidth=l;
measuredHeight=l;
measuredWidth=l;
}
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void{
super.updateDisplayList(unscaledWidth, unscaledHeight);
var realHeight:Number,realWidth:Number;
realHeight=this.getExplicitOrMeasuredHeight();
realWidth=this.getExplicitOrMeasuredWidth();
this.setActualSize(realWidth,realHeight);
}
public function changeState(_state:int):void{
state=_state;
switch(_state){
case 0:{ //#53A6BE\#AFE0EE\#7CC3D8
stateColor=0x53A6BE;
extendColor=0xAFE0EE;
_glowColor=0x7CC3D8;
break;
}
case 1:{ //#FFB66B\#FFDDBA\#FFC78F
stateColor=0xFFB66B;
extendColor=0xFFDDBA;
_glowColor=0xFFC78F;
break;
}
case 2:{ //#FF7F6B\#FFC3BA\#FF9E8F
stateColor=0xFF7F6B;
extendColor=0xFFC3BA;
_glowColor=0xFF9E8F;
break;
}
case 3:{ //#58D27D\#B1F3C5\#80E49E
stateColor=0x58D27D;
extendColor=0xB1F3C5;
_glowColor=0x80E49E;
break;
}
}
drawState();
}
private function drawState():void{
if(_content){
this.removeElement(_content);
}
_content=new Group;
var cx:Number,cy:Number;
cx=radius;
cy=radius;
_content.graphics.beginFill(stateColor,0.8);
_content.graphics.drawCircle(cx,cy,radius);
_content.graphics.endFill();
var ringR:Number=radius+2
if(extendRadius-ringR<=255){
_content.graphics.lineStyle(extendRadius-ringR,extendColor);
_content.graphics.drawCircle(cx,cy,(ringR+extendRadius)/2);
}
this.addElement(_content);
}
public function glowTween(color:uint=0x7CC3D8,maxBlur:int=10, duration:int=100):void{
cancelGlowTween();
if(_glowColor<0){
_glowColor=color>=0?color:stateColor;
}
_maxBlur=maxBlur;
_duration=duration;
_interval=setInterval(dispatchEnterFrame,_duration);
this.addEventListener(Event.ENTER_FRAME, blinkHandler, false, 0, true);
}
private function dispatchEnterFrame():void{
this.dispatchEvent(new Event(Event.ENTER_FRAME,true));
}
public function cancelGlowTween():void{
clearInterval(_interval);
this.filters=[];
this.removeEventListener(Event.ENTER_FRAME, blinkHandler);
}
private function blinkHandler(evt:Event):void
{
if (_blur >= _maxBlur)
_toggle=false;
else if (_blur <= 2)
_toggle=true;
_toggle ? _blur++ : _blur--;
var glow:GlowFilter=new GlowFilter(_glowColor, 1, _blur, _blur, 2, 2);
this.filters=[glow];
}
}
}
<s:BorderContainer height="80" width="100%"
top="40" borderWeight="1"
borderColor="0x9E92F1" borderAlpha="0.8"
backgroundAlpha="0" borderStyle="inset"
verticalCenter="0" horizontalCenter="0">
<s:layout>
<s:HorizontalLayout gap="5"
verticalAlign="middle" horizontalAlign="center" />
</s:layout>
<!-- --> <suportCom:StateSymbol id="startSymbol" stateColor="0x53A6BE"
extendColor="0xAFE0EE" visible="true"
width="20" height="20" />
<s:Line id="p1Line" width="40" xFrom="0" xTo="0" >
<s:stroke>
<s:SolidColorStroke color="0x333333" weight="2" caps="round"/>
</s:stroke>
</s:Line>
<suportCom:StateSymbol id="middleSymbol" stateColor="0xFFB66B"
extendColor="0xFFDDBA" visible="true"
width="20" height="20"
click="middleSymbol_clickHandler(event)" />
<s:Line id="p2Line" width="40" xFrom="0" xTo="0" >
<s:stroke>
<s:SolidColorStroke color="0x333333" weight="2" caps="round"/>
</s:stroke>
</s:Line>
<suportCom:StateSymbol id="endSymbol" stateColor="0x58D27D"
extendColor="0xB1F3C5" visible="true"
width="20" height="20" click="endSymbol_symbolClickHandler(event)"/>
</s:BorderContainer>
效果:
点击后
考虑追加个toggle方法,点击后 改变是否闪烁,嘿嘿!