PDA

View Full Version : Flex custom AS3 component - resize tween help


aftershock
12-14-2006, 02:45 PM
i'm new here so go gental!

I'm developing my first from scratch AS3 component for Flex2. Its a simple single bar that will grow or shrink depending upon a value set.
I have it drawing & displaying on the screen and can alter the bars width using mx.effects.resize however I cannot get it to tween what am i doing wrong? I don't get any errors although I think that I might have a looping issue as it runs very slow in the browser.

Actionscript class:

package components.singlebar
{
import flash.display.DisplayObject;
import mx.core.UIComponent;
import mx.core.IFlexDisplayObject;
import mx.styles.ISimpleStyleClient;
import components.singlebar.skins.programmatic.*;
import mx.effects.Resize;
import flash.events.Event;

/**
* trackSkin
*
* The color class for the background of the track
*/
[Style(name="trackColor", type="Number", format="Color", inherit="no")]

/**
* barSkin
*
* The color class for the bar
*/
[Style(name="barSingleColor", type="Number", format="Color", inherit="no")]

public class BarChartSingle extends UIComponent
{

/**
* variables that hold the class instances of the skins
*/
protected var trackSkin:IFlexDisplayObject;
protected var barSkin:IFlexDisplayObject;
private var resizeBar:Resize;
//holds the previous bar width size
private var _prevBarWidth:Number = 1;
//UIcomponent to hold the moveable bar
private var _content:UIComponent;

/**
* Contstructor
*/
public function BarChartSingle()
{
super();
}

/**
* called by the Flex framework when the component is to create
* any new children.
*/
override protected function createChildren():void
{
super.createChildren();

//create the skins for the graphics
// passing the skinName and the default skin Class name
trackSkin = createSkin( "trackSkin", BarChartSkin );
barSkin = createSkin( "barSingleColor", BarChartSkin );

_content = new UIComponent;
//add barSkin to the UIComponent so we can manipulate it with mx.effects.resize on value change
_content.addChild(DisplayObject(barSkin));

//add the trackskin directly to the displaylist
addChild(DisplayObject(trackSkin));
addChild(_content);

//so we can resize the bar when needed.
resizeBar = new Resize(_content);
}

/**
* createSkin
*
* Creates the given skin. Skin will have a specified style or
* default to the standard one
*/

protected function createSkin( skinName:String, defaultSkin:Class ):IFlexDisplayObject
{
//taken mostly from http://weblogs.macromedia.com/pent/archives/2006/07/writing_flex_2.cfm
//checks to see if the skin is already created
var newSkin:IFlexDisplayObject = IFlexDisplayObject( getChildByName( skinName ));

//if is needs to be created the result from above will be null
if ( !newSkin )
{
//Attempt to get class for skin. If not then use the default class

var newSkinClass:Class = Class( getStyle( skinName ));
if( !newSkinClass ) newSkinClass = defaultSkin;

if ( newSkinClass )
{
//Create an instance of the skin class
newSkin = IFlexDisplayObject( new newSkinClass() );
//defaultSkin is passed in from the statement in createChildren
if( !newSkin ) newSkin = new defaultSkin();

//Set its name so that we can find it in the future
//using getChildName()
newSkin.name = skinName;

//Make the getStyle() calls in the skin class find the styles
//for this instance. Setting the styleName to this means that the
// when the skin code does a getStyle('trackColor') it retrieves the style from this
//BarChartSingle not the skin.

var styleableSkin:ISimpleStyleClient = newSkin as ISimpleStyleClient;
if ( styleableSkin ) styleableSkin.styleName = this;

//make sure the skin is a proper child of the component
//addChild(DisplayObject( newSkin ));
}
}
return newSkin;
}

/**
* measure
*
* Defines the default size of the component.
*/
override protected function measure():void
{
super.measure();

//measuredWidth = measuredMinWidth = 150;
//measuredHeight = measuredMinHeight = 50;
}

/**
* updateDeisplayList
*
* Draws the skin and its elements. Called by the Flex framework
* don't call directly. If re-draw is needed call invalidateDisplayList()
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList( unscaledWidth, unscaledHeight );

//position and track and bar
trackSkin.move(0,0);
_content.move(0,0);
barSkin.move(0,0);

//set the size of the track and bar
trackSkin.setActualSize(unscaledWidth, unscaledHeight);

//work out the height & padding for the bar
var barHeight:Number = unscaledHeight - (_barPadding * 2);
var xOffset:Number = _barPadding;

_content.setActualSize(_prevBarWidth, barHeight);
_content.move(0,xOffset);
barSkin.setActualSize(_content.width, _content.height);

//adjust the value to make sure its within bounds
if( _value < _minimum ) _value = _minimum;
if( _value > _maximum ) _value = _maximum;

//determine the size of the bar
//if ( resizeBar.isPlaying ) resizeBar.end();
resizeBar.widthFrom = _content.width;
resizeBar.widthTo = _value;
resizeBar.duration = 1000;
resizeBar.play();

//set the new value
_prevBarWidth = _value;

}

/**
* value
*
* The value of the bar; Will be within the min and max set in the mxml
*/
private var _value:Number = 0;

[Bindable(event="valueChanged")]
public function get value():Number
{
return _value;
}

public function set value( n:Number ):void
{
_value = n;
invalidateDisplayList();
dispatchEvent( new Event("valueChanged") );
}

/**
* minimum
*
* The smallest allowed value for the bar; default = 0;
*/
private var _minimum:Number = 0;

[Bindable]
public function get minimum():Number
{
return _minimum;
}

public function set minimum( n:Number ):void
{
_minimum = n;
invalidateDisplayList();
}

/**
* maximum
*
* The largest allowed value for the bar; default = 100;
*/
private var _maximum:Number = 100;

[Bindable]
public function get maximum():Number
{
return _maximum;
}

public function set maximum( n:Number ):void
{
_maximum = n;
invalidateDisplayList();
}

/**
* barPadding
*
* The padding on the top and bottom of the bar
* can be used to make it look more spaced out against the track
*/
private var _barPadding:Number = 15;

public function set barPadding( n:Number ):void
{
_barPadding = n;
invalidateDisplayList();
}

}
}



