200 lines
6.1 KiB
JavaScript
200 lines
6.1 KiB
JavaScript
|
if(!dojo._hasResource["dojox.charting.plot2d.Pie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||
|
dojo._hasResource["dojox.charting.plot2d.Pie"] = true;
|
||
|
dojo.provide("dojox.charting.plot2d.Pie");
|
||
|
|
||
|
dojo.require("dojox.charting.Element");
|
||
|
dojo.require("dojox.charting.axis2d.common");
|
||
|
dojo.require("dojox.charting.plot2d.common");
|
||
|
|
||
|
dojo.require("dojox.lang.functional");
|
||
|
dojo.require("dojox.gfx");
|
||
|
|
||
|
(function(){
|
||
|
var df = dojox.lang.functional, du = dojox.lang.utils,
|
||
|
dc = dojox.charting.plot2d.common,
|
||
|
da = dojox.charting.axis2d.common,
|
||
|
g = dojox.gfx;
|
||
|
|
||
|
dojo.declare("dojox.charting.plot2d.Pie", dojox.charting.Element, {
|
||
|
defaultParams: {
|
||
|
labels: true,
|
||
|
ticks: false,
|
||
|
fixed: true,
|
||
|
precision: 1,
|
||
|
labelOffset: 20,
|
||
|
labelStyle: "default", // default/rows/auto
|
||
|
htmlLabels: true // use HTML to draw labels
|
||
|
},
|
||
|
optionalParams: {
|
||
|
font: "",
|
||
|
fontColor: "",
|
||
|
radius: 0
|
||
|
},
|
||
|
|
||
|
constructor: function(chart, kwArgs){
|
||
|
this.opt = dojo.clone(this.defaultParams);
|
||
|
du.updateWithObject(this.opt, kwArgs);
|
||
|
du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
|
||
|
this.run = null;
|
||
|
this.dyn = [];
|
||
|
},
|
||
|
clear: function(){
|
||
|
this.dirty = true;
|
||
|
this.dyn = [];
|
||
|
return this;
|
||
|
},
|
||
|
setAxis: function(axis){
|
||
|
// nothing
|
||
|
return this;
|
||
|
},
|
||
|
addSeries: function(run){
|
||
|
this.run = run;
|
||
|
return this;
|
||
|
},
|
||
|
calculateAxes: function(dim){
|
||
|
// nothing
|
||
|
return this;
|
||
|
},
|
||
|
getRequiredColors: function(){
|
||
|
return this.run ? this.run.data.length : 0;
|
||
|
},
|
||
|
render: function(dim, offsets){
|
||
|
if(!this.dirty){ return this; }
|
||
|
this.dirty = false;
|
||
|
this.cleanGroup();
|
||
|
var s = this.group, color, t = this.chart.theme;
|
||
|
|
||
|
// calculate the geometry
|
||
|
var rx = (dim.width - offsets.l - offsets.r) / 2,
|
||
|
ry = (dim.height - offsets.t - offsets.b) / 2,
|
||
|
r = Math.min(rx, ry),
|
||
|
taFont = "font" in this.opt ? this.opt.font : t.axis.font,
|
||
|
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0,
|
||
|
taFontColor = "fontColor" in this.opt ? this.opt.fontColor : t.axis.fontColor,
|
||
|
start = 0, step, sum, slices, labels, shift, labelR,
|
||
|
run = this.run.data;
|
||
|
if(typeof run[0] == "number"){
|
||
|
sum = df.foldl1(run, "+");
|
||
|
slices = dojo.map(run, function(x){ return x / sum; });
|
||
|
if(this.opt.labels){
|
||
|
labels = dojo.map(slices, function(x){
|
||
|
return this._getLabel(x * 100) + "%";
|
||
|
}, this);
|
||
|
}
|
||
|
}else{
|
||
|
sum = df.foldl1(run, function(a, b){ return {y: a.y + b.y}; }).y;
|
||
|
slices = df.map(run, function(x){ return x.y / sum; });
|
||
|
if(this.opt.labels){
|
||
|
labels = dojo.map(slices, function(x, i){
|
||
|
var v = run[i];
|
||
|
return "text" in v ? v.text : this._getLabel(x * 100) + "%";
|
||
|
}, this);
|
||
|
}
|
||
|
}
|
||
|
if(this.opt.labels){
|
||
|
shift = df.foldl1(df.map(labels, function(label){
|
||
|
return dojox.gfx._base._getTextBox(label, {font: taFont}).w;
|
||
|
}, this), "Math.max(a, b)") / 2;
|
||
|
if(this.opt.labelOffset < 0){
|
||
|
r = Math.min(rx - 2 * shift, ry - size) + this.opt.labelOffset;
|
||
|
}
|
||
|
labelR = r - this.opt.labelOffset;
|
||
|
}
|
||
|
if("radius" in this.opt){
|
||
|
r = this.opt.radius;
|
||
|
labelR = r - this.opt.labelOffset;
|
||
|
}
|
||
|
var circle = {
|
||
|
cx: offsets.l + rx,
|
||
|
cy: offsets.t + ry,
|
||
|
r: r
|
||
|
};
|
||
|
|
||
|
this.dyn = [];
|
||
|
if(!this.run || !run.length){
|
||
|
return this;
|
||
|
}
|
||
|
if(run.length == 1){
|
||
|
// need autogenerated color
|
||
|
color = new dojo.Color(t.next("color"));
|
||
|
var shape = s.createCircle(circle).
|
||
|
setFill(dc.augmentFill(t.run.fill, color)).
|
||
|
setStroke(dc.augmentStroke(t.series.stroke, color));
|
||
|
this.dyn.push({color: color, fill: shape.getFill(), stroke: shape.getStroke()});
|
||
|
if(this.opt.labels){
|
||
|
// draw the label
|
||
|
var elem = da.createText[this.opt.htmlLabels && dojox.gfx.renderer != "vml" ? "html" : "gfx"]
|
||
|
(this.chart, s, circle.cx, circle.cy + size / 2, "middle",
|
||
|
"100%", taFont, taFontColor);
|
||
|
if(this.opt.htmlLabels){ this.htmlElements.push(elem); }
|
||
|
}
|
||
|
return this;
|
||
|
}
|
||
|
// draw slices
|
||
|
dojo.forEach(slices, function(x, i){
|
||
|
// calculate the geometry of the slice
|
||
|
var end = start + x * 2 * Math.PI, v = run[i];
|
||
|
if(i + 1 == slices.length){
|
||
|
end = 2 * Math.PI;
|
||
|
}
|
||
|
var step = end - start,
|
||
|
x1 = circle.cx + r * Math.cos(start),
|
||
|
y1 = circle.cy + r * Math.sin(start),
|
||
|
x2 = circle.cx + r * Math.cos(end),
|
||
|
y2 = circle.cy + r * Math.sin(end);
|
||
|
// draw the slice
|
||
|
var color, fill, stroke;
|
||
|
if(typeof v == "object"){
|
||
|
color = "color" in v ? v.color : new dojo.Color(t.next("color"));
|
||
|
fill = "fill" in v ? v.fill : dc.augmentFill(t.series.fill, color);
|
||
|
stroke = "stroke" in v ? v.stroke : dc.augmentStroke(t.series.stroke, color);
|
||
|
}else{
|
||
|
color = new dojo.Color(t.next("color"));
|
||
|
fill = dc.augmentFill(t.series.fill, color);
|
||
|
stroke = dc.augmentStroke(t.series.stroke, color);
|
||
|
}
|
||
|
var shape = s.createPath({}).
|
||
|
moveTo(circle.cx, circle.cy).
|
||
|
lineTo(x1, y1).
|
||
|
arcTo(r, r, 0, step > Math.PI, true, x2, y2).
|
||
|
lineTo(circle.cx, circle.cy).
|
||
|
closePath().
|
||
|
setFill(fill).
|
||
|
setStroke(stroke);
|
||
|
this.dyn.push({color: color, fill: fill, stroke: stroke});
|
||
|
start = end;
|
||
|
}, this);
|
||
|
// draw labels
|
||
|
if(this.opt.labels){
|
||
|
start = 0;
|
||
|
dojo.forEach(slices, function(slice, i){
|
||
|
// calculate the geometry of the slice
|
||
|
var end = start + slice * 2 * Math.PI, v = run[i];
|
||
|
if(i + 1 == slices.length){
|
||
|
end = 2 * Math.PI;
|
||
|
}
|
||
|
var labelAngle = (start + end) / 2,
|
||
|
x = circle.cx + labelR * Math.cos(labelAngle),
|
||
|
y = circle.cy + labelR * Math.sin(labelAngle) + size / 2;
|
||
|
// draw the label
|
||
|
var elem = da.createText[this.opt.htmlLabels && dojox.gfx.renderer != "vml" ? "html" : "gfx"]
|
||
|
(this.chart, s, x, y, "middle",
|
||
|
labels[i], taFont,
|
||
|
(typeof v == "object" && "fontColor" in v)
|
||
|
? v.fontColor : taFontColor);
|
||
|
if(this.opt.htmlLabels){ this.htmlElements.push(elem); }
|
||
|
start = end;
|
||
|
}, this);
|
||
|
}
|
||
|
return this;
|
||
|
},
|
||
|
|
||
|
// utilities
|
||
|
_getLabel: function(number){
|
||
|
return this.opt.fixed ? number.toFixed(this.opt.precision) : number.toString();
|
||
|
}
|
||
|
});
|
||
|
})();
|
||
|
|
||
|
}
|