1 Ext.require('Ext.chart.*');
2 Ext.require(['Ext.Window', 'Ext.fx.target.Sprite', 'Ext.layout.container.Fit']);
8 rgbToHsv: function(rgb) {
13 minVal = Math.min(r, g, b),
14 maxVal = Math.max(r, g, b),
15 delta = maxVal - minVal,
26 r: (((maxVal - r) / 6) + (delta / 2)) / delta,
27 g: (((maxVal - g) / 6) + (delta / 2)) / delta,
28 b: (((maxVal - b) / 6) + (delta / 2)) / delta
31 h = deltaRgb.b - deltaRgb.g;
32 } else if (g == maxVal) {
33 h = (1 / 3) + deltaRgb.r - deltaRgb.b;
34 } else if (b == maxVal) {
35 h = (2 / 3) + deltaRgb.g - deltaRgb.r;
37 //handle edge cases for hue
53 hsvToRgb : function(hsv) {
57 r, g, b, rd = Math.round;
66 v2 = v * (1 - s * (vh - vi)),
67 v3 = v * (1 - s * (1 - (vh - vi)));
71 r = v; g = v3; b = v1;
74 r = v2; g = v; b = v1;
77 r = v1; g = v; b = v3;
80 r = v1; g = v2; b = v;
83 r = v3; g = v1; b = v;
86 r = v; g = v1; b = v2;
94 //Generic number interpolator
95 var delta = function(x, y, a, b, theta) {
96 return a + (b - a) * (y - theta) / (y - x);
98 //Add renderer methods.
99 Ext.apply(Renderers, {
100 color: function(fieldName, minColor, maxColor, minValue, maxValue) {
101 var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/,
102 minColorMatch = minColor.match(re),
103 maxColorMatch = maxColor.match(re),
104 interpolate = function(theta) {
105 return [ delta(minValue, maxValue, minColor[0], maxColor[0], theta),
106 delta(minValue, maxValue, minColor[1], maxColor[1], theta),
107 delta(minValue, maxValue, minColor[2], maxColor[2], theta) ];
109 minColor = ColorManager.rgbToHsv([ +minColorMatch[1], +minColorMatch[2], +minColorMatch[3] ]);
110 maxColor = ColorManager.rgbToHsv([ +maxColorMatch[1], +maxColorMatch[2], +maxColorMatch[3] ]);
111 //Return the renderer
112 return function(sprite, record, attr, index, store) {
113 var value = +record.get(fieldName),
114 rgb = ColorManager.hsvToRgb(interpolate(value)),
115 rgbString = 'rgb(' + rgb[0] + ', ' + rgb[1] + ', ' + rgb[2] + ')';
116 return Ext.apply(attr, {
122 grayscale: function(fieldName, minColor, maxColor, minValue, maxValue) {
123 var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/,
124 minColorMatch = minColor.match(re),
125 maxColorMatch = maxColor.match(re),
126 interpolate = function(theta) {
127 var ans = delta(minValue, maxValue, +minColorMatch[1], +maxColorMatch[1], theta) >> 0;
128 return [ ans, ans, ans ];
130 //Return the renderer
131 return function(sprite, record, attr, index, store) {
132 var value = +record.get(fieldName),
133 rgb = interpolate(value),
134 rgbString = 'rgb(' + rgb[0] + ', ' + rgb[1] + ', ' + rgb[2] + ')';
136 return Ext.apply(attr, {
138 strokeFill: 'rgb(0, 0, 0)'
143 radius: function(fieldName, minRadius, maxRadius, minValue, maxValue) {
144 var interpolate = function(theta) {
145 return delta(minValue, maxValue, minRadius, maxRadius, theta);
147 //Return the renderer
148 return function(sprite, record, attr, index, store) {
149 var value = +record.get(fieldName),
150 radius = interpolate(value);
152 return Ext.apply(attr, {
161 Ext.onReady(function () {
162 //current renderer configuration
163 var rendererConfiguration = {
167 colorFrom: 'rgb(250, 20, 20)',
168 colorTo: 'rgb(127, 0, 240)',
170 scaleFrom: 'rgb(20, 20, 20)',
171 scaleTo: 'rgb(220, 220, 220)',
175 //update the visualization with the new renderer configuration
177 var chart = Ext.getCmp('chartCmp'),
178 series = chart.series.items,
180 rc = rendererConfiguration,
181 color, grayscale, radius, s;
183 for(var i = 0; i < len; i++) {
185 s.xField = rc.xField;
186 s.yField = rc.yField;
187 color = rc.color? Renderers.color(rc.color, rc.colorFrom, rc.colorTo, 0, 100) : function(a, b, attr) { return attr; };
188 grayscale = rc.grayscale? Renderers.grayscale(rc.grayscale, rc.scaleFrom, rc.scaleTo, 0, 100) : function(a, b, attr) { return attr; };
189 radius = rc.radius? Renderers.radius(rc.radius, 10, rc.radiusSize, 0, 100) : function(a, b, attr) { return attr; };
190 s.renderer = function(sprite, record, attr, index, store) {
191 return radius(sprite, record, grayscale(sprite, record, color(sprite, record, attr, index, store), index, store), index, store);
196 //form selection callbacks/handlers.
197 var xAxisHandler = function(elem) {
198 var xField = elem.text;
199 rendererConfiguration.xField = xField;
203 var yAxisHandler = function(elem) {
204 var yField = elem.text;
205 rendererConfiguration.yField = yField;
209 var colorVariableHandler = function(elem) {
210 var color = elem.text;
211 rendererConfiguration.color = color;
212 rendererConfiguration.grayscale = false;
216 var grayscaleVariableHandler = function(elem) {
217 var color = elem.text;
218 rendererConfiguration.grayscale = color;
219 rendererConfiguration.color = false;
223 var scaleFromHandler = function(elem) {
224 var from = elem.text;
225 rendererConfiguration.scaleFrom = from;
229 var scaleToHandler = function(elem) {
231 rendererConfiguration.scaleTo = to;
235 var colorFromHandler = function(elem) {
236 var from = elem.text;
237 rendererConfiguration.colorFrom = from;
241 var colorToHandler = function(elem) {
243 rendererConfiguration.colorTo = to;
247 var radiusHandler = function(elem) {
248 var radius = elem.text;
249 rendererConfiguration.radius = radius;
253 var radiusSizeHandler = function(elem) {
254 var radius = elem.text;
255 rendererConfiguration.radiusSize = parseInt(radius, 10);
259 var xAxisMenu = Ext.create('Ext.menu.Menu', {
263 handler: xAxisHandler,
269 handler: xAxisHandler,
275 handler: xAxisHandler,
281 var yAxisMenu = Ext.create('Ext.menu.Menu', {
285 handler: yAxisHandler,
291 handler: yAxisHandler,
297 handler: yAxisHandler,
303 var colorMenu = Ext.create('Ext.menu.Menu', {
305 items: [ { text: 'data1', handler: colorVariableHandler, checked: false, group: 'color' },
306 { text: 'data2', handler: colorVariableHandler, checked: false, group: 'color' },
307 { text: 'data3', handler: colorVariableHandler, checked: false, group: 'color' },
308 { text: 'Color From',
310 items: [{ text: 'rgb(250, 20, 20)', handler: colorToHandler, checked: true, group: 'colorrange' },
311 { text: 'rgb(20, 250, 20)', handler: colorToHandler, checked: false, group: 'colorrange' },
312 { text: 'rgb(20, 20, 250)', handler: colorToHandler, checked: false, group: 'colorrange' },
313 { text: 'rgb(127, 0, 240)', handler: colorFromHandler, checked: false, group: 'colorrange' },
314 { text: 'rgb(213, 70, 121)', handler: colorToHandler, checked: false, group: 'colorrange' },
315 { text: 'rgb(44, 153, 201)', handler: colorFromHandler, checked: false, group: 'colorrange' },
316 { text: 'rgb(146, 6, 157)', handler: colorFromHandler, checked: false, group: 'colorrange' },
317 { text: 'rgb(49, 149, 0)', handler: colorFromHandler, checked: false, group: 'colorrange' },
318 { text: 'rgb(249, 153, 0)', handler: colorFromHandler, checked: false, group: 'colorrange' }]
323 items: [{ text: 'rgb(250, 20, 20)', handler: colorToHandler, checked: false, group: 'tocolorrange' },
324 { text: 'rgb(20, 250, 20)', handler: colorToHandler, checked: false, group: 'tocolorrange' },
325 { text: 'rgb(20, 20, 250)', handler: colorToHandler, checked: false, group: 'tocolorrange' },
326 { text: 'rgb(127, 0, 220)', handler: colorFromHandler, checked: true, group: 'tocolorrange' },
327 { text: 'rgb(213, 70, 121)', handler: colorToHandler, checked: false, group: 'tocolorrange' },
328 { text: 'rgb(44, 153, 201)', handler: colorToHandler, checked: false, group: 'tocolorrange' },
329 { text: 'rgb(146, 6, 157)' , handler: colorToHandler, checked: false, group: 'tocolorrange' },
330 { text: 'rgb(49, 149, 0)', handler: colorToHandler, checked: false, group: 'tocolorrange' },
331 { text: 'rgb(249, 153, 0)', handler: colorToHandler, checked: false, group: 'tocolorrange' }]
337 var grayscaleMenu = Ext.create('Ext.menu.Menu', {
339 items: [ { text: 'data1', handler: grayscaleVariableHandler, checked: false, group: 'gs' },
340 { text: 'data2', handler: grayscaleVariableHandler, checked: false, group: 'gs' },
341 { text: 'data3', handler: grayscaleVariableHandler, checked: false, group: 'gs' },
342 { text: 'Scale From',
344 items: [{ text: 'rgb(20, 20, 20)', handler: scaleFromHandler, checked: true, group: 'gsrange' },
345 { text: 'rgb(80, 80, 80)', handler: scaleFromHandler, checked: false, group: 'gsrange' },
346 { text: 'rgb(120, 120, 120)', handler: scaleFromHandler, checked: false, group: 'gsrange' },
347 { text: 'rgb(180, 180, 180)', handler: scaleFromHandler, checked: false, group: 'gsrange' },
348 { text: 'rgb(220, 220, 220)', handler: scaleFromHandler, checked: false, group: 'gsrange' },
349 { text: 'rgb(250, 250, 250)', handler: scaleFromHandler, checked: false, group: 'gsrange' }]
354 items: [{ text: 'rgb(20, 20, 20)', handler: scaleToHandler, checked: false, group: 'togsrange' },
355 { text: 'rgb(80, 80, 80)', handler: scaleToHandler, checked: false, group: 'togsrange' },
356 { text: 'rgb(120, 120, 120)', handler: scaleToHandler, checked: false, group: 'togsrange' },
357 { text: 'rgb(180, 180, 180)', handler: scaleToHandler, checked: false, group: 'togsrange' },
358 { text: 'rgb(220, 220, 220)', handler: scaleToHandler, checked: true, group: 'togsrange' },
359 { text: 'rgb(250, 250, 250)', handler: scaleToHandler, checked: false, group: 'togsrange' }]
365 var radiusMenu = Ext.create('Ext.menu.Menu', {
368 overflow: 'visible' // For the Combo popup
370 items: [ { text: 'data1', handler: radiusHandler, checked: false, group: 'radius' },
371 { text: 'data2', handler: radiusHandler, checked: false, group: 'radius' },
372 { text: 'data3', handler: radiusHandler, checked: false, group: 'radius' },
373 { text: 'Max Radius',
375 items: [{ text: '20', handler: radiusSizeHandler, checked: false, group: 'sradius' },
376 { text: '30', handler: radiusSizeHandler, checked: false, group: 'sradius' },
377 { text: '40', handler: radiusSizeHandler, checked: false, group: 'sradius' },
378 { text: '50', handler: radiusSizeHandler, checked: true, group: 'sradius' },
379 { text: '60', handler: radiusSizeHandler, checked: false, group: 'sradius' }]
385 var win = Ext.create('Ext.Window', {
390 title: 'Scatter Chart Renderer',
391 renderTo: Ext.getBody(),
396 handler: function() {
397 store1.loadData(generateData());
401 text: 'Select X Axis',
405 text: 'Select Y Axis',
410 text: 'Select Color',
414 text: 'Select Grayscale',
418 text: 'Select Radius',
425 style: 'background:#fff',