AS3 - 根据数据最小最大值计算轴的刻度
如果要在Flex/Flash中自行开发图表。则不可避免的要进行值轴的绘制,而值轴中最重要的是要根据数据来确定轴的最小刻度和最大刻度,以及每个刻度的步长。下面提供了一个计算类,可以方便的计算出刻度相关的数据。
计算类:
先看使用方法:
var valueAxis:ValueAxis = new ValueAxis(); valueAxis.getMinMax(4,888); trace("最小刻度值:"+valueAxis.min); //0 trace("最大刻度值:"+valueAxis.max); //900 trace("步长:"+valueAxis.step); //100
计算类:
package { public class ValueAxis { private var _min:Number; private var _max:Number; private var _gridCount:Number; private var _minReal:Number; private var _maxReal:Number; private var _step:Number; private var _maxDecCount:Number; /** * 计算最终的最大最小刻度 */ public function getMinMax(min:Number,max:Number,gridCount:Number = 10):void{ this._max = max; this._min = min; this._gridCount = gridCount; var difE:Number; var maxT:Number; if (_min > _max){ maxT = _max; _max = _min; _min = maxT; }; _minReal = _min; _maxReal = _max; if ((((_min == 0)) && ((_max == 0)))){ _max = 9; }; var initialMin:Number = _min; var initialMax:Number = _max; var dif:Number = (_max - _min); if (dif == 0){ difE = (Math.pow(10, Math.floor((Math.log(Math.abs(_max)) * Math.LOG10E))) / 10); } else { difE = (Math.pow(10, Math.floor((Math.log(Math.abs(dif)) * Math.LOG10E))) / 10); }; if ((((_min < 0)) && ((initialMin >= 0)))){ _min = 0; }; if ((((_max > 0)) && ((initialMax <= 0)))){ _max = 0; }; dif = (_max - _min); difE = (Math.pow(10, Math.floor((Math.log(Math.abs(dif)) * Math.LOG10E))) / 10); _step = (Math.ceil(((dif / _gridCount) / difE)) * difE); var stepE:Number = Math.pow(10, Math.floor((Math.log(Math.abs(_step)) * Math.LOG10E))); var stepExp:String = stepE.toExponential(0); var stepExpArr:Array = stepExp.split("e"); var base:Number = stepExpArr[0]; var mant:Number = stepExpArr[1]; if (base == 9){ mant++; }; stepE = generateNumber(1, mant); var temp:Number = Math.ceil((_step / stepE)); if (temp > 5){ temp = 10; }; if ((((temp <= 5)) && ((temp > 2)))){ temp = 5; }; _step = ((Math.ceil((_step / (stepE * temp))) * stepE) * temp); if (stepE < 1){ _maxDecCount = Math.abs((Math.log(Math.abs(stepE)) * Math.LOG10E)); _maxDecCount = Math.round(_maxDecCount); _step = roundTo(_step, (_maxDecCount + 1)); } else { _maxDecCount = 0; }; _min = (_step * Math.floor((_min / _step))); _max = (_step * Math.ceil((_max / _step))); if ((((_min < 0)) && ((initialMin >= 0)))){ _min = 0; }; if ((((_max > 0)) && ((initialMax <= 0)))){ _max = 0; }; if ((((_minReal > 1)) && (((_max - _minReal) > 1)))){ _minReal = Math.floor(_minReal); }; dif = Math.pow(10, Math.floor((Math.log(Math.abs(_minReal)) * Math.LOG10E))); if (_min == 0){ _minReal = dif; }; if ((((_min == 0)) && ((_minReal > 1)))){ _minReal = 1; }; if ((((_min > 0)) && (((_minReal - _step) > 0)))){ if ((_min + _step) < _minReal){ _minReal = (_min + _step); } else { _minReal = _min; }; }; } /** * 数字格式化 */ private function generateNumber(num:Number, mant:Number):Number{ var n:Number; var zeroes:String = ""; if (mant < 1){ n = (Math.abs(mant) - 1); } else { n = Math.abs(mant); }; var i:Number = 0; while (i < n) { zeroes = (zeroes + "0"); i++; }; if (mant < 1){ return (Number((("0." + zeroes) + String(num)))); }; return (Number((String(num) + zeroes))); } private function roundTo(num:Number, precision:Number):Number{ precision = Math.round(precision); var p:Number = Math.pow(10, precision); return ((Math.round((num * p)) / p)); } public function get min():Number { return _min; } public function set min(value:Number):void { _min = value; } public function get max():Number { return _max; } public function set max(value:Number):void { _max = value; } public function get step():Number { return _step; } public function set step(value:Number):void { _step = value; } } }