⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stackedarealayout.as

📁 用于flash/flex的 as3的 2D图形图像图表的动态生成
💻 AS
字号:
package flare.vis.operator.layout
{
	import flare.scale.LinearScale;
	import flare.scale.OrdinalScale;
	import flare.scale.QuantitativeScale;
	import flare.scale.Scale;
	import flare.scale.TimeScale;
	import flare.util.Arrays;
	import flare.util.Maths;
	import flare.util.Orientation;
	import flare.util.Stats;
	import flare.vis.axis.CartesianAxes;
	import flare.vis.data.NodeSprite;
	
	import flash.geom.Rectangle;
	
	/**
	 * Layout that consecutively places items on top of each other. The layout
	 * currently assumes that each column value is available as separate
	 * properties of individual DataSprites.
	 */
	public class StackedAreaLayout extends Layout
	{
		// -- Properties ------------------------------------------------------
		
		private var _columns:Array;
    	private var _peaks:Array;
    	private var _poly:Array;
		
		private var _orient:String = Orientation.BOTTOM_TO_TOP;
		private var _horiz:Boolean = false;
		private var _top:Boolean = false;
		private var _initAxes:Boolean = true;
		
		private var _normalize:Boolean = false;
		private var _padding:Number = 0.05;
		private var _threshold:Number = 1.0;
		
		private var _scale:QuantitativeScale = new LinearScale(0,0,10,true);
		private var _colScale:Scale;
		
		/** Array containing the column names. */
		public function get columns():Array { return _columns; }
		public function set columns(cols:Array):void {
			_columns = Arrays.copy(cols);
			_peaks = new Array(cols.length);
			_poly = new Array(cols.length);
			_colScale = getScale(_columns);
		}
		
		/** Flag indicating if the visualization should be normalized. */		
		public function get normalize():Boolean { return _normalize; }
		public function set normalize(b:Boolean):void { _normalize = b; }
		
		/** Value indicating the padding (as a percentage of the view)
		 *  that should be reserved within the visualization. */
		public function get padding():Number { return _padding; }
		public function set padding(p:Number):void {
			if (p<0 || isNaN(p) || !isFinite(p)) return;
			_padding = p;
		}
		
		/** Threshold size value (in pixels) that at least one column width
		 *  must surpass for a stack to remain visible. */
		public function get threshold():Number { return _threshold; }
		public function set threshold(t:Number):void { _threshold = t; }
		
		/** The orientation of the layout. */
		public function get orientation():String { return _orient; }
		public function set orientation(o:String):void {
			_orient = o;
			_horiz = Orientation.isHorizontal(_orient);
        	_top   = (_orient == Orientation.TOP_TO_BOTTOM ||
        			  _orient == Orientation.LEFT_TO_RIGHT);
        	initializeAxes();
		}
		
		/** The scale used to layout the stacked values. */
		public function get scale():QuantitativeScale { return _scale; }
		public function set scale(s:QuantitativeScale):void {
			_scale = s; _scale.dataMin = 0;
		}
		
		// -- Methods ---------------------------------------------------------
		
		/**
		 * Creates a new StackedAreaLayout.
		 * @param cols an ordered array of properties for the column values
		 * @param padding percentage of space to leave as a padding margin
		 *  for the stacked chart
		 */		
		public function StackedAreaLayout(cols:Array=null, padding:Number=0.05)
		{
			layoutType = CARTESIAN;
			if (cols != null) this.columns = cols;
			this.padding = padding;
		}
		
		private static function getScale(cols:Array):Scale
		{
			var stats:Stats = new Stats(cols);
			switch (stats.dataType) {
				case Stats.NUMBER:
					return new LinearScale(stats.minimum, stats.maximum, 10, true);
				case Stats.DATE:
					return new TimeScale(stats.minDate, stats.maxDate, true);
				case Stats.OBJECT:
				default:
					return new OrdinalScale(stats.distinctValues, true, false);
			}
		}
		
		/** @inheritDoc */
		public override function setup():void
		{
			if (!_initAxes || visualization==null) return;
			initializeAxes();
			(_horiz ? xyAxes.yAxis : xyAxes.xAxis).showLines = false;
		}
		
		/**
		 * Initializes the axes prior to layout.
		 */
		protected function initializeAxes():void
		{
			if (!_initAxes || visualization==null) return;
			var axes:CartesianAxes = xyAxes;
			if (_horiz) {
				axes.xAxis.axisScale = _scale;
				axes.yAxis.axisScale = _colScale;
			} else {
				axes.xAxis.axisScale = _colScale;
				axes.yAxis.axisScale = _scale;
			}
		}
		
		/** @inheritDoc */
		protected override function layout():void
		{
	        // get the orientation specifics sorted out
	        var bounds:Rectangle = layoutBounds;
	        var hgt:Number, wth:Number;
	        var xbias:int, ybias:int, sign:int, len:int;
	        hgt = (_horiz ? bounds.width : bounds.height);
	        wth = (_horiz ? -bounds.height : bounds.width);
	        xbias = (_horiz ? 1 : 0);
	        ybias = (_horiz ? 0 : 1);
	        sign = _top ? 1 : -1;
	        len = _columns.length;

	        var minX:Number = _horiz ? bounds.bottom : bounds.left;
	        var minY:Number = _horiz ? (_top ? bounds.left : bounds.right)
	                                 : (_top ? bounds.top : bounds.bottom);
	                                 
			// perform first walk to get the data distribution
	        _scale.dataMax = peaks();
	        initializeAxes();
	        
	        // initialize current polygon
	        var axes:CartesianAxes = super.xyAxes;
	        var scale:Scale = (_horiz ? axes.yAxis : axes.xAxis).axisScale;
	        var xx:Number;
	        for (var j:uint=0; j<len; ++j) {
				xx = minX + wth * scale.interpolate(_columns[j]);
	            _poly[2*(len+j)+xbias] = xx;
	            _poly[2*(len+j)+ybias] = minY;
	            _poly[2*(len-1-j)+xbias] = xx;
	            _poly[2*(len-1-j)+ybias] = minY;
	        }
	        
	        // perform second walk to compute polygon layout
	        visualization.data.nodes.visit(function(d:NodeSprite):void
	        {
	        	var obj:Object = _t.$(d);
	        	var height:Number = 0, i:uint;
	        	var visible:Boolean = d.visible && d.alpha>0;
	        	var filtered:Boolean = !obj.visible;
	        	
	        	// set full polygon to current baseline
	            for (i=0; i<len; ++i) {
	            	_poly[2*(len-1-i)+ybias] = _poly[2*(len+i)+ybias];
	            }
	            
	            // if not visible, flatten on current baseline
	        	if (!visible || filtered) {
	        		if (!visible || _t.immediate) {
	        			// if already hidden, skip transitioner
	        			d.points = Arrays.copy(_poly, d.points);
	        		} else {
	        			// otherwise interpolate the change
	        			obj.points = Arrays.copy(_poly, d.props.poly);
	        		}
	        		return;
	        	}
	        	if (d.points == null) d.points = Arrays.copy(_poly);
	        	
	        	// if visible, compute the new heights
	            for (i=0; i<len; ++i) {
	                var base:int = 2*(len+i), h:Number;
	                var value:Number = d.data[_columns[i]];
	                
	                if (_normalize) {
	                	_poly[base+ybias] += sign * hgt * Maths.invLinearInterp(value,0,_peaks[i]);
	                } else {
	                	_poly[base+ybias] += sign * hgt * _scale.interpolate(value);
	                }
	                
	                h = Math.abs(_poly[2*(len-1-i)+ybias] - _poly[base+ybias]);
	                if (h > height) height = h;
	            }
	            
	            // if size is beneath threshold, then hide
	            if (height < _threshold) {
	            	d.visible = false;
	            }
	            
	            // update data sprite layout
	            obj.x = 0; obj.y = 0;
	            if (_t.immediate) {
	            	d.points = Arrays.copy(_poly, d.points);
	            } else {
	            	obj.points = Arrays.copy(_poly, d.props.poly);
	            }
	        }, null, true);
		}
		
		private function peaks():Number
		{
			var sum:Number = 0;
	        
	        // first, compute max value of the current data
	        Arrays.fill(_peaks, 0);
	        visualization.data.nodes.visit(function(d:NodeSprite):void {
	        	if (!d.visible || d.alpha <= 0 || !_t.$(d).visible)
	        		return;
	        	
	        	for (var i:uint=0; i<_columns.length; ++i) {
	        		var val:Number = d.data[_columns[i]];
	        		_peaks[i] += val;
	        		sum += val;
	        	}
	        });
	        var max:Number = Arrays.max(_peaks);
	        
	        // update peaks array as needed
	        // adjust peaks to include padding space
	        if (!_normalize) {
	        	Arrays.fill(_peaks, max);
	            for (var i:uint=0; i<_peaks.length; ++i) {
	                _peaks[i] += _padding * _peaks[i];
	            }
	            max += _padding*max;
	        }
	        
	        // return max range value
	        if (_normalize) max = 1.0;
	        if (isNaN(max)) max = 0;
	        return max;
		}
		
	} // end of class StackedAreaLayout
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -