Initial check-in
[dygraphs.git] / plotkit_v091 / PlotKit / SweetCanvas.js
1 /*
2 PlotKit Sweet Canvas Renderer
3 =============================
4 Canvas Renderer for PlotKit which looks pretty!
5
6 Copyright
7 ---------
8 Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
9 For use under the BSD license. <http://www.liquidx.net/plotkit>
10 */
11
12 // -------------------------------------------------------------------------
13 // Check required components
14 // -------------------------------------------------------------------------
15
16 try {
17 if (typeof(PlotKit.CanvasRenderer) == 'undefined')
18 {
19 throw "";
20 }
21 }
22 catch (e) {
23 throw "SweetCanvas depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, Canvas}"
24 }
25
26
27 if (typeof(PlotKit.SweetCanvasRenderer) == 'undefined') {
28 PlotKit.SweetCanvasRenderer = {};
29 }
30
31 PlotKit.SweetCanvasRenderer = function(element, layout, options) {
32 if (arguments.length > 0) {
33 this.__init__(element, layout, options);
34 }
35 };
36
37 PlotKit.SweetCanvasRenderer.NAME = "PlotKit.SweetCanvasRenderer";
38 PlotKit.SweetCanvasRenderer.VERSION = PlotKit.VERSION;
39
40 PlotKit.SweetCanvasRenderer.__repr__ = function() {
41 return "[" + this.NAME + " " + this.VERSION + "]";
42 };
43
44 PlotKit.SweetCanvasRenderer.toString = function() {
45 return this.__repr__();
46 };
47
48 // ---------------------------------------------------------------------
49 // Subclassing Magic
50 // ---------------------------------------------------------------------
51
52 PlotKit.SweetCanvasRenderer.prototype = new PlotKit.CanvasRenderer();
53 PlotKit.SweetCanvasRenderer.prototype.constructor = PlotKit.SweetCanvasRenderer;
54 PlotKit.SweetCanvasRenderer.__super__ = PlotKit.CanvasRenderer.prototype;
55
56 // ---------------------------------------------------------------------
57 // Constructor
58 // ---------------------------------------------------------------------
59
60 PlotKit.SweetCanvasRenderer.prototype.__init__ = function(el, layout, opts) {
61 var moreOpts = PlotKit.Base.officeBlue();
62 MochiKit.Base.update(moreOpts, opts);
63 PlotKit.SweetCanvasRenderer.__super__.__init__.call(this, el, layout, moreOpts);
64 };
65
66 // ---------------------------------------------------------------------
67 // Extended Plotting Functions
68 // ---------------------------------------------------------------------
69
70 PlotKit.SweetCanvasRenderer.prototype._renderBarChart = function() {
71 var bind = MochiKit.Base.bind;
72 var shadowColor = Color.blackColor().colorWithAlpha(0.1).toRGBString();
73
74 var prepareFakeShadow = function(context, x, y, w, h) {
75 context.fillStyle = shadowColor;
76 context.fillRect(x-2, y-2, w+4, h+2);
77 context.fillStyle = shadowColor;
78 context.fillRect(x-1, y-1, w+2, h+1);
79 };
80
81 var colorCount = this.options.colorScheme.length;
82 var colorScheme = this.options.colorScheme;
83 var setNames = PlotKit.Base.keys(this.layout.datasets);
84 var setCount = setNames.length;
85
86 var chooseColor = function(name) {
87 for (var i = 0; i < setCount; i++) {
88 if (name == setNames[i])
89 return colorScheme[i%colorCount];
90 }
91 return colorScheme[0];
92 };
93
94 var drawRect = function(context, bar) {
95 var x = this.area.w * bar.x + this.area.x;
96 var y = this.area.h * bar.y + this.area.y;
97 var w = this.area.w * bar.w;
98 var h = this.area.h * bar.h;
99
100 if ((w < 1) || (h < 1))
101 return;
102
103 context.save();
104
105 context.shadowBlur = 5.0;
106 context.shadowColor = Color.fromHexString("#888888").toRGBString();
107
108 if (this.isIE) {
109 context.save();
110 context.fillStyle = "#cccccc";
111 context.fillRect(x-2, y-2, w+4, h+2);
112 context.restore();
113 }
114 else {
115 prepareFakeShadow(context, x, y, w, h);
116 }
117
118 if (this.options.shouldFill) {
119 context.fillStyle = chooseColor(bar.name).toRGBString();
120 context.fillRect(x, y, w, h);
121 }
122
123 context.shadowBlur = 0;
124 context.strokeStyle = Color.whiteColor().toRGBString();
125 context.lineWidth = 2.0;
126
127 if (this.options.shouldStroke) {
128 context.strokeRect(x, y, w, h);
129 }
130
131 context.restore();
132
133 };
134 this._renderBarChartWrap(this.layout.bars, bind(drawRect, this));
135 };
136
137 PlotKit.SweetCanvasRenderer.prototype._renderLineChart = function() {
138 var context = this.element.getContext("2d");
139 var colorCount = this.options.colorScheme.length;
140 var colorScheme = this.options.colorScheme;
141 var setNames = PlotKit.Base.keys(this.layout.datasets);
142 var setCount = setNames.length;
143 var bind = MochiKit.Base.bind;
144
145
146 for (var i = 0; i < setCount; i++) {
147 var setName = setNames[i];
148 var color = colorScheme[i%colorCount];
149 var strokeX = this.options.strokeColorTransform;
150
151 // setup graphics context
152 context.save();
153
154 // create paths
155 var makePath = function(ctx) {
156 ctx.beginPath();
157 ctx.moveTo(this.area.x, this.area.y + this.area.h);
158 var addPoint = function(ctx_, point) {
159 if (point.name == setName)
160 ctx_.lineTo(this.area.w * point.x + this.area.x,
161 this.area.h * point.y + this.area.y);
162 };
163 MochiKit.Iter.forEach(this.layout.points, partial(addPoint, ctx), this);
164 ctx.lineTo(this.area.w + this.area.x,
165 this.area.h + this.area.y);
166 ctx.lineTo(this.area.x, this.area.y + this.area.h);
167 ctx.closePath();
168 };
169
170 // faux shadow for firefox
171 if (this.options.shouldFill) {
172 context.save();
173 if (this.isIE) {
174 context.fillStyle = "#cccccc";
175 }
176 else {
177 context.fillStyle = Color.blackColor().colorWithAlpha(0.2).toRGBString();
178 }
179 context.translate(-1, -2);
180 bind(makePath, this)(context);
181 if (this.options.shouldFill) {
182 context.fill();
183 }
184 context.restore();
185 }
186
187 context.shadowBlur = 5.0;
188 context.shadowColor = Color.fromHexString("#888888").toRGBString();
189 context.fillStyle = color.toRGBString();
190 context.lineWidth = 2.0;
191 context.strokeStyle = Color.whiteColor().toRGBString();
192
193 if (this.options.shouldFill) {
194 bind(makePath, this)(context);
195 context.fill();
196 }
197 if (this.options.shouldStroke) {
198 bind(makePath, this)(context);
199 context.stroke();
200 }
201 context.restore();
202 }
203 };
204
205 PlotKit.SweetCanvasRenderer.prototype._renderPieChart = function() {
206 var context = this.element.getContext("2d");
207
208 var colorCount = this.options.colorScheme.length;
209 var slices = this.layout.slices;
210
211 var centerx = this.area.x + this.area.w * 0.5;
212 var centery = this.area.y + this.area.h * 0.5;
213 var radius = Math.min(this.area.w * this.options.pieRadius,
214 this.area.h * this.options.pieRadius);
215
216 if (this.isIE) {
217 centerx = parseInt(centerx);
218 centery = parseInt(centery);
219 radius = parseInt(radius);
220 }
221
222 // NOTE NOTE!! Canvas Tag draws the circle clockwise from the y = 0, x = 1
223 // so we have to subtract 90 degrees to make it start at y = 1, x = 0
224
225 if (!this.isIE) {
226 context.save();
227 var shadowColor = Color.blackColor().colorWithAlpha(0.2);
228 context.fillStyle = shadowColor.toRGBString();
229 context.shadowBlur = 5.0;
230 context.shadowColor = Color.fromHexString("#888888").toRGBString();
231 context.translate(1, 1);
232 context.beginPath();
233 context.moveTo(centerx, centery);
234 context.arc(centerx, centery, radius + 2, 0, Math.PI*2, false);
235 context.closePath();
236 context.fill();
237 context.restore();
238 }
239
240 context.save();
241 context.strokeStyle = Color.whiteColor().toRGBString();
242 context.lineWidth = 2.0;
243 for (var i = 0; i < slices.length; i++) {
244 var color = this.options.colorScheme[i%colorCount];
245 context.fillStyle = color.toRGBString();
246
247 var makePath = function() {
248 context.beginPath();
249 context.moveTo(centerx, centery);
250 context.arc(centerx, centery, radius,
251 slices[i].startAngle - Math.PI/2,
252 slices[i].endAngle - Math.PI/2,
253 false);
254 context.lineTo(centerx, centery);
255 context.closePath();
256 };
257
258 if (Math.abs(slices[i].startAngle - slices[i].endAngle) > 0.0001) {
259 if (this.options.shouldFill) {
260 makePath();
261 context.fill();
262 }
263 if (this.options.shouldStroke) {
264 makePath();
265 context.stroke();
266 }
267 }
268 }
269 context.restore();
270 };
271
272 PlotKit.SweetCanvasRenderer.prototype._renderBackground = function() {
273 var context = this.element.getContext("2d");
274
275 if (this.layout.style == "bar" || this.layout.style == "line") {
276 context.save();
277 context.fillStyle = this.options.backgroundColor.toRGBString();
278 context.fillRect(this.area.x, this.area.y, this.area.w, this.area.h);
279 context.strokeStyle = this.options.axisLineColor.toRGBString();
280 context.lineWidth = 1.0;
281
282 var ticks = this.layout.yticks;
283 var horiz = false;
284 if (this.layout.style == "bar" &&
285 this.layout.options.barOrientation == "horizontal") {
286 ticks = this.layout.xticks;
287 horiz = true;
288 }
289
290 for (var i = 0; i < ticks.length; i++) {
291 var x1 = 0;
292 var y1 = 0;
293 var x2 = 0;
294 var y2 = 0;
295
296 if (horiz) {
297 x1 = ticks[i][0] * this.area.w + this.area.x;
298 y1 = this.area.y;
299 x2 = x1;
300 y2 = y1 + this.area.h;
301 }
302 else {
303 x1 = this.area.x;
304 y1 = ticks[i][0] * this.area.h + this.area.y;
305 x2 = x1 + this.area.w;
306 y2 = y1;
307 }
308
309 context.beginPath();
310 context.moveTo(x1, y1);
311 context.lineTo(x2, y2);
312 context.closePath();
313 context.stroke();
314 }
315 context.restore();
316 }
317 else {
318 PlotKit.SweetCanvasRenderer.__super__._renderBackground.call(this);
319 }
320 };
321
322 // Namespace Iniitialisation
323
324 PlotKit.SweetCanvas = {}
325 PlotKit.SweetCanvas.SweetCanvasRenderer = PlotKit.SweetCanvasRenderer;
326
327 PlotKit.SweetCanvas.EXPORT = [
328 "SweetCanvasRenderer"
329 ];
330
331 PlotKit.SweetCanvas.EXPORT_OK = [
332 "SweetCanvasRenderer"
333 ];
334
335 PlotKit.SweetCanvas.__new__ = function() {
336 var m = MochiKit.Base;
337
338 m.nameFunctions(this);
339
340 this.EXPORT_TAGS = {
341 ":common": this.EXPORT,
342 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
343 };
344 };
345
346 PlotKit.SweetCanvas.__new__();
347 MochiKit.Base._exportSymbols(this, PlotKit.SweetCanvas);
348