2 PlotKit Sweet Canvas Renderer
3 =============================
4 Canvas Renderer for PlotKit which looks pretty!
8 Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
9 For use under the BSD license. <http://www.liquidx.net/plotkit>
12 // -------------------------------------------------------------------------
13 // Check required components
14 // -------------------------------------------------------------------------
17 if (typeof(PlotKit
.CanvasRenderer
) == 'undefined')
23 throw "SweetCanvas depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, Canvas}"
27 if (typeof(PlotKit
.SweetCanvasRenderer
) == 'undefined') {
28 PlotKit
.SweetCanvasRenderer
= {};
31 PlotKit
.SweetCanvasRenderer
= function(element
, layout
, options
) {
32 if (arguments
.length
> 0) {
33 this.__init__(element
, layout
, options
);
37 PlotKit
.SweetCanvasRenderer
.NAME
= "PlotKit.SweetCanvasRenderer";
38 PlotKit
.SweetCanvasRenderer
.VERSION
= PlotKit
.VERSION
;
40 PlotKit
.SweetCanvasRenderer
.__repr__
= function() {
41 return "[" + this.NAME
+ " " + this.VERSION
+ "]";
44 PlotKit
.SweetCanvasRenderer
.toString
= function() {
45 return this.__repr__();
48 // ---------------------------------------------------------------------
50 // ---------------------------------------------------------------------
52 PlotKit
.SweetCanvasRenderer
.prototype = new PlotKit
.CanvasRenderer();
53 PlotKit
.SweetCanvasRenderer
.prototype.constructor
= PlotKit
.SweetCanvasRenderer
;
54 PlotKit
.SweetCanvasRenderer
.__super__
= PlotKit
.CanvasRenderer
.prototype;
56 // ---------------------------------------------------------------------
58 // ---------------------------------------------------------------------
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
);
66 // ---------------------------------------------------------------------
67 // Extended Plotting Functions
68 // ---------------------------------------------------------------------
70 PlotKit
.SweetCanvasRenderer
.prototype._renderBarChart
= function() {
71 var bind
= MochiKit
.Base
.bind
;
72 var shadowColor
= Color
.blackColor().colorWithAlpha(0.1).toRGBString();
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);
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
;
86 var chooseColor
= function(name
) {
87 for (var i
= 0; i
< setCount
; i
++) {
88 if (name
== setNames
[i
])
89 return colorScheme
[i
%colorCount
];
91 return colorScheme
[0];
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
;
100 if ((w
< 1) || (h
< 1))
105 context
.shadowBlur
= 5.0;
106 context
.shadowColor
= Color
.fromHexString("#888888").toRGBString();
110 context
.fillStyle
= "#cccccc";
111 context
.fillRect(x
-2, y
-2, w
+4, h
+2);
115 prepareFakeShadow(context
, x
, y
, w
, h
);
118 if (this.options
.shouldFill
) {
119 context
.fillStyle
= chooseColor(bar
.name
).toRGBString();
120 context
.fillRect(x
, y
, w
, h
);
123 context
.shadowBlur
= 0;
124 context
.strokeStyle
= Color
.whiteColor().toRGBString();
125 context
.lineWidth
= 2.0;
127 if (this.options
.shouldStroke
) {
128 context
.strokeRect(x
, y
, w
, h
);
134 this._renderBarChartWrap(this.layout
.bars
, bind(drawRect
, this));
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
;
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
;
151 // setup graphics context
155 var makePath
= function(ctx
) {
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
);
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
);
170 // faux shadow for firefox
171 if (this.options
.shouldFill
) {
174 context
.fillStyle
= "#cccccc";
177 context
.fillStyle
= Color
.blackColor().colorWithAlpha(0.2).toRGBString();
179 context
.translate(-1, -2);
180 bind(makePath
, this)(context
);
181 if (this.options
.shouldFill
) {
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();
193 if (this.options
.shouldFill
) {
194 bind(makePath
, this)(context
);
197 if (this.options
.shouldStroke
) {
198 bind(makePath
, this)(context
);
205 PlotKit
.SweetCanvasRenderer
.prototype._renderPieChart
= function() {
206 var context
= this.element
.getContext("2d");
208 var colorCount
= this.options
.colorScheme
.length
;
209 var slices
= this.layout
.slices
;
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
);
217 centerx
= parseInt(centerx
);
218 centery
= parseInt(centery
);
219 radius
= parseInt(radius
);
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
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);
233 context
.moveTo(centerx
, centery
);
234 context
.arc(centerx
, centery
, radius
+ 2, 0, Math
.PI
*2, false);
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();
247 var makePath
= function() {
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,
254 context
.lineTo(centerx
, centery
);
258 if (Math
.abs(slices
[i
].startAngle
- slices
[i
].endAngle
) > 0.0001) {
259 if (this.options
.shouldFill
) {
263 if (this.options
.shouldStroke
) {
272 PlotKit
.SweetCanvasRenderer
.prototype._renderBackground
= function() {
273 var context
= this.element
.getContext("2d");
275 if (this.layout
.style
== "bar" || this.layout
.style
== "line") {
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;
282 var ticks
= this.layout
.yticks
;
284 if (this.layout
.style
== "bar" &&
285 this.layout
.options
.barOrientation
== "horizontal") {
286 ticks
= this.layout
.xticks
;
290 for (var i
= 0; i
< ticks
.length
; i
++) {
297 x1
= ticks
[i
][0] * this.area
.w
+ this.area
.x
;
300 y2
= y1
+ this.area
.h
;
304 y1
= ticks
[i
][0] * this.area
.h
+ this.area
.y
;
305 x2
= x1
+ this.area
.w
;
310 context
.moveTo(x1
, y1
);
311 context
.lineTo(x2
, y2
);
318 PlotKit
.SweetCanvasRenderer
.__super__
._renderBackground
.call(this);
322 // Namespace Iniitialisation
324 PlotKit
.SweetCanvas
= {}
325 PlotKit
.SweetCanvas
.SweetCanvasRenderer
= PlotKit
.SweetCanvasRenderer
;
327 PlotKit
.SweetCanvas
.EXPORT
= [
328 "SweetCanvasRenderer"
331 PlotKit
.SweetCanvas
.EXPORT_OK
= [
332 "SweetCanvasRenderer"
335 PlotKit
.SweetCanvas
.__new__
= function() {
336 var m
= MochiKit
.Base
;
338 m
.nameFunctions(this);
341 ":common": this.EXPORT
,
342 ":all": m
.concat(this.EXPORT
, this.EXPORT_OK
)
346 PlotKit
.SweetCanvas
.__new__();
347 MochiKit
.Base
._exportSymbols(this, PlotKit
.SweetCanvas
);