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

📄 zoomablelinechart.as

📁 FLASH实现的可根据图例个数自动缩放图表宽度组件
💻 AS
📖 第 1 页 / 共 2 页
字号:
import mx.core.UIComponent;
import mx.utils.Delegate;
import webex.Chart;

[IconFile("LineChart.png")]

class webex.zoomableLineChart extends Chart {
	
	/**
	* @private
	* SymbolName for object
	*/
	static var symbolName:String = "LineChartZoomable";
	
	/**
	* @private
	* Class used in createClassObject
	*/
	//static var symbolOwner:Object = LineChart;
	var className:String = "LineChartZoomable";
	
	var hAxis_mc:MovieClip;
	var vAxis_mc:MovieClip;
	
	// -----------------------------
	var __lines:Array = [];
	var __breakPoints:Array = [];	//the data array to hold the breakpoint's index, so it used to control the drawing method.
	var __startPointXLeftAlign:Boolean = true;
	var boundingBox_mc:MovieClip;
	
	function LineChart()
	{
		
	}
	
	function init():Void
	{
		super.init();
		
		boundingBox_mc._visible = false;
	}
	
	function size():Void
	{
		super.size();
		invalidate();
	}
	
	function createChildren():Void
	{
		this.createEmptyMovieClip("hAxis_mc", this.getNextHighestDepth());
	}
	
	function draw():Void
	{
		drawChart();
	}
	
	// -----------------------------------------------------
	
	function getLabelDims(label:String):Object
	{
		this.createTextField("temp_getwidth", this.getNextHighestDepth(), -1000, -1000, 0, 10);
		var o:TextField = this["temp_getwidth"];
		o.text = label;
		o.autoSize = "center";
		o.selectable = false;
		o.setTextFormat(labelFormat);
		var dims:Object = {width:o._width, height:o._height};
		o.removeTextField();
		return dims;
	}
	
	function drawHAxis():Void
	{
		var layout_lineY:Number = 0;
		var layout_markerLineY:Number = layout_lineY + 1;
		var layout_markerLineH:Number = 7;
		var layout_labelY:Number = layout_markerLineY + layout_markerLineH + 2;
		var layout_labelPad:Number = 3;
		
		if (hAxis_mc != undefined) hAxis_mc.removeMovieClip();
		this.createEmptyObject("hAxis_mc", this.getNextHighestDepth());
		
		var w:Number = width;
		var h:Number = height;
		
		// Create 50px margin on left and right
		hAxis_mc._x = 50;
		w -= 100;
		
		// Draw top line
		drawRoundRect(hAxis_mc, 0, layout_lineY, w, layout_lineY+1, 0, lineColor, 100);
		
		// Prepare to draw markers
		var numMarkers:Number = __hPoints.length;
		var sectionW:Number = w / (numMarkers - 1);
		var sectionMargin:Number = sectionW / 2;
		var maxLabelW:Number = sectionW - layout_labelPad;
		var layoutX:Number = 0; // + sectionMargin;
		
		// Determine if stacking is necessary
		var stackLabels:Boolean = false;
		for (var i:Number=0; i<numMarkers; i++)
		{
			var markerLabel:String = __hPoints[i].label;
			var labelW:Number = getLabelDims(markerLabel).width;
			if (labelW > maxLabelW) {
				stackLabels = true;
				break;
			}
		}
		
		// Create labels/markers
		var layout_labelUpperY:Number = layout_labelY;
		var layout_labelLowerY:Number = layout_labelUpperY + 12;
		var layoutYtoUse:String = "upper";
		
		//define the granularity of the labels, when the point count is too much, then throw some of them per step
		var xLabelStep = Math.ceil(numMarkers/30);
		for (var i:Number=0; i<numMarkers; i++)
		{
			var markerLabel:String = __hPoints[i].label;
			var markerLabelName:String = "label" + i + "_txt";

			// Determine positions
			var lineX:Number = Math.round(layoutX - 0.5);
			var labelX:Number = Math.round(layoutX); 
			__hPoints[i].hAxisX = lineX + 50; // Make up for margin
			
			// Draw line
			drawRoundRect(hAxis_mc, lineX, layout_markerLineY, 1, layout_markerLineH, 0, lineColor, 100);
			
			// Create Label
			if(i % xLabelStep ==0)	{	//mode by xlabelStep, so the label will draw per this step
				//Added by Roland Zhu 2006.8.1
				//todo: make the label upper or lower position when "through" some labels
				// Determine label y
				var labelY:Number = (layoutYtoUse=="upper" ? layout_labelUpperY : layout_labelLowerY);
				if (stackLabels) layoutYtoUse = (layoutYtoUse=="upper" ? "lower" : "upper");
			
				hAxis_mc.createTextField(markerLabelName, hAxis_mc.getNextHighestDepth(), labelX, labelY, 0, 10);
				var o:TextField = hAxis_mc[markerLabelName];
				o.text = markerLabel;
				o.autoSize = "center";
				o.selectable = false;
				o.setTextFormat(labelFormat);
			}
			// Increment layoutX
				layoutX += sectionW;
			
		}
		
		hAxis_mc._y = Math.round(height - hAxis_mc._height) - 5;
		
	}
	
	
	function setBreakPoints(breakPoints:Array):Void{
		__breakPoints = breakPoints;
	}
	
