axis.as
来自「用于flash/flex的 as3的 2D图形图像图表的动态生成」· AS 代码 · 共 714 行 · 第 1/2 页
AS
714 行
package flare.vis.axis
{
import flare.animate.Transitioner;
import flare.display.TextSprite;
import flare.scale.IScaleMap;
import flare.scale.LinearScale;
import flare.scale.Scale;
import flare.scale.ScaleType;
import flare.util.Arrays;
import flare.util.Stats;
import flare.util.Strings;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.geom.Point;
import flash.text.TextFormat;
import flash.utils.Dictionary;
/**
* A metric data axis consisting of axis labels and gridlines.
*
* <p>Axis labels can be configured both in terms of text formatting,
* orientation, and position. Use the <code>labelOffsetX</code> or
* <code>labelOffsetY</code> property to adjust label positioning. For
* example, <code>labelOffsetX = -10;</code> places the anchor point for
* the label ten pixels to the left of the data bounds, whereas
* <code>labelOffsetX = 10;</code> will place the point 10 pixels to the
* right of the data bounds. One could simultaneously adjust the
* <code>horizontalAnchor</code> property to align the labels as desired.
* </p>
*
* <p>Similarly, axis gridlines can also be configured. The
* <code>lineCapX1</code>, <code>lineCapX2</code>, <code>lineCapY1</code>,
* and <code>lineCapY2</code> properties determine by how much the
* grid lines should exceed the data bounds. For example,
* <code>lineCapX1 = 5</code> causes the grid line to extend an extra
* 5 pixels to the left. Each of these values should be greater than or
* equal to zero.</p>
*/
public class Axis extends Sprite implements IScaleMap
{
// children indices
private static const LABELS:uint = 1;
private static const GRIDLINES:uint = 0;
// axis scale
private var _prevScale:Scale;
// axis settings
private var _xa:Number=0, _ya:Number=0; // start of the axis
private var _xb:Number=0, _yb:Number=0; // end of the axis
private var _xaP:Number=0, _yaP:Number=0; // previous start of the axis
private var _xbP:Number=0, _ybP:Number=0; // previous end of the axis
private var _xd:int, _yd:int; // axis directions (1 or -1)
private var _xlo:Number, _ylo:Number; // label offsets
// gridline settings
private var _lineColor:uint = 0xd8d8d8;
private var _lineWidth:Number = 0;
// label settings
private var _numLabels:int = -1;
private var _anchorH:int = TextSprite.LEFT;
private var _anchorV:int = TextSprite.TOP;
private var _labelAngle:Number = 0;
private var _labelColor:uint = 0;
private var _labelFormat:String = null;
private var _labelTextMode:int = TextSprite.BITMAP;
private var _labelTextFormat:TextFormat = new TextFormat("Arial",12,0);
// temporary variables
private var _point:Point = new Point();
// -- Properties ------------------------------------------------------
/** Sprite containing the axis labels. */
public function get labels():Sprite { return getChildAt(LABELS) as Sprite; }
/** Sprite containing the axis grid lines. */
public function get gridLines():Sprite { return getChildAt(GRIDLINES) as Sprite; }
/** @inheritDoc */
public function get x1():Number { return _xa; }
public function set x1(x:Number):void { _xa = x; }
/** @inheritDoc */
public function get y1():Number { return _ya; }
public function set y1(y:Number):void { _ya = y; }
/** @inheritDoc */
public function get x2():Number { return _xb; }
public function set x2(x:Number):void { _xb = x; }
/** @inheritDoc */
public function get y2():Number { return _yb; }
public function set y2(y:Number):void { _yb = y; }
/** The Scale used to map values to this axis. */
public var axisScale:Scale;
/** Flag indicating if axis labels should be shown. */
public var showLabels:Boolean = true;
/** Flag indicating if labels should be removed in case of overlap. */
public var fixLabelOverlap:Boolean = true;
/** Flag indicating if axis grid lines should be shown. */
public var showLines:Boolean = true;
/** X length of axis gridlines. */
public var lineLengthX:Number = 0;
/** Y length of axis gridlines. */
public var lineLengthY:Number = 0;
/** X offset for axis gridlines at the lower end of the axis. */
public var lineCapX1:Number = 0;
/** X offset for axis gridlines at the upper end of the axis. */
public var lineCapX2:Number = 0;
/** Y offset for axis gridlines at the lower end of the axis. */
public var lineCapY1:Number = 0;
/** Y offset for axis gridlines at the upper end of the axis. */
public var lineCapY2:Number = 0;
/** X-dimension offset value for axis labels. If negative or zero, this
* value indicates how much to offset to the left of the data bounds.
* If positive, the offset is made to the right of the data bounds. */
public var labelOffsetX:Number = 0;
/** Y-dimension offset value for axis labels. If negative or zero, this
* value indicates how much to offset above the data bounds.
* If positive, the offset is made beneath the data bounds.*/
public var labelOffsetY:Number = 0;
/** The line color of axis grid lines. */
public function get lineColor():uint { return _lineColor; }
public function set lineColor(c:uint):void { _lineColor = c; updateGridLines(); }
/** The line width of axis grid lines. */
public function get lineWidth():Number { return _lineWidth; }
public function set lineWidth(w:Number):void { _lineWidth = w; updateGridLines(); }
/** The color of axis label text. */
public function get labelColor():uint { return _labelColor; }
public function set labelColor(c:uint):void { _labelColor = c; updateLabels(); }
/** The angle (orientation) of axis label text. */
public function get labelAngle():Number { return _labelAngle; }
public function set labelAngle(a:Number):void { _labelAngle = a; updateLabels(); }
/** TextFormat (font, size, style) for axis label text. */
public function get labelTextFormat():TextFormat { return _labelTextFormat; }
public function set labelTextFormat(f:TextFormat):void { _labelTextFormat = f; updateLabels(); }
/** The text rendering mode to use for label TextSprites.
* @see flare.display.TextSprite. */
public function get labelTextMode():int { return _labelTextMode; }
public function set labelTextMode(m:int):void { _labelTextMode = m; updateLabels(); }
/** String formatting pattern used for axis labels, overwrites any
* formatting pattern used by the <code>axisScale</code>. If null,
* the formatting pattern for the <code>axisScale</code> is used. */
public function get labelFormat():String {
return _labelFormat==null ? null
: _labelFormat.substring(3, _labelFormat.length-1);
}
public function set labelFormat(fmt:String):void {
_labelFormat = "{0:"+fmt+"}"; updateLabels();
}
/** The number of labels and gridlines to generate by default. If this
* number is zero or less (default -1), the number of labels will be
* automatically determined from the current scale and size. */
public function get numLabels():int {
// if set positive, return number
if (_numLabels > 0) return _numLabels;
// if ordinal return all labels
if (ScaleType.isOrdinal(axisScale.scaleType)) return -1;
// otherwise determine based on axis size (random hack...)
var lx:Number = _xb-_xa; if (lx<0) lx = -lx;
var ly:Number = _yb-_ya; if (ly<0) ly = -ly;
lx = (lx > ly ? lx : ly);
return lx > 200 ? 10 : lx < 20 ? 1 : int(lx/20);
}
public function set numLabels(n:int):void { _numLabels = n; }
/** The horizontal anchor point for axis labels.
* @see flare.display.TextSprite. */
public function get horizontalAnchor():int { return _anchorH; }
public function set horizontalAnchor(a:int):void { _anchorH = a; updateLabels(); }
/** The vertical anchor point for axis labels.
* @see flare.display.TextSprite. */
public function get verticalAnchor():int { return _anchorV; }
public function set verticalAnchor(a:int):void { _anchorV = a; updateLabels(); }
/** The x-coordinate of the axis origin. */
public function get originX():Number {
return (ScaleType.isQuantitative(axisScale.scaleType) ? X(0) : x1);
}
/** The y-coordinate of the axis origin. */
public function get originY():Number {
return (ScaleType.isQuantitative(axisScale.scaleType) ? Y(0) : y1);
}
// -- Initialization --------------------------------------------------
/**
* Creates a new Axis.
* @param axisScale the axis scale to use. If null, a linear scale
* is assumed.
*/
public function Axis(axisScale:Scale=null)
{
this.axisScale = axisScale ? axisScale : new LinearScale();
_prevScale = this.axisScale;
initializeChildren();
}
/**
* Initializes the child container sprites for labels and grid lines.
*/
protected function initializeChildren():void
{
addChild(new Sprite()); // add gridlines
addChild(new Sprite()); // add labels
}
// -- Updates ---------------------------------------------------------
/**
* Updates this axis, performing filtering and layout as needed.
* @param trans a Transitioner for collecting value updates
* @return the input transitioner.
*/
public function update(trans:Transitioner):Transitioner
{
var t:Transitioner = (trans!=null ? trans : Transitioner.DEFAULT);
// compute directions and offsets
_xd = lineLengthX < 0 ? -1 : 1;
_yd = lineLengthY < 0 ? -1 : 1;
_xlo = _xd*labelOffsetX + (labelOffsetX>0 ? lineLengthX : 0);
_ylo = -_yd*labelOffsetY + (labelOffsetY<0 ? lineLengthY : 0);
// run updates
filter(t);
layout(t);
updateLabels(); // TODO run through transitioner?
updateGridLines(); // TODO run through transitioner?
return trans;
}
// -- Lookups ---------------------------------------------------------
/**
* Returns the horizontal offset along the axis for the input value.
* @param value an input data value
* @return the horizontal offset along the axis corresponding to the
* input value. This is the x-position minus <code>x1</code>.
*/
public function offsetX(value:Object):Number
{
return axisScale.interpolate(value) * (_xb - _xa);
}
/**
* Returns the vertical offset along the axis for the input value.
* @param value an input data value
* @return the vertical offset along the axis corresponding to the
* input value. This is the y-position minus <code>y1</code>.
*/
public function offsetY(value:Object):Number
{
return axisScale.interpolate(value) * (_yb - _ya);
}
/** @inheritDoc */
public function X(value:Object):Number
{
return _xa + offsetX(value);
}
/** @inheritDoc */
public function Y(value:Object):Number
{
return _ya + offsetY(value);
}
/** @inheritDoc */
public function value(x:Number, y:Number, stayInBounds:Boolean=true):Object
{
// project the input point onto the axis line
// (P-A).(B-A) / |B-A|^2 == fractional projection onto axis line
var dx:Number = (_xb-_xa);
var dy:Number = (_yb-_ya);
var f:Number = ((x-_xa)*dx + (y-_ya)*dy) / (dx*dx + dy*dy);
// correct bounds, if desired
if (stayInBounds) {
if (f < 0) f = 0;
if (f > 1) f = 1;
}
// lookup and return value
return axisScale.lookup(f);
}
/**
* Clears the previous axis scale used, if cached.
*/
public function clearPreviousScale():void
{
_prevScale = axisScale;
}
// -- Filter ----------------------------------------------------------
/**
* Performs filtering, determining which axis labels and grid lines
* should be visible.
* @param trans a Transitioner for collecting value updates.
*/
protected function filter(trans:Transitioner) : void
{
var ordinal:uint = 0, i:uint, idx:int = -1, val:Object;
var label:AxisLabel = null;
var gline:AxisGridLine = null;
var nl:uint = labels.numChildren;
var ng:uint = gridLines.numChildren;
var keepLabels:Array = new Array(nl);
var keepLines:Array = new Array(ng);
var values:Array = axisScale.values(numLabels);
if (showLabels) { // process labels
for (i=0, ordinal=0; i<values.length; ++i) {
val = values[i];
if ((idx = findLabel(val, nl)) < 0) {
label = createLabel(val);
} else {
label = labels.getChildAt(idx) as AxisLabel;
keepLabels[idx] = true;
}
label.ordinal = ordinal++;
}
}
if (showLines) { // process gridlines
for (i=0, ordinal=0; i<values.length; ++i) {
val = values[i];
if ((idx = findGridLine(val, ng)) < 0) {
gline = createGridLine(val);
} else {
gline = gridLines.getChildAt(idx) as AxisGridLine;
keepLines[idx] = true;
}
gline.ordinal = ordinal++;
}
}
markRemovals(trans, keepLabels, labels);
markRemovals(trans, keepLines, gridLines);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?