The ActionScript skin file is:

package components.singlebar.skins.programmatic
{
import mx.skins.Border;
import flash.display.Graphics;
import mx.styles.StyleManager;

public class BarChartSkin extends Border
{
public function BarChartSkin()
{
super();

}

/**
* updateDisplayList
* This is where the skin is actually drawn. The colours are
* actually taken from the parent - the BarChart component as specified
* in the MXML. Any style must have a default value.
*/

override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
var trackBgColor:Number = getStyle("trackColor");
if( isNaN(trackBgColor) || !StyleManager.isValidStyleValue(trackBgColor)) trackBgColor = 0xFF00FF;
var barColor:Number = getStyle("barSingleColor");
if( isNaN(barColor) || !StyleManager.isValidStyleValue(barColor)) barColor = 0x88D807;

var g:Graphics = graphics;

g.clear();

// the name property defines which skin is to be drawn

switch ( name )
{
case "trackSkin":
g.lineStyle( 1, 0x606060, 1 );
g.beginFill( trackBgColor, 1 );
g.drawRoundRect(x,y,unscaledWidth,unscaledHeight,1 ,1 );
g.endFill();
break;

case "barSingleColor":
g.lineStyle( 1, 0x88D807, 1 );
g.beginFill( barColor, 1 );
g.drawRoundRect(x,y,unscaledWidth ,unscaledHeight ,1,1 );
g.endFill();
break;
}
}

}
}


Called from my main.mxml by using:
<jmw:BarChartSingle id="barChart1" width="100" height="20" minimum="0" maximum="100" value="20" />

Any help would be great thanks!

aftershock
12-15-2006, 12:50 PM
The reason it was not working was because it was getting stuck in a look within the updateDisplayList method. I cahned the lines in updateDisplayList to be like this:


if( resizeBar.isPlaying ) resizeBar.end();

resizeBar.duration = 1000;
resizeBar.widthFrom = _prevBarWidth;
resizeBar.widthTo = _value;

resizeBar.play();


I still can't work out how to use the easingFunction within actionscript. I have imported mx.effects.easing.* and tried adding:


resizeBar.easingFunction(Bounce.easeOut);


This now errors saying that the "value is not a function". How do I pass it a function??

Tink
12-15-2006, 12:58 PM
resizeBar.easingFunction = Bounce.easeOut;

aftershock
12-15-2006, 01:52 PM
Thanks Tink, just realised what it needed.

However I still dont get any animation it just jumps from one value to another without any easing or tweening?

This code is placed in the components updateDisplayList() method and resizeBar is a UIComponent object. I have a duration set but that makes no difference to the output. Would I have to then cancel the tween somehow, i'm not sure.


if( resizeBar.isPlaying ) resizeBar.end();

resizeBar.duration = 1000;
resizeBar.widthFrom = _prevBarWidth;
resizeBar.widthTo = _value;
resizeBar.easingFunction = Bounce.easeIn;
resizeBar.play();

//set the new value
_prevBarWidth = _value;

cspinillo
12-22-2006, 07:47 PM
I am running into the same issue and it's driving me batty. I'd be curious to know if/how you solved the issue

chearn
12-28-2006, 09:58 PM
From what I understand there are no tween classes yet implemented in AS3.

They may or may not include them in the final release of Flash 9, I think someone just needs to convert Robert Penners easing equations.

Tink
12-28-2006, 10:10 PM
From what I understand there are no tween classes yet implemented in AS3.The Flash team have previewed some tween stuff in Flash 9, copying motion from the timeline and re-creatig it in AS, its not in the version on labs though.

flexy
12-29-2006, 11:39 AM
Yeh I saw that at FOTB, looked really interesting.

Just wondering how bloaty the code will be that it knocks-out...

dr_zeus
12-29-2006, 06:02 PM
I love how everyone still assumes that generated code will be bloated these days.

If I remember correctly, when you copy a motion tween to an AS tween, it ends up in some sort of XML-based state. That might be considered bloaty by some, but motion tweens can be more complex than programmatic tweens.