198 lines
6.4 KiB
JavaScript
198 lines
6.4 KiB
JavaScript
//>>built
|
|
define("dojox/charting/plot2d/Stacked", ["dojo/_base/lang", "dojo/_base/declare", "dojo/_base/array", "./Default", "./common",
|
|
"dojox/lang/functional", "dojox/lang/functional/reversed", "dojox/lang/functional/sequence"],
|
|
function(lang, declare, arr, Default, dc, df, dfr, dfs){
|
|
/*=====
|
|
var Default = dojox.charting.plot2d.Default;
|
|
=====*/
|
|
var purgeGroup = dfr.lambda("item.purgeGroup()");
|
|
|
|
return declare("dojox.charting.plot2d.Stacked", Default, {
|
|
// summary:
|
|
// Like the default plot, Stacked sets up lines, areas and markers
|
|
// in a stacked fashion (values on the y axis added to each other)
|
|
// as opposed to a direct one.
|
|
getSeriesStats: function(){
|
|
// summary:
|
|
// Calculate the min/max on all attached series in both directions.
|
|
// returns: Object
|
|
// {hmin, hmax, vmin, vmax} min/max in both directions.
|
|
var stats = dc.collectStackedStats(this.series);
|
|
this._maxRunLength = stats.hmax;
|
|
return stats;
|
|
},
|
|
render: function(dim, offsets){
|
|
// summary:
|
|
// Run the calculations for any axes for this plot.
|
|
// dim: Object
|
|
// An object in the form of { width, height }
|
|
// offsets: Object
|
|
// An object of the form { l, r, t, b}.
|
|
// returns: dojox.charting.plot2d.Stacked
|
|
// A reference to this plot for functional chaining.
|
|
if(this._maxRunLength <= 0){
|
|
return this;
|
|
}
|
|
|
|
// stack all values
|
|
var acc = df.repeat(this._maxRunLength, "-> 0", 0);
|
|
for(var i = 0; i < this.series.length; ++i){
|
|
var run = this.series[i];
|
|
for(var j = 0; j < run.data.length; ++j){
|
|
var v = run.data[j];
|
|
if(v !== null){
|
|
if(isNaN(v)){ v = 0; }
|
|
acc[j] += v;
|
|
}
|
|
}
|
|
}
|
|
// draw runs in backwards
|
|
if(this.zoom && !this.isDataDirty()){
|
|
return this.performZoom(dim, offsets);
|
|
}
|
|
this.resetEvents();
|
|
this.dirty = this.isDirty();
|
|
if(this.dirty){
|
|
arr.forEach(this.series, purgeGroup);
|
|
this._eventSeries = {};
|
|
this.cleanGroup();
|
|
var s = this.group;
|
|
df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
|
|
}
|
|
|
|
var t = this.chart.theme, events = this.events(),
|
|
ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
|
|
vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler);
|
|
|
|
for(var i = this.series.length - 1; i >= 0; --i){
|
|
var run = this.series[i];
|
|
if(!this.dirty && !run.dirty){
|
|
t.skip();
|
|
this._reconnectEvents(run.name);
|
|
continue;
|
|
}
|
|
run.cleanGroup();
|
|
var theme = t.next(this.opt.areas ? "area" : "line", [this.opt, run], true),
|
|
s = run.group, outline,
|
|
lpoly = arr.map(acc, function(v, i){
|
|
return {
|
|
x: ht(i + 1) + offsets.l,
|
|
y: dim.height - offsets.b - vt(v)
|
|
};
|
|
}, this);
|
|
|
|
var lpath = this.opt.tension ? dc.curve(lpoly, this.opt.tension) : "";
|
|
|
|
if(this.opt.areas){
|
|
var apoly = lang.clone(lpoly);
|
|
if(this.opt.tension){
|
|
var p=dc.curve(apoly, this.opt.tension);
|
|
p += " L" + lpoly[lpoly.length - 1].x + "," + (dim.height - offsets.b) +
|
|
" L" + lpoly[0].x + "," + (dim.height - offsets.b) +
|
|
" L" + lpoly[0].x + "," + lpoly[0].y;
|
|
run.dyn.fill = s.createPath(p).setFill(theme.series.fill).getFill();
|
|
} else {
|
|
apoly.push({x: lpoly[lpoly.length - 1].x, y: dim.height - offsets.b});
|
|
apoly.push({x: lpoly[0].x, y: dim.height - offsets.b});
|
|
apoly.push(lpoly[0]);
|
|
run.dyn.fill = s.createPolyline(apoly).setFill(theme.series.fill).getFill();
|
|
}
|
|
}
|
|
if(this.opt.lines || this.opt.markers){
|
|
if(theme.series.outline){
|
|
outline = dc.makeStroke(theme.series.outline);
|
|
outline.width = 2 * outline.width + theme.series.stroke.width;
|
|
}
|
|
}
|
|
if(this.opt.markers){
|
|
run.dyn.marker = theme.symbol;
|
|
}
|
|
var frontMarkers, outlineMarkers, shadowMarkers;
|
|
if(theme.series.shadow && theme.series.stroke){
|
|
var shadow = theme.series.shadow,
|
|
spoly = arr.map(lpoly, function(c){
|
|
return {x: c.x + shadow.dx, y: c.y + shadow.dy};
|
|
});
|
|
if(this.opt.lines){
|
|
if(this.opt.tension){
|
|
run.dyn.shadow = s.createPath(dc.curve(spoly, this.opt.tension)).setStroke(shadow).getStroke();
|
|
} else {
|
|
run.dyn.shadow = s.createPolyline(spoly).setStroke(shadow).getStroke();
|
|
}
|
|
}
|
|
if(this.opt.markers){
|
|
shadow = theme.marker.shadow;
|
|
shadowMarkers = arr.map(spoly, function(c){
|
|
return s.createPath("M" + c.x + " " + c.y + " " + theme.symbol).
|
|
setStroke(shadow).setFill(shadow.color);
|
|
}, this);
|
|
}
|
|
}
|
|
if(this.opt.lines){
|
|
if(outline){
|
|
if(this.opt.tension){
|
|
run.dyn.outline = s.createPath(lpath).setStroke(outline).getStroke();
|
|
} else {
|
|
run.dyn.outline = s.createPolyline(lpoly).setStroke(outline).getStroke();
|
|
}
|
|
}
|
|
if(this.opt.tension){
|
|
run.dyn.stroke = s.createPath(lpath).setStroke(theme.series.stroke).getStroke();
|
|
} else {
|
|
run.dyn.stroke = s.createPolyline(lpoly).setStroke(theme.series.stroke).getStroke();
|
|
}
|
|
}
|
|
if(this.opt.markers){
|
|
frontMarkers = new Array(lpoly.length);
|
|
outlineMarkers = new Array(lpoly.length);
|
|
outline = null;
|
|
if(theme.marker.outline){
|
|
outline = dc.makeStroke(theme.marker.outline);
|
|
outline.width = 2 * outline.width + (theme.marker.stroke ? theme.marker.stroke.width : 0);
|
|
}
|
|
arr.forEach(lpoly, function(c, i){
|
|
var path = "M" + c.x + " " + c.y + " " + theme.symbol;
|
|
if(outline){
|
|
outlineMarkers[i] = s.createPath(path).setStroke(outline);
|
|
}
|
|
frontMarkers[i] = s.createPath(path).setStroke(theme.marker.stroke).setFill(theme.marker.fill);
|
|
}, this);
|
|
if(events){
|
|
var eventSeries = new Array(frontMarkers.length);
|
|
arr.forEach(frontMarkers, function(s, i){
|
|
var o = {
|
|
element: "marker",
|
|
index: i,
|
|
run: run,
|
|
shape: s,
|
|
outline: outlineMarkers[i] || null,
|
|
shadow: shadowMarkers && shadowMarkers[i] || null,
|
|
cx: lpoly[i].x,
|
|
cy: lpoly[i].y,
|
|
x: i + 1,
|
|
y: run.data[i]
|
|
};
|
|
this._connectEvents(o);
|
|
eventSeries[i] = o;
|
|
}, this);
|
|
this._eventSeries[run.name] = eventSeries;
|
|
}else{
|
|
delete this._eventSeries[run.name];
|
|
}
|
|
}
|
|
run.dirty = false;
|
|
// update the accumulator
|
|
for(var j = 0; j < run.data.length; ++j){
|
|
var v = run.data[j];
|
|
if(v !== null){
|
|
if(isNaN(v)){ v = 0; }
|
|
acc[j] -= v;
|
|
}
|
|
}
|
|
}
|
|
this.dirty = false;
|
|
return this; // dojox.charting.plot2d.Stacked
|
|
}
|
|
});
|
|
});
|