📄 zoomablelinechart.as
字号:
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 + -