DataDrawingCanvas from Ely Greenfield does have beginFill() and beginBitmapFill(), but misses beginGradientFill() and beginShaderFill(). Same with the CartesianDataCanvas and PolarDataCanvas present in Flex since SDK 3.0 which are derived from it.
Modify the DataDrawingCanvas and OpCode classes. Add the BEGIN_GRADIENT_FILL, BEGIN_SHADER_FILL, LINE_BITMAP_STYLE, LINE_GRADIENT_STYLE and LINE_SHADER_STYLE constants to the OpCode class. Modify the collectValues() and render() methods implementation to use them. Add the beginGradientFill(), beginShaderFill(), lineBitmapStyle(), lineGradientStyle() and lineShaderStyle() methods in the DataDrawingCanvas class.
In the
OpCode class, add:
public static const BEGIN_GRADIENT_FILL :int = 14; public static const BEGIN_SHADER_FILL :int = 15; public static const LINE_BITMAP_STYLE :int = 16; public static const LINE_GRADIENT_STYLE :int = 17; public static const LINE_SHADER_STYLE :int = 18;
Edit the
collectValues() method and add:
case BEGIN_GRADIENT_FILL:
split(params.x);
if(_data != undefined)
cache.storeX(_data,-_offset,_offset);
split(params.y);
if(_data != undefined)
cache.storeY(_data,-_offset,_offset);
break;
case BEGIN_SHADER_FILL:
split(params.x);
if(_data != undefined)
cache.storeX(_data,-_offset,_offset);
split(params.y);
if(_data != undefined)
cache.storeY(_data,-_offset,_offset);
break;
NB: LINE_STYLE does not need any code in collectValue(), neither do LINE_BITMAP_STYLE, LINE_GRADIENT_STYLE or LINE_SHADER_STYLE.
Edit the
render() method and add:
public function render(target:DataDrawingCanvas,cache:DataCache):void
{
...
var m:Matrix;
var d:*;
if(params.matrix == null)
m = new Matrix();
else
m = params.matrix.clone();
d = data(params.x);
if(d != undefined)
m.tx = cache.x(d);
m.tx += offset(params.x);
d = data(params.y);
if(d != undefined)
m.ty = cache.y(d);
m.ty += offset(params.y);
...
case BEGIN_GRADIENT_FILL:
g.beginGradientFill(params.type, params.colors, params.alphas, params.ratios, m, params.spreadMethod, params.interpolationMethod, params.focalPointRatio);
break;
case BEGIN_SHADER_FILL:
g.beginShaderFill(params.shader, m);
break;
case LINE_BITMAP_STYLE:
g.lineBitmapStyle(params.bitmapData,m,params.repeat,params.smooth);
break;
case LINE_GRADIENT_STYLE:
g.lineGradientStyle(params.type,params.colors,params.alphas,params.ratios,m,params.spreadMethod,params.joints,params.focalPointRatio);
break;
case LINE_SHADER_STYLE:
g.lineShaderStyle(params.shader, m);
break;
In the
DataDrawingCanvas class, add the
beginGradientFill()
,
beginShaderFill(), lineBitmapStyle(), lineGradientStyle() and lineShaderStyle() methods.
public function beginGradientFill(type:String, colors:Array, alphas:Array, ratios:Array,x:* = undefined,y:* = undefined, matrix:Matrix = null, spreadMethod:String = "pad", interpolationMethod:String = "rgb", focalPointRatio:Number = 0):void {
pushOp(EnhancedCartesianOpCode.BEGIN_GRADIENT_FILL, {type:type, x:x, y:y, colors:colors, alphas:alphas, ratios:ratios, matrix:matrix, spreadMethod:spreadMethod, interpolationMethod:interpolationMethod, focalPointRatio:focalPointRatio});
}
public function beginShaderFill(shader:Shader,x:* = undefined,y:* = undefined, matrix:Matrix = null):void {
pushOp(EnhancedCartesianOpCode.BEGIN_SHADER_FILL, {shader:shader, x:x, y:y, matrix:matrix});
}
public function lineBitmapStyle(bitmapData:BitmapData, matrix:Matrix, repeat:Boolean, smooth:Boolean):void
{
pushOp(OpCode.LINE_BITMAP_STYLE,{bitmapData:bitmapData, matrix:matrix, repeat:repeat, smooth:smooth} );
}
public function lineGradientStyle(type:String, colors:Array, alphas:Array, ratios:Array, matrix:Matrix, spreadMethod:String, joints:String, focalPointRatio:Number):void
{
pushOp(OpCode.LINE_GRADIENT_STYLE,{type:type, colors:colors, alphas:alphas, ratios:ratios, matrix:matrix, spreadMethod:spreadMethod, joints:joints, focalPointRatio:focalPointRatio} );
}
public function lineShaderStyle(shader:Shader, matrix:Matrix):void
{
pushOp(OpCode.LINE_SHADER_STYLE,{shader:shader, matrix:matrix} );
}
It is easy to copy Ely Greenfield's classes and modify the DataDrawingCanvas and OpCode classes implementation. But now, what if tou want to apply the same modifications to the CartesianDataCanvas and PolarDataCanvas classes in the Flex SDK ? You can either 1. Extend these classes or 2. Copy
them, modify them and use registerClass in your application preloader in order to register your own implementation of these classes before the Flex framework initializes (use a static initializer in that case).
NB: The documentation states that beginGradientFill() exists in CartesianDataCanvas and PolarDataCanvas but this is still not true as of Flex SDK 4.5.1
Example of use:
// The DataDrawingCanvas instance allows you draw graphics in the data background using data coordinates as opposed to pixel ones
public var background:DataDrawingCanvas;
var matrix:Matrix = new Matrix();
matrix.createGradientBox(this.width, this.height, Math.PI / 2, 0, 0);
if(topSectionFillColorsData && topSectionFillAlphasData && topSectionFillRatiosData && isTopSectionFillChanged)
{
background.beginGradientFill(GradientType.LINEAR, topSectionFillColorsData, topSectionFillAlphasData, topSectionFillRatiosData, Edge.LEFT, physicalLimit, matrix);
background.moveTo(Edge.LEFT, physicalLimit);
background.lineTo(Edge.RIGHT, physicalLimit);
background.lineTo(Edge.RIGHT, safeOperationLevel);
background.lineTo(Edge.LEFT, safeOperationLevel);
background.lineTo(Edge.LEFT, physicalLimit);
background.endFill();
}
Links:
DataDrawingCanvas
http://flexsamples.blogspot.com/2008/04/flex-easy-custom-charts.html
CartesianDataCanvas
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/charts/chartClasses/CartesianDataCanvas.html
PolarDataCanvas
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/charts/chartClasses/PolarDataCanvas.html
+