	function set breakPoints(breakPoints:Array):Void{
		setBreakPoints(breakPoints);
	}
	
	function convertLineObj(obj:Object):Array
	{
		// Create reference object
		var referenceObj:Object = {};
		for (var i:Number=0; i<__hPoints.length; i++) {
			var tempItem:Object = __hPoints[i];
			referenceObj[tempItem.id] = i;
		}
		// Create ordered array
		var returnArray:Array = [];
		for (var i:String in obj)
		{
			var tempOrder = referenceObj[i];
			var tempVal:Number = obj[i];
			returnArray[tempOrder] = tempVal;
		}
		return returnArray;
	}
	
	function getExtremeValues():Object
	{
		// Concatenate all arrays
		var comboArray:Array = [];
		for (var i:Number=0; i<__lines.length; i++)
		{
			/*Added by Roland Zhu 2006.9.20 this feature only for the Detail Latency Time 
			 *Remove the null value point from __lines.point to make it can calculate the step and the max,min boundary of y axis
			 */
			var retrievedPoints:Array = [];
			for(var j=0; j< __lines[i].points.length;j++){
				if(__lines[i].points[j] != undefined && !isNaN(__lines[i].points[j])){
					retrievedPoints.push(__lines[i].points[j]);
				}
			}
			//comboArray = comboArray.concat(__lines[i].points);
			comboArray = comboArray.concat(retrievedPoints);
		}
		
		// Sort and return extremes
		var sortArray:Array = comboArray.sort(Array.NUMERIC);
		var minNum:Number = sortArray[0];
		var maxNum:Number = sortArray[sortArray.length - 1];
		var returnObj:Object = {min:minNum, max:maxNum};
		return returnObj;
	}
	
	function getGCF(top:Number, bot:Number):Number
	{
        var gcm:Number = 1;
        // Start with biggest possible and work down
        for (var i:Number=top; i>gcm; i--)
		{
			// If i divides into top and bot with no fraction then it is a factor
			if (top%i == 0 && bot%i == 0)
			{
				//the first time this is set the function is done
				gcm = i;
			}
        }
        return gcm;
	}
	
	function getLCD(num1:Number, num2:Number):Number
	{
        // This number will always work, but its not the best
        var lcd:Number = num1*num2;
        var bigNum:Number = Math.max(num1, num2);
        var smallNum:Number = Math.min(num1, num2);
        // Check all numbers between 2 and smallNum to see if they divide
        for (var i:Number=2; i<smallNum; i++)
		{
			while ((lcd%i) == 0 && ((lcd/i)%bigNum) == 0 && ((lcd/1)%smallNum) == 0) {
				// If no remainder is left, then we can lower the lcd
				lcd /= i;
			}
        }
        return lcd;
	}
	
	function getLeastCommonDividend(num:Number):Number
	{
		// Note: this method is dangerous on big numbers...
		// Note: we skip 1, because that's obvious
		for (var i:Number=2; i<((num/2)+2); i++)
		{
			if (num%i==0) {
				break;
			}
		}
		return i;
	}
	
	function getVAxisBounds():Object
	{
		// Get extremes
		var extremeNums:Object = getExtremeValues();
		var minVal:Number = extremeNums.min;
		var maxVal:Number = extremeNums.max;
		
		// See about zero base
		if (zeroBase && minVal >= 0) {
			minVal = 0;
		}		
		
		// Round nums
		var dif:Number = maxVal - minVal;
		var upperBoundary:Number = maxVal + (dif * 0.1);
		var lowerBoundary:Number = minVal - (dif * 0.1);
		
		// Determine declaredBoundaries
		var midMinVal:Number = minVal;
		var midMaxVal:Number = maxVal;
		
		if (midMaxVal.toString().length > 1)
		{
			var upperBoundaryDividend:Number = Math.pow(10, midMaxVal.toString().length - 1); // / (upperBoundary - midMaxVal);
			var declaredUpperBoundary:Number = Math.ceil(midMaxVal / upperBoundaryDividend) * upperBoundaryDividend;
			if (declaredUpperBoundary > upperBoundary)
			{
				upperBoundaryDividend /= 2;
				declaredUpperBoundary = Math.ceil(midMaxVal / upperBoundaryDividend) * upperBoundaryDividend;
			}
		}
		else
		{
			var declaredUpperBoundary:Number = Math.ceil(midMaxVal / 5) * 5;
		}
		
		if (midMinVal.toString().length > 1)
		{
			var lowerBoundaryDividend:Number = Math.pow(10, midMinVal.toString().length - 1);
			var declaredLowerBoundary:Number = Math.floor(midMinVal / lowerBoundaryDividend) * lowerBoundaryDividend;
			if (declaredLowerBoundary < lowerBoundary)
			{
				lowerBoundaryDividend /= 2;
				declaredLowerBoundary = Math.floor(midMinVal / lowerBoundaryDividend) * lowerBoundaryDividend;
			}
		}
		else
		{
			var declaredLowerBoundary:Number = Math.floor(midMinVal / 5) * 5;
		}
		// trace("upper: " + declaredUpperBoundary + " - lower: " + declaredLowerBoundary + " ------ " + upperBoundaryDividend + " - " + lowerBoundaryDividend);
		
		// Determine section step
		var step:Number = getGCF(declaredLowerBoundary, declaredUpperBoundary);
		// trace("gcf: " + gcf);
		
		// Return vals
		var returnObj:Object = {upperBoundary:declaredUpperBoundary, lowerBoundary:declaredLowerBoundary, step:step};
		
		return returnObj;
	}
	
	function getVAxisStep(h:Number):Object
	{
		var bounds:Object = getVAxisBounds();
		var upperBoundary:Number = bounds.upperBoundary;
		var lowerBoundary:Number = bounds.lowerBoundary;
		var step:Number = bounds.step;
		
		// Determine max steps
		
		var maxSteps:Number = Math.floor(h / 20);
		
		// Determine actual steps
		var numSteps:Number = (upperBoundary - lowerBoundary) / step;
		var lcd:Number;
		while (numSteps > maxSteps)
		{
			lcd = getLeastCommonDividend(numSteps);
			if (lcd==numSteps) break; // Can only divide by itself - this should never happen
			step *= lcd;
			numSteps = (upperBoundary - lowerBoundary) / step;
		}
		
		// Return val
		var returnObj:Object = {numSteps:numSteps, step:step, upperBoundary:upperBoundary, lowerBoundary:lowerBoundary};
		
		return returnObj;
	}
	
	function drawVAxis():Void
	{
		// Prepare positioning
		var topPadding:Number = 7;
		var h:Number = height - (height - hAxis_mc._y) - topPadding;
		var w:Number = width - 50; // 50px margin on right
		var leftBlockW:Number = 7;
		
		// Get step info
		var stepObj:Object = getVAxisStep(h);
		var numSteps:Number = stepObj.numSteps;
		var step:Number = stepObj.step;
		var upperBoundary:Number = stepObj.upperBoundary;
		var lowerBoundary:Number = stepObj.lowerBoundary;
		// trace("numSteps: " + numSteps + " - step: " + step);
		
		// Create/Recreate mc
		if (vAxis_mc != undefined) vAxis_mc.removeMovieClip();
		this.createEmptyObject("vAxis_mc", this.getNextHighestDepth());
		
		/*Added by Roland Zhu 2006.8.3
		 *Draw the title of y axis
		 */
		 vAxis_mc.createTextField("vTitle_Txt",vAxis_mc.getNextHighestDepth(),leftBlockW-60,h/2,0,0);
		var vt:TextField = vAxis_mc["vTitle_Txt"];
		vt.embedFonts = true;
		vt.text = __vTitle;
		vt.align = "center";
		vt.setTextFormat(titleFormatBold);
		
		vt._width = vt.textWidth+5;
		vt._height = vt.textHeight +5;
		vt._rotation = -90;
		vt._y = vt._y + vt._height/2;	//make the label align center with the v axis
		
		/*Added by Roland Zhu 2006.8.3
		 *Draw the title of x axis
		 */
		 vAxis_mc.createTextField("hTitle_Txt",vAxis_mc.getNextHighestDepth(),w/2, h+ 40,0,0);
		var ht:TextField = vAxis_mc["hTitle_Txt"];
		ht.embedFonts = true;
		ht.text = __hTitle;
		ht.align = "center";
		ht.setTextFormat(titleFormatBold);
		
		ht._width = ht.textWidth+5;
		ht._height = ht.textHeight +5;
		
		// Draw left block
		drawRoundRect(vAxis_mc, 50-leftBlockW, topPadding + 1, leftBlockW, h-1, 0, lineColor, 100);

⌨️ 快捷键说明

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