1318 |
alexandre_ |
1 |
/*
|
|
|
2 |
Copyright (c) 2004-2006, The Dojo Foundation
|
|
|
3 |
All Rights Reserved.
|
|
|
4 |
|
|
|
5 |
Licensed under the Academic Free License version 2.1 or above OR the
|
|
|
6 |
modified BSD license. For more information on Dojo licensing, see:
|
|
|
7 |
|
|
|
8 |
http://dojotoolkit.org/community/licensing.shtml
|
|
|
9 |
*/
|
|
|
10 |
|
|
|
11 |
dojo.provide("dojo.widget.svg.Chart");
|
|
|
12 |
dojo.require("dojo.widget.HtmlWidget");
|
|
|
13 |
dojo.require("dojo.widget.Chart");
|
|
|
14 |
dojo.require("dojo.html.layout");
|
|
|
15 |
dojo.require("dojo.math");
|
|
|
16 |
dojo.require("dojo.svg");
|
|
|
17 |
dojo.require("dojo.gfx.color");
|
|
|
18 |
dojo.require("dojo.json");
|
|
|
19 |
dojo.widget.defineWidget("dojo.widget.svg.Chart", [dojo.widget.HtmlWidget, dojo.widget.Chart], function () {
|
|
|
20 |
this.templatePath = null;
|
|
|
21 |
this.templateCssPath = null;
|
|
|
22 |
this._isInitialize = false;
|
|
|
23 |
this.hasData = false;
|
|
|
24 |
this.vectorNode = null;
|
|
|
25 |
this.plotArea = null;
|
|
|
26 |
this.dataGroup = null;
|
|
|
27 |
this.axisGroup = null;
|
|
|
28 |
this.properties = {height:0, width:0, defaultWidth:600, defaultHeight:400, plotType:null, padding:{top:10, bottom:2, left:60, right:30}, axes:{x:{plotAt:0, label:"", unitLabel:"", unitType:Number, nUnitsToShow:10, range:{min:0, max:200}}, y:{plotAt:0, label:"", unitLabel:"", unitType:Number, nUnitsToShow:10, range:{min:0, max:200}}}};
|
|
|
29 |
}, {parseProperties:function (node) {
|
|
|
30 |
var bRangeX = false;
|
|
|
31 |
var bRangeY = false;
|
|
|
32 |
if (node.getAttribute("width")) {
|
|
|
33 |
this.properties.width = node.getAttribute("width");
|
|
|
34 |
}
|
|
|
35 |
if (node.getAttribute("height")) {
|
|
|
36 |
this.properties.height = node.getAttribute("height");
|
|
|
37 |
}
|
|
|
38 |
if (node.getAttribute("plotType")) {
|
|
|
39 |
this.properties.plotType = node.getAttribute("plotType");
|
|
|
40 |
}
|
|
|
41 |
if (node.getAttribute("padding")) {
|
|
|
42 |
if (node.getAttribute("padding").indexOf(",") > -1) {
|
|
|
43 |
var p = node.getAttribute("padding").split(",");
|
|
|
44 |
} else {
|
|
|
45 |
var p = node.getAttribute("padding").split(" ");
|
|
|
46 |
}
|
|
|
47 |
if (p.length == 1) {
|
|
|
48 |
var pad = parseFloat(p[0]);
|
|
|
49 |
this.properties.padding.top = pad;
|
|
|
50 |
this.properties.padding.right = pad;
|
|
|
51 |
this.properties.padding.bottom = pad;
|
|
|
52 |
this.properties.padding.left = pad;
|
|
|
53 |
} else {
|
|
|
54 |
if (p.length == 2) {
|
|
|
55 |
var padV = parseFloat(p[0]);
|
|
|
56 |
var padH = parseFloat(p[1]);
|
|
|
57 |
this.properties.padding.top = padV;
|
|
|
58 |
this.properties.padding.right = padH;
|
|
|
59 |
this.properties.padding.bottom = padV;
|
|
|
60 |
this.properties.padding.left = padH;
|
|
|
61 |
} else {
|
|
|
62 |
if (p.length == 4) {
|
|
|
63 |
this.properties.padding.top = parseFloat(p[0]);
|
|
|
64 |
this.properties.padding.right = parseFloat(p[1]);
|
|
|
65 |
this.properties.padding.bottom = parseFloat(p[2]);
|
|
|
66 |
this.properties.padding.left = parseFloat(p[3]);
|
|
|
67 |
}
|
|
|
68 |
}
|
|
|
69 |
}
|
|
|
70 |
}
|
|
|
71 |
if (node.getAttribute("rangeX")) {
|
|
|
72 |
var p = node.getAttribute("rangeX");
|
|
|
73 |
if (p.indexOf(",") > -1) {
|
|
|
74 |
p = p.split(",");
|
|
|
75 |
} else {
|
|
|
76 |
p = p.split(" ");
|
|
|
77 |
}
|
|
|
78 |
this.properties.axes.x.range.min = parseFloat(p[0]);
|
|
|
79 |
this.properties.axes.x.range.max = parseFloat(p[1]);
|
|
|
80 |
bRangeX = true;
|
|
|
81 |
}
|
|
|
82 |
if (node.getAttribute("rangeY")) {
|
|
|
83 |
var p = node.getAttribute("rangeY");
|
|
|
84 |
if (p.indexOf(",") > -1) {
|
|
|
85 |
p = p.split(",");
|
|
|
86 |
} else {
|
|
|
87 |
p = p.split(" ");
|
|
|
88 |
}
|
|
|
89 |
this.properties.axes.y.range.min = parseFloat(p[0]);
|
|
|
90 |
this.properties.axes.y.range.max = parseFloat(p[1]);
|
|
|
91 |
bRangeY = true;
|
|
|
92 |
}
|
|
|
93 |
return {rangeX:bRangeX, rangeY:bRangeY};
|
|
|
94 |
}, setAxesPlot:function (table) {
|
|
|
95 |
if (table.getAttribute("axisAt")) {
|
|
|
96 |
var p = table.getAttribute("axisAt");
|
|
|
97 |
if (p.indexOf(",") > -1) {
|
|
|
98 |
p = p.split(",");
|
|
|
99 |
} else {
|
|
|
100 |
p = p.split(" ");
|
|
|
101 |
}
|
|
|
102 |
if (!isNaN(parseFloat(p[0]))) {
|
|
|
103 |
this.properties.axes.x.plotAt = parseFloat(p[0]);
|
|
|
104 |
} else {
|
|
|
105 |
if (p[0].toLowerCase() == "ymin") {
|
|
|
106 |
this.properties.axes.x.plotAt = this.properties.axes.y.range.min;
|
|
|
107 |
} else {
|
|
|
108 |
if (p[0].toLowerCase() == "ymax") {
|
|
|
109 |
this.properties.axes.x.plotAt = this.properties.axes.y.range.max;
|
|
|
110 |
}
|
|
|
111 |
}
|
|
|
112 |
}
|
|
|
113 |
if (!isNaN(parseFloat(p[1]))) {
|
|
|
114 |
this.properties.axes.y.plotAt = parseFloat(p[1]);
|
|
|
115 |
} else {
|
|
|
116 |
if (p[1].toLowerCase() == "xmin") {
|
|
|
117 |
this.properties.axes.y.plotAt = this.properties.axes.x.range.min;
|
|
|
118 |
} else {
|
|
|
119 |
if (p[1].toLowerCase() == "xmax") {
|
|
|
120 |
this.properties.axes.y.plotAt = this.properties.axes.x.range.max;
|
|
|
121 |
}
|
|
|
122 |
}
|
|
|
123 |
}
|
|
|
124 |
} else {
|
|
|
125 |
this.properties.axes.x.plotAt = this.properties.axes.y.range.min;
|
|
|
126 |
this.properties.axes.y.plotAt = this.properties.axes.x.range.min;
|
|
|
127 |
}
|
|
|
128 |
}, drawVectorNode:function () {
|
|
|
129 |
dojo.svg.g.suspend();
|
|
|
130 |
if (this.vectorNode) {
|
|
|
131 |
this.destroy();
|
|
|
132 |
}
|
|
|
133 |
this.vectorNode = document.createElementNS(dojo.svg.xmlns.svg, "svg");
|
|
|
134 |
this.vectorNode.setAttribute("width", this.properties.width);
|
|
|
135 |
this.vectorNode.setAttribute("height", this.properties.height);
|
|
|
136 |
dojo.svg.g.resume();
|
|
|
137 |
}, drawPlotArea:function () {
|
|
|
138 |
dojo.svg.g.suspend();
|
|
|
139 |
if (this.plotArea) {
|
|
|
140 |
this.plotArea.parentNode.removeChild(this.plotArea);
|
|
|
141 |
this.plotArea = null;
|
|
|
142 |
}
|
|
|
143 |
var defs = document.createElementNS(dojo.svg.xmlns.svg, "defs");
|
|
|
144 |
var clip = document.createElementNS(dojo.svg.xmlns.svg, "clipPath");
|
|
|
145 |
clip.setAttribute("id", "plotClip" + this.widgetId);
|
|
|
146 |
var rect = document.createElementNS(dojo.svg.xmlns.svg, "rect");
|
|
|
147 |
rect.setAttribute("x", this.properties.padding.left);
|
|
|
148 |
rect.setAttribute("y", this.properties.padding.top);
|
|
|
149 |
rect.setAttribute("width", this.properties.width - this.properties.padding.left - this.properties.padding.right);
|
|
|
150 |
rect.setAttribute("height", this.properties.height - this.properties.padding.top - this.properties.padding.bottom);
|
|
|
151 |
clip.appendChild(rect);
|
|
|
152 |
defs.appendChild(clip);
|
|
|
153 |
this.vectorNode.appendChild(defs);
|
|
|
154 |
this.plotArea = document.createElementNS(dojo.svg.xmlns.svg, "g");
|
|
|
155 |
this.vectorNode.appendChild(this.plotArea);
|
|
|
156 |
var rect = document.createElementNS(dojo.svg.xmlns.svg, "rect");
|
|
|
157 |
rect.setAttribute("x", this.properties.padding.left);
|
|
|
158 |
rect.setAttribute("y", this.properties.padding.top);
|
|
|
159 |
rect.setAttribute("width", this.properties.width - this.properties.padding.left - this.properties.padding.right);
|
|
|
160 |
rect.setAttribute("height", this.properties.height - this.properties.padding.top - this.properties.padding.bottom);
|
|
|
161 |
rect.setAttribute("fill", "#fff");
|
|
|
162 |
this.plotArea.appendChild(rect);
|
|
|
163 |
dojo.svg.g.resume();
|
|
|
164 |
}, drawDataGroup:function () {
|
|
|
165 |
dojo.svg.g.suspend();
|
|
|
166 |
if (this.dataGroup) {
|
|
|
167 |
this.dataGroup.parentNode.removeChild(this.dataGroup);
|
|
|
168 |
this.dataGroup = null;
|
|
|
169 |
}
|
|
|
170 |
this.dataGroup = document.createElementNS(dojo.svg.xmlns.svg, "g");
|
|
|
171 |
this.dataGroup.setAttribute("style", "clip-path:url(#plotClip" + this.widgetId + ");");
|
|
|
172 |
this.plotArea.appendChild(this.dataGroup);
|
|
|
173 |
dojo.svg.g.resume();
|
|
|
174 |
}, drawAxes:function () {
|
|
|
175 |
dojo.svg.g.suspend();
|
|
|
176 |
if (this.axisGroup) {
|
|
|
177 |
this.axisGroup.parentNode.removeChild(this.axisGroup);
|
|
|
178 |
this.axisGroup = null;
|
|
|
179 |
}
|
|
|
180 |
this.axisGroup = document.createElementNS(dojo.svg.xmlns.svg, "g");
|
|
|
181 |
this.plotArea.appendChild(this.axisGroup);
|
|
|
182 |
var stroke = 1;
|
|
|
183 |
var line = document.createElementNS(dojo.svg.xmlns.svg, "line");
|
|
|
184 |
var y = dojo.widget.svg.Chart.Plotter.getY(this.properties.axes.x.plotAt, this);
|
|
|
185 |
line.setAttribute("y1", y);
|
|
|
186 |
line.setAttribute("y2", y);
|
|
|
187 |
line.setAttribute("x1", this.properties.padding.left - stroke);
|
|
|
188 |
line.setAttribute("x2", this.properties.width - this.properties.padding.right);
|
|
|
189 |
line.setAttribute("style", "stroke:#000;stroke-width:" + stroke + ";");
|
|
|
190 |
this.axisGroup.appendChild(line);
|
|
|
191 |
var textSize = 10;
|
|
|
192 |
var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
|
|
|
193 |
text.setAttribute("x", this.properties.padding.left);
|
|
|
194 |
text.setAttribute("y", this.properties.height - this.properties.padding.bottom + textSize + 2);
|
|
|
195 |
text.setAttribute("style", "text-anchor:middle;font-size:" + textSize + "px;fill:#000;");
|
|
|
196 |
text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.x.range.min), 2)));
|
|
|
197 |
this.axisGroup.appendChild(text);
|
|
|
198 |
var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
|
|
|
199 |
text.setAttribute("x", this.properties.width - this.properties.padding.right - (textSize / 2));
|
|
|
200 |
text.setAttribute("y", this.properties.height - this.properties.padding.bottom + textSize + 2);
|
|
|
201 |
text.setAttribute("style", "text-anchor:middle;font-size:" + textSize + "px;fill:#000;");
|
|
|
202 |
text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.x.range.max), 2)));
|
|
|
203 |
this.axisGroup.appendChild(text);
|
|
|
204 |
var line = document.createElementNS(dojo.svg.xmlns.svg, "line");
|
|
|
205 |
var x = dojo.widget.svg.Chart.Plotter.getX(this.properties.axes.y.plotAt, this);
|
|
|
206 |
line.setAttribute("x1", x);
|
|
|
207 |
line.setAttribute("x2", x);
|
|
|
208 |
line.setAttribute("y1", this.properties.padding.top);
|
|
|
209 |
line.setAttribute("y2", this.properties.height - this.properties.padding.bottom);
|
|
|
210 |
line.setAttribute("style", "stroke:#000;stroke-width:" + stroke + ";");
|
|
|
211 |
this.axisGroup.appendChild(line);
|
|
|
212 |
var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
|
|
|
213 |
text.setAttribute("x", this.properties.padding.left - 4);
|
|
|
214 |
text.setAttribute("y", this.properties.height - this.properties.padding.bottom);
|
|
|
215 |
text.setAttribute("style", "text-anchor:end;font-size:" + textSize + "px;fill:#000;");
|
|
|
216 |
text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.y.range.min), 2)));
|
|
|
217 |
this.axisGroup.appendChild(text);
|
|
|
218 |
var text = document.createElementNS(dojo.svg.xmlns.svg, "text");
|
|
|
219 |
text.setAttribute("x", this.properties.padding.left - 4);
|
|
|
220 |
text.setAttribute("y", this.properties.padding.top + (textSize / 2));
|
|
|
221 |
text.setAttribute("style", "text-anchor:end;font-size:" + textSize + "px;fill:#000;");
|
|
|
222 |
text.appendChild(document.createTextNode(dojo.math.round(parseFloat(this.properties.axes.y.range.max), 2)));
|
|
|
223 |
this.axisGroup.appendChild(text);
|
|
|
224 |
dojo.svg.g.resume();
|
|
|
225 |
}, init:function () {
|
|
|
226 |
if (!this.properties.width || !this.properties.height) {
|
|
|
227 |
var box = dojo.html.getContentBox(this.domNode);
|
|
|
228 |
if (!this.properties.width) {
|
|
|
229 |
this.properties.width = (box.width < 32) ? this.properties.defaultWidth : box.width;
|
|
|
230 |
}
|
|
|
231 |
if (!this.properties.height) {
|
|
|
232 |
this.properties.height = (box.height < 32) ? this.properties.defaultHeight : box.height;
|
|
|
233 |
}
|
|
|
234 |
}
|
|
|
235 |
this.drawVectorNode();
|
|
|
236 |
this.drawPlotArea();
|
|
|
237 |
this.drawDataGroup();
|
|
|
238 |
this.drawAxes();
|
|
|
239 |
this.domNode.appendChild(this.vectorNode);
|
|
|
240 |
this.assignColors();
|
|
|
241 |
this._isInitialized = true;
|
|
|
242 |
}, destroy:function () {
|
|
|
243 |
while (this.domNode.childNodes.length > 0) {
|
|
|
244 |
this.domNode.removeChild(this.domNode.childNodes.item(0));
|
|
|
245 |
}
|
|
|
246 |
this.vectorNode = this.plotArea = this.dataGroup = this.axisGroup = null;
|
|
|
247 |
}, render:function () {
|
|
|
248 |
dojo.svg.g.suspend();
|
|
|
249 |
if (this.dataGroup) {
|
|
|
250 |
while (this.dataGroup.childNodes.length > 0) {
|
|
|
251 |
this.dataGroup.removeChild(this.dataGroup.childNodes.item(0));
|
|
|
252 |
}
|
|
|
253 |
} else {
|
|
|
254 |
this.init();
|
|
|
255 |
}
|
|
|
256 |
for (var i = 0; i < this.series.length; i++) {
|
|
|
257 |
dojo.widget.svg.Chart.Plotter.plot(this.series[i], this);
|
|
|
258 |
}
|
|
|
259 |
dojo.svg.g.resume();
|
|
|
260 |
}, postCreate:function () {
|
|
|
261 |
var table = this.domNode.getElementsByTagName("table")[0];
|
|
|
262 |
if (table) {
|
|
|
263 |
var ranges = this.parseProperties(table);
|
|
|
264 |
var bRangeX = false;
|
|
|
265 |
var bRangeY = false;
|
|
|
266 |
var axisValues = this.parseData(table);
|
|
|
267 |
if (!bRangeX) {
|
|
|
268 |
this.properties.axes.x.range = {min:axisValues.x.min, max:axisValues.x.max};
|
|
|
269 |
}
|
|
|
270 |
if (!bRangeY) {
|
|
|
271 |
this.properties.axes.y.range = {min:axisValues.y.min, max:axisValues.y.max};
|
|
|
272 |
}
|
|
|
273 |
this.setAxesPlot(table);
|
|
|
274 |
this.domNode.removeChild(table);
|
|
|
275 |
}
|
|
|
276 |
if (this.series.length > 0) {
|
|
|
277 |
this.render();
|
|
|
278 |
}
|
|
|
279 |
}});
|
|
|
280 |
dojo.widget.svg.Chart.Plotter = new function () {
|
|
|
281 |
var self = this;
|
|
|
282 |
var plotters = {};
|
|
|
283 |
var types = dojo.widget.Chart.PlotTypes;
|
|
|
284 |
this.getX = function (value, chart) {
|
|
|
285 |
var v = parseFloat(value);
|
|
|
286 |
var min = chart.properties.axes.x.range.min;
|
|
|
287 |
var max = chart.properties.axes.x.range.max;
|
|
|
288 |
var ofst = 0 - min;
|
|
|
289 |
min += ofst;
|
|
|
290 |
max += ofst;
|
|
|
291 |
v += ofst;
|
|
|
292 |
var xmin = chart.properties.padding.left;
|
|
|
293 |
var xmax = chart.properties.width - chart.properties.padding.right;
|
|
|
294 |
var x = (v * ((xmax - xmin) / max)) + xmin;
|
|
|
295 |
return x;
|
|
|
296 |
};
|
|
|
297 |
this.getY = function (value, chart) {
|
|
|
298 |
var v = parseFloat(value);
|
|
|
299 |
var max = chart.properties.axes.y.range.max;
|
|
|
300 |
var min = chart.properties.axes.y.range.min;
|
|
|
301 |
var ofst = 0;
|
|
|
302 |
if (min < 0) {
|
|
|
303 |
ofst += Math.abs(min);
|
|
|
304 |
}
|
|
|
305 |
min += ofst;
|
|
|
306 |
max += ofst;
|
|
|
307 |
v += ofst;
|
|
|
308 |
var ymin = chart.properties.height - chart.properties.padding.bottom;
|
|
|
309 |
var ymax = chart.properties.padding.top;
|
|
|
310 |
var y = (((ymin - ymax) / (max - min)) * (max - v)) + ymax;
|
|
|
311 |
return y;
|
|
|
312 |
};
|
|
|
313 |
this.addPlotter = function (name, func) {
|
|
|
314 |
plotters[name] = func;
|
|
|
315 |
};
|
|
|
316 |
this.plot = function (series, chart) {
|
|
|
317 |
if (series.values.length == 0) {
|
|
|
318 |
return;
|
|
|
319 |
}
|
|
|
320 |
if (series.plotType && plotters[series.plotType]) {
|
|
|
321 |
return plotters[series.plotType](series, chart);
|
|
|
322 |
} else {
|
|
|
323 |
if (chart.plotType && plotters[chart.plotType]) {
|
|
|
324 |
return plotters[chart.plotType](series, chart);
|
|
|
325 |
}
|
|
|
326 |
}
|
|
|
327 |
};
|
|
|
328 |
plotters["bar"] = function (series, chart) {
|
|
|
329 |
var space = 1;
|
|
|
330 |
var lastW = 0;
|
|
|
331 |
for (var i = 0; i < series.values.length; i++) {
|
|
|
332 |
var x = self.getX(series.values[i].x, chart);
|
|
|
333 |
var w;
|
|
|
334 |
if (i == series.values.length - 1) {
|
|
|
335 |
w = lastW;
|
|
|
336 |
} else {
|
|
|
337 |
w = self.getX(series.values[i + 1].x, chart) - x - space;
|
|
|
338 |
lastW = w;
|
|
|
339 |
}
|
|
|
340 |
x -= (w / 2);
|
|
|
341 |
var yA = self.getY(chart.properties.axes.x.plotAt, chart);
|
|
|
342 |
var y = self.getY(series.values[i].value, chart);
|
|
|
343 |
var h = Math.abs(yA - y);
|
|
|
344 |
if (parseFloat(series.values[i].value) < chart.properties.axes.x.plotAt) {
|
|
|
345 |
var oy = yA;
|
|
|
346 |
yA = y;
|
|
|
347 |
y = oy;
|
|
|
348 |
}
|
|
|
349 |
var bar = document.createElementNS(dojo.svg.xmlns.svg, "rect");
|
|
|
350 |
bar.setAttribute("fill", series.color);
|
|
|
351 |
bar.setAttribute("title", series.label + ": " + series.values[i].value);
|
|
|
352 |
bar.setAttribute("stroke-width", "0");
|
|
|
353 |
bar.setAttribute("x", x);
|
|
|
354 |
bar.setAttribute("y", y);
|
|
|
355 |
bar.setAttribute("width", w);
|
|
|
356 |
bar.setAttribute("height", h);
|
|
|
357 |
bar.setAttribute("fill-opacity", "0.9");
|
|
|
358 |
chart.dataGroup.appendChild(bar);
|
|
|
359 |
}
|
|
|
360 |
};
|
|
|
361 |
plotters["line"] = function (series, chart) {
|
|
|
362 |
var tension = 1.5;
|
|
|
363 |
var line = document.createElementNS(dojo.svg.xmlns.svg, "path");
|
|
|
364 |
line.setAttribute("fill", "none");
|
|
|
365 |
line.setAttribute("stroke", series.color);
|
|
|
366 |
line.setAttribute("stroke-width", "2");
|
|
|
367 |
line.setAttribute("stroke-opacity", "0.85");
|
|
|
368 |
line.setAttribute("title", series.label);
|
|
|
369 |
chart.dataGroup.appendChild(line);
|
|
|
370 |
var path = [];
|
|
|
371 |
for (var i = 0; i < series.values.length; i++) {
|
|
|
372 |
var x = self.getX(series.values[i].x, chart);
|
|
|
373 |
var y = self.getY(series.values[i].value, chart);
|
|
|
374 |
var dx = chart.properties.padding.left + 1;
|
|
|
375 |
var dy = chart.properties.height - chart.properties.padding.bottom;
|
|
|
376 |
if (i > 0) {
|
|
|
377 |
dx = x - self.getX(series.values[i - 1].x, chart);
|
|
|
378 |
dy = self.getY(series.values[i - 1].value, chart);
|
|
|
379 |
}
|
|
|
380 |
if (i == 0) {
|
|
|
381 |
path.push("M");
|
|
|
382 |
} else {
|
|
|
383 |
path.push("C");
|
|
|
384 |
var cx = x - (tension - 1) * (dx / tension);
|
|
|
385 |
path.push(cx + "," + dy);
|
|
|
386 |
cx = x - (dx / tension);
|
|
|
387 |
path.push(cx + "," + y);
|
|
|
388 |
}
|
|
|
389 |
path.push(x + "," + y);
|
|
|
390 |
}
|
|
|
391 |
line.setAttribute("d", path.join(" "));
|
|
|
392 |
};
|
|
|
393 |
plotters["area"] = function (series, chart) {
|
|
|
394 |
var tension = 1.5;
|
|
|
395 |
var line = document.createElementNS(dojo.svg.xmlns.svg, "path");
|
|
|
396 |
line.setAttribute("fill", series.color);
|
|
|
397 |
line.setAttribute("fill-opacity", "0.4");
|
|
|
398 |
line.setAttribute("stroke", series.color);
|
|
|
399 |
line.setAttribute("stroke-width", "1");
|
|
|
400 |
line.setAttribute("stroke-opacity", "0.8");
|
|
|
401 |
line.setAttribute("title", series.label);
|
|
|
402 |
chart.dataGroup.appendChild(line);
|
|
|
403 |
var path = [];
|
|
|
404 |
for (var i = 0; i < series.values.length; i++) {
|
|
|
405 |
var x = self.getX(series.values[i].x, chart);
|
|
|
406 |
var y = self.getY(series.values[i].value, chart);
|
|
|
407 |
var dx = chart.properties.padding.left + 1;
|
|
|
408 |
var dy = chart.properties.height - chart.properties.padding.bottom;
|
|
|
409 |
if (i > 0) {
|
|
|
410 |
dx = x - self.getX(series.values[i - 1].x, chart);
|
|
|
411 |
dy = self.getY(series.values[i - 1].value, chart);
|
|
|
412 |
}
|
|
|
413 |
if (i == 0) {
|
|
|
414 |
path.push("M");
|
|
|
415 |
} else {
|
|
|
416 |
path.push("C");
|
|
|
417 |
var cx = x - (tension - 1) * (dx / tension);
|
|
|
418 |
path.push(cx + "," + dy);
|
|
|
419 |
cx = x - (dx / tension);
|
|
|
420 |
path.push(cx + "," + y);
|
|
|
421 |
}
|
|
|
422 |
path.push(x + "," + y);
|
|
|
423 |
}
|
|
|
424 |
path.push("L");
|
|
|
425 |
path.push(x + "," + self.getY(0, chart));
|
|
|
426 |
path.push("L");
|
|
|
427 |
path.push(self.getX(0, chart) + "," + self.getY(0, chart));
|
|
|
428 |
path.push("Z");
|
|
|
429 |
line.setAttribute("d", path.join(" "));
|
|
|
430 |
}, plotters["scatter"] = function (series, chart) {
|
|
|
431 |
var r = 7;
|
|
|
432 |
for (var i = 0; i < series.values.length; i++) {
|
|
|
433 |
var x = self.getX(series.values[i].x, chart);
|
|
|
434 |
var y = self.getY(series.values[i].value, chart);
|
|
|
435 |
var point = document.createElementNS(dojo.svg.xmlns.svg, "path");
|
|
|
436 |
point.setAttribute("fill", series.color);
|
|
|
437 |
point.setAttribute("stroke-width", "0");
|
|
|
438 |
point.setAttribute("title", series.label + ": " + series.values[i].value);
|
|
|
439 |
point.setAttribute("d", "M " + x + "," + (y - r) + " " + "Q " + x + "," + y + " " + (x + r) + "," + y + " " + "Q " + x + "," + y + " " + x + "," + (y + r) + " " + "Q " + x + "," + y + " " + (x - r) + "," + y + " " + "Q " + x + "," + y + " " + x + "," + (y - r) + " " + "Z");
|
|
|
440 |
chart.dataGroup.appendChild(point);
|
|
|
441 |
}
|
|
|
442 |
};
|
|
|
443 |
plotters["bubble"] = function (series, chart) {
|
|
|
444 |
var minR = 1;
|
|
|
445 |
var min = chart.properties.axes.x.range.min;
|
|
|
446 |
var max = chart.properties.axes.x.range.max;
|
|
|
447 |
var ofst = 0 - min;
|
|
|
448 |
min += ofst;
|
|
|
449 |
max += ofst;
|
|
|
450 |
var xmin = chart.properties.padding.left;
|
|
|
451 |
var xmax = chart.properties.width - chart.properties.padding.right;
|
|
|
452 |
var factor = (max - min) / (xmax - xmin) * 25;
|
|
|
453 |
for (var i = 0; i < series.values.length; i++) {
|
|
|
454 |
var size = series.values[i].size;
|
|
|
455 |
if (isNaN(parseFloat(size))) {
|
|
|
456 |
size = minR;
|
|
|
457 |
}
|
|
|
458 |
var point = document.createElementNS(dojo.svg.xmlns.svg, "circle");
|
|
|
459 |
point.setAttribute("stroke-width", 0);
|
|
|
460 |
point.setAttribute("fill", series.color);
|
|
|
461 |
point.setAttribute("fill-opacity", "0.8");
|
|
|
462 |
point.setAttribute("r", (parseFloat(size) * factor) / 2);
|
|
|
463 |
point.setAttribute("cx", self.getX(series.values[i].x, chart));
|
|
|
464 |
point.setAttribute("cy", self.getY(series.values[i].value, chart));
|
|
|
465 |
point.setAttribute("title", series.label + ": " + series.values[i].value + " (" + size + ")");
|
|
|
466 |
chart.dataGroup.appendChild(point);
|
|
|
467 |
}
|
|
|
468 |
};
|
|
|
469 |
}();
|
|
|
470 |
|