2150 |
mathias |
1 |
if(!dojo._hasResource["dojox.charting.plot2d.Pie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dojox.charting.plot2d.Pie"] = true;
|
|
|
3 |
dojo.provide("dojox.charting.plot2d.Pie");
|
|
|
4 |
|
|
|
5 |
dojo.require("dojox.charting.Element");
|
|
|
6 |
dojo.require("dojox.charting.axis2d.common");
|
|
|
7 |
dojo.require("dojox.charting.plot2d.common");
|
|
|
8 |
|
|
|
9 |
dojo.require("dojox.lang.functional");
|
|
|
10 |
dojo.require("dojox.gfx");
|
|
|
11 |
|
|
|
12 |
(function(){
|
|
|
13 |
var df = dojox.lang.functional, du = dojox.lang.utils,
|
|
|
14 |
dc = dojox.charting.plot2d.common,
|
|
|
15 |
da = dojox.charting.axis2d.common,
|
|
|
16 |
g = dojox.gfx,
|
|
|
17 |
labelFudgeFactor = 0.8; // in percents (to convert font's heigth to label width)
|
|
|
18 |
|
|
|
19 |
dojo.declare("dojox.charting.plot2d.Pie", dojox.charting.Element, {
|
|
|
20 |
defaultParams: {
|
|
|
21 |
labels: true,
|
|
|
22 |
ticks: false,
|
|
|
23 |
fixed: true,
|
|
|
24 |
precision: 1,
|
|
|
25 |
labelOffset: 20,
|
|
|
26 |
labelStyle: "default", // default/rows/auto
|
|
|
27 |
htmlLabels: true // use HTML to draw labels
|
|
|
28 |
},
|
|
|
29 |
optionalParams: {
|
|
|
30 |
font: "",
|
|
|
31 |
fontColor: "",
|
|
|
32 |
radius: 0
|
|
|
33 |
},
|
|
|
34 |
|
|
|
35 |
constructor: function(chart, kwArgs){
|
|
|
36 |
this.opt = dojo.clone(this.defaultParams);
|
|
|
37 |
du.updateWithObject(this.opt, kwArgs);
|
|
|
38 |
du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
|
|
|
39 |
this.run = null;
|
|
|
40 |
this.dyn = [];
|
|
|
41 |
},
|
|
|
42 |
clear: function(){
|
|
|
43 |
this.dirty = true;
|
|
|
44 |
this.dyn = [];
|
|
|
45 |
return this;
|
|
|
46 |
},
|
|
|
47 |
setAxis: function(axis){
|
|
|
48 |
// nothing
|
|
|
49 |
return this;
|
|
|
50 |
},
|
|
|
51 |
addSeries: function(run){
|
|
|
52 |
this.run = run;
|
|
|
53 |
return this;
|
|
|
54 |
},
|
|
|
55 |
calculateAxes: function(dim){
|
|
|
56 |
// nothing
|
|
|
57 |
return this;
|
|
|
58 |
},
|
|
|
59 |
getRequiredColors: function(){
|
|
|
60 |
return this.run ? this.run.data.length : 0;
|
|
|
61 |
},
|
|
|
62 |
render: function(dim, offsets){
|
|
|
63 |
if(!this.dirty){ return this; }
|
|
|
64 |
this.dirty = false;
|
|
|
65 |
this.cleanGroup();
|
|
|
66 |
var s = this.group, color, t = this.chart.theme;
|
|
|
67 |
|
|
|
68 |
// calculate the geometry
|
|
|
69 |
var rx = (dim.width - offsets.l - offsets.r) / 2,
|
|
|
70 |
ry = (dim.height - offsets.t - offsets.b) / 2,
|
|
|
71 |
r = Math.min(rx, ry),
|
|
|
72 |
taFont = "font" in this.opt ? this.opt.font : t.axis.font,
|
|
|
73 |
taFontColor = "fontColor" in this.opt ? this.opt.fontColor : t.axis.fontColor,
|
|
|
74 |
sum = df.foldl1(this.run.data, "+"), start = 0, step,
|
|
|
75 |
slices = dojo.map(this.run.data, function(x){ return x / sum; }),
|
|
|
76 |
shift, size, labelR;
|
|
|
77 |
if(this.opt.labels){
|
|
|
78 |
var labels = dojo.map(slices, function(x){
|
|
|
79 |
return this._getLabel(x * 100) + "%";
|
|
|
80 |
}, this);
|
|
|
81 |
shift = df.foldl1(dojo.map(labels, df.pluck("length")), "x, y -> Math.max(x, y)");
|
|
|
82 |
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0;
|
|
|
83 |
shift = Math.max(shift * labelFudgeFactor, 1) / 2 * size;
|
|
|
84 |
if(this.opt.labelOffset < 0){
|
|
|
85 |
r = Math.min(rx - 2 * shift, ry - size) + this.opt.labelOffset;
|
|
|
86 |
}
|
|
|
87 |
labelR = r - this.opt.labelOffset;
|
|
|
88 |
}
|
|
|
89 |
if("radius" in this.opt){
|
|
|
90 |
r = this.opt.radius;
|
|
|
91 |
labelR = r - this.opt.labelOffset;
|
|
|
92 |
}
|
|
|
93 |
var circle = {
|
|
|
94 |
cx: offsets.l + rx,
|
|
|
95 |
cy: offsets.t + ry,
|
|
|
96 |
r: r
|
|
|
97 |
};
|
|
|
98 |
|
|
|
99 |
this.dyn = [];
|
|
|
100 |
if(!this.run || !this.run.data.length){
|
|
|
101 |
return this;
|
|
|
102 |
}
|
|
|
103 |
if(this.run.data.length == 1){
|
|
|
104 |
// need autogenerated color
|
|
|
105 |
color = new dojo.Color(t.next("color"));
|
|
|
106 |
var shape = s.createCircle(circle).
|
|
|
107 |
setFill(dc.augmentFill(t.run.fill, color)).
|
|
|
108 |
setStroke(dc.augmentStroke(t.series.stroke, color));
|
|
|
109 |
this.dyn.push({color: color, fill: shape.getFill(), stroke: shape.getStroke()});
|
|
|
110 |
if(this.opt.labels){
|
|
|
111 |
var shift = 4,
|
|
|
112 |
taFont = "font" in this.opt ? this.opt.font : t.axis.font,
|
|
|
113 |
taFontColor = "fontColor" in this.opt ? this.opt.fontColor : t.axis.fontColor,
|
|
|
114 |
size = taFont ? g.normalizedLength(g.splitFontString(taFont).size) : 0;
|
|
|
115 |
shift = Math.max(shift * labelFudgeFactor, 1) / 2 * size;
|
|
|
116 |
// draw the label
|
|
|
117 |
var elem = da.createText[this.opt.htmlLabels ? "html" : "gfx"]
|
|
|
118 |
(this.chart, s, circle.cx, circle.cy + size / 2, "middle",
|
|
|
119 |
"100%", taFont, taFontColor);
|
|
|
120 |
if(this.opt.htmlLabels){ this.htmlElements.push(elem); }
|
|
|
121 |
}
|
|
|
122 |
return this;
|
|
|
123 |
}
|
|
|
124 |
// draw slices
|
|
|
125 |
dojo.forEach(slices, function(x, i){
|
|
|
126 |
// calculate the geometry of the slice
|
|
|
127 |
var end = start + x * 2 * Math.PI;
|
|
|
128 |
if(i + 1 == slices.length){
|
|
|
129 |
end = 2 * Math.PI;
|
|
|
130 |
}
|
|
|
131 |
var step = end - start,
|
|
|
132 |
x1 = circle.cx + r * Math.cos(start),
|
|
|
133 |
y1 = circle.cy + r * Math.sin(start),
|
|
|
134 |
x2 = circle.cx + r * Math.cos(end),
|
|
|
135 |
y2 = circle.cy + r * Math.sin(end);
|
|
|
136 |
// draw the slice
|
|
|
137 |
color = new dojo.Color(t.next("color"));
|
|
|
138 |
var shape = s.createPath({}).
|
|
|
139 |
moveTo(circle.cx, circle.cy).
|
|
|
140 |
lineTo(x1, y1).
|
|
|
141 |
arcTo(r, r, 0, step > Math.PI, true, x2, y2).
|
|
|
142 |
lineTo(circle.cx, circle.cy).
|
|
|
143 |
closePath().
|
|
|
144 |
setFill(dc.augmentFill(t.series.fill, color)).
|
|
|
145 |
setStroke(dc.augmentStroke(t.series.stroke, color));
|
|
|
146 |
this.dyn.push({color: color, fill: shape.getFill(), stroke: shape.getStroke()});
|
|
|
147 |
start = end;
|
|
|
148 |
}, this);
|
|
|
149 |
// draw labels
|
|
|
150 |
if(this.opt.labels){
|
|
|
151 |
start = 0;
|
|
|
152 |
dojo.forEach(slices, function(x, i){
|
|
|
153 |
// calculate the geometry of the slice
|
|
|
154 |
var end = start + x * 2 * Math.PI;
|
|
|
155 |
if(i + 1 == slices.length){
|
|
|
156 |
end = 2 * Math.PI;
|
|
|
157 |
}
|
|
|
158 |
var labelAngle = (start + end) / 2,
|
|
|
159 |
x = circle.cx + labelR * Math.cos(labelAngle),
|
|
|
160 |
y = circle.cy + labelR * Math.sin(labelAngle) + size / 2;
|
|
|
161 |
// draw the label
|
|
|
162 |
var elem = da.createText[this.opt.htmlLabels ? "html" : "gfx"]
|
|
|
163 |
(this.chart, s, x, y, "middle",
|
|
|
164 |
labels[i], taFont, taFontColor);
|
|
|
165 |
if(this.opt.htmlLabels){ this.htmlElements.push(elem); }
|
|
|
166 |
start = end;
|
|
|
167 |
}, this);
|
|
|
168 |
}
|
|
|
169 |
return this;
|
|
|
170 |
},
|
|
|
171 |
|
|
|
172 |
// utilities
|
|
|
173 |
_getLabel: function(number){
|
|
|
174 |
return this.opt.fixed ? number.toFixed(this.opt.precision) : number.toString();
|
|
|
175 |
}
|
|
|
176 |
});
|
|
|
177 |
})();
|
|
|
178 |
|
|
|
179 |
}
|