You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
8.6 KiB
JavaScript

dojo.provide("dojox.charting.scaler.linear");
dojo.require("dojox.charting.scaler.common");
(function(){
var deltaLimit = 3, // pixels
dc = dojox.charting, dcs = dc.scaler, dcsc = dcs.common,
findString = dcsc.findString,
getLabel = dcsc.getNumericLabel;
var calcTicks = function(min, max, kwArgs, majorTick, minorTick, microTick, span){
kwArgs = dojo.delegate(kwArgs);
if(!majorTick){
if(kwArgs.fixUpper == "major"){ kwArgs.fixUpper = "minor"; }
if(kwArgs.fixLower == "major"){ kwArgs.fixLower = "minor"; }
}
if(!minorTick){
if(kwArgs.fixUpper == "minor"){ kwArgs.fixUpper = "micro"; }
if(kwArgs.fixLower == "minor"){ kwArgs.fixLower = "micro"; }
}
if(!microTick){
if(kwArgs.fixUpper == "micro"){ kwArgs.fixUpper = "none"; }
if(kwArgs.fixLower == "micro"){ kwArgs.fixLower = "none"; }
}
var lowerBound = findString(kwArgs.fixLower, ["major"]) ?
Math.floor(kwArgs.min / majorTick) * majorTick :
findString(kwArgs.fixLower, ["minor"]) ?
Math.floor(kwArgs.min / minorTick) * minorTick :
findString(kwArgs.fixLower, ["micro"]) ?
Math.floor(kwArgs.min / microTick) * microTick : kwArgs.min,
upperBound = findString(kwArgs.fixUpper, ["major"]) ?
Math.ceil(kwArgs.max / majorTick) * majorTick :
findString(kwArgs.fixUpper, ["minor"]) ?
Math.ceil(kwArgs.max / minorTick) * minorTick :
findString(kwArgs.fixUpper, ["micro"]) ?
Math.ceil(kwArgs.max / microTick) * microTick : kwArgs.max;
if(kwArgs.useMin){ min = lowerBound; }
if(kwArgs.useMax){ max = upperBound; }
var majorStart = (!majorTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major"])) ?
min : Math.ceil(min / majorTick) * majorTick,
minorStart = (!minorTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major", "minor"])) ?
min : Math.ceil(min / minorTick) * minorTick,
microStart = (! microTick || kwArgs.useMin && findString(kwArgs.fixLower, ["major", "minor", "micro"])) ?
min : Math.ceil(min / microTick) * microTick,
majorCount = !majorTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major"]) ?
Math.round((max - majorStart) / majorTick) :
Math.floor((max - majorStart) / majorTick)) + 1,
minorCount = !minorTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major", "minor"]) ?
Math.round((max - minorStart) / minorTick) :
Math.floor((max - minorStart) / minorTick)) + 1,
microCount = !microTick ? 0 : (kwArgs.useMax && findString(kwArgs.fixUpper, ["major", "minor", "micro"]) ?
Math.round((max - microStart) / microTick) :
Math.floor((max - microStart) / microTick)) + 1,
minorPerMajor = minorTick ? Math.round(majorTick / minorTick) : 0,
microPerMinor = microTick ? Math.round(minorTick / microTick) : 0,
majorPrecision = majorTick ? Math.floor(Math.log(majorTick) / Math.LN10) : 0,
minorPrecision = minorTick ? Math.floor(Math.log(minorTick) / Math.LN10) : 0,
scale = span / (max - min);
if(!isFinite(scale)){ scale = 1; }
return {
bounds: {
lower: lowerBound,
upper: upperBound,
from: min,
to: max,
scale: scale,
span: span
},
major: {
tick: majorTick,
start: majorStart,
count: majorCount,
prec: majorPrecision
},
minor: {
tick: minorTick,
start: minorStart,
count: minorCount,
prec: minorPrecision
},
micro: {
tick: microTick,
start: microStart,
count: microCount,
prec: 0
},
minorPerMajor: minorPerMajor,
microPerMinor: microPerMinor,
scaler: dcs.linear
};
};
dojo.mixin(dojox.charting.scaler.linear, {
buildScaler: function(/*Number*/ min, /*Number*/ max, /*Number*/ span, /*Object*/ kwArgs){
var h = {fixUpper: "none", fixLower: "none", natural: false};
if(kwArgs){
if("fixUpper" in kwArgs){ h.fixUpper = String(kwArgs.fixUpper); }
if("fixLower" in kwArgs){ h.fixLower = String(kwArgs.fixLower); }
if("natural" in kwArgs){ h.natural = Boolean(kwArgs.natural); }
}
// update bounds
if("min" in kwArgs){ min = kwArgs.min; }
if("max" in kwArgs){ max = kwArgs.max; }
if(kwArgs.includeZero){
if(min > 0){ min = 0; }
if(max < 0){ max = 0; }
}
h.min = min;
h.useMin = true;
h.max = max;
h.useMax = true;
if("from" in kwArgs){
min = kwArgs.from;
h.useMin = false;
}
if("to" in kwArgs){
max = kwArgs.to;
h.useMax = false;
}
// check for erroneous condition
if(max <= min){
return calcTicks(min, max, h, 0, 0, 0, span); // Object
}
var mag = Math.floor(Math.log(max - min) / Math.LN10),
major = kwArgs && ("majorTickStep" in kwArgs) ? kwArgs.majorTickStep : Math.pow(10, mag),
minor = 0, micro = 0, ticks;
// calculate minor ticks
if(kwArgs && ("minorTickStep" in kwArgs)){
minor = kwArgs.minorTickStep;
}else{
do{
minor = major / 10;
if(!h.natural || minor > 0.9){
ticks = calcTicks(min, max, h, major, minor, 0, span);
if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
}
minor = major / 5;
if(!h.natural || minor > 0.9){
ticks = calcTicks(min, max, h, major, minor, 0, span);
if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
}
minor = major / 2;
if(!h.natural || minor > 0.9){
ticks = calcTicks(min, max, h, major, minor, 0, span);
if(ticks.bounds.scale * ticks.minor.tick > deltaLimit){ break; }
}
return calcTicks(min, max, h, major, 0, 0, span); // Object
}while(false);
}
// calculate micro ticks
if(kwArgs && ("microTickStep" in kwArgs)){
micro = kwArgs.microTickStep;
ticks = calcTicks(min, max, h, major, minor, micro, span);
}else{
do{
micro = minor / 10;
if(!h.natural || micro > 0.9){
ticks = calcTicks(min, max, h, major, minor, micro, span);
if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
}
micro = minor / 5;
if(!h.natural || micro > 0.9){
ticks = calcTicks(min, max, h, major, minor, micro, span);
if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
}
micro = minor / 2;
if(!h.natural || micro > 0.9){
ticks = calcTicks(min, max, h, major, minor, micro, span);
if(ticks.bounds.scale * ticks.micro.tick > deltaLimit){ break; }
}
micro = 0;
}while(false);
}
return micro ? ticks : calcTicks(min, max, h, major, minor, 0, span); // Object
},
buildTicks: function(/*Object*/ scaler, /*Object*/ kwArgs){
var step, next, tick,
nextMajor = scaler.major.start,
nextMinor = scaler.minor.start,
nextMicro = scaler.micro.start;
if(kwArgs.microTicks && scaler.micro.tick){
step = scaler.micro.tick, next = nextMicro;
}else if(kwArgs.minorTicks && scaler.minor.tick){
step = scaler.minor.tick, next = nextMinor;
}else if(scaler.major.tick){
step = scaler.major.tick, next = nextMajor;
}else{
// no ticks
return null;
}
// make sure that we have finite bounds
var revScale = 1 / scaler.bounds.scale;
if(scaler.bounds.to <= scaler.bounds.from || isNaN(revScale) || !isFinite(revScale) ||
step <= 0 || isNaN(step) || !isFinite(step)){
// no ticks
return null;
}
// loop over all ticks
var majorTicks = [], minorTicks = [], microTicks = [];
while(next <= scaler.bounds.to + revScale){
if(Math.abs(nextMajor - next) < step / 2){
// major tick
tick = {value: nextMajor};
if(kwArgs.majorLabels){
tick.label = getLabel(nextMajor, scaler.major.prec, kwArgs);
}
majorTicks.push(tick);
nextMajor += scaler.major.tick;
nextMinor += scaler.minor.tick;
nextMicro += scaler.micro.tick;
}else if(Math.abs(nextMinor - next) < step / 2){
// minor tick
if(kwArgs.minorTicks){
tick = {value: nextMinor};
if(kwArgs.minorLabels && (scaler.minMinorStep <= scaler.minor.tick * scaler.bounds.scale)){
tick.label = getLabel(nextMinor, scaler.minor.prec, kwArgs);
}
minorTicks.push(tick);
}
nextMinor += scaler.minor.tick;
nextMicro += scaler.micro.tick;
}else{
// micro tick
if(kwArgs.microTicks){
microTicks.push({value: nextMicro});
}
nextMicro += scaler.micro.tick;
}
next += step;
}
return {major: majorTicks, minor: minorTicks, micro: microTicks}; // Object
},
getTransformerFromModel: function(/*Object*/ scaler){
var offset = scaler.bounds.from, scale = scaler.bounds.scale;
return function(x){ return (x - offset) * scale; }; // Function
},
getTransformerFromPlot: function(/*Object*/ scaler){
var offset = scaler.bounds.from, scale = scaler.bounds.scale;
return function(x){ return x / scale + offset; }; // Function
}
});
})();