X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/examples/charts/ScatterRenderer.js?ds=inline diff --git a/examples/charts/ScatterRenderer.js b/examples/charts/ScatterRenderer.js new file mode 100644 index 00000000..77412d30 --- /dev/null +++ b/examples/charts/ScatterRenderer.js @@ -0,0 +1,444 @@ +Ext.require('Ext.chart.*'); +Ext.require(['Ext.Window', 'Ext.fx.target.Sprite', 'Ext.layout.container.Fit']); + +var Renderers = {}; + +(function() { + var ColorManager = { + rgbToHsv: function(rgb) { + var r = rgb[0] / 255, + g = rgb[1] / 255, + b = rgb[2] / 255, + rd = Math.round, + minVal = Math.min(r, g, b), + maxVal = Math.max(r, g, b), + delta = maxVal - minVal, + h = 0, s = 0, v = 0, + deltaRgb; + + v = maxVal; + + if (delta == 0) { + return [0, 0, v]; + } else { + s = delta / maxVal; + deltaRgb = { + r: (((maxVal - r) / 6) + (delta / 2)) / delta, + g: (((maxVal - g) / 6) + (delta / 2)) / delta, + b: (((maxVal - b) / 6) + (delta / 2)) / delta + }; + if (r == maxVal) { + h = deltaRgb.b - deltaRgb.g; + } else if (g == maxVal) { + h = (1 / 3) + deltaRgb.r - deltaRgb.b; + } else if (b == maxVal) { + h = (2 / 3) + deltaRgb.g - deltaRgb.r; + } + //handle edge cases for hue + if (h < 0) { + h += 1; + } + if (h > 1) { + h -= 1; + } + } + + h = rd(h * 360); + s = rd(s * 100); + v = rd(v * 100); + + return [h, s, v]; + }, + + hsvToRgb : function(hsv) { + var h = hsv[0] / 360, + s = hsv[1] / 100, + v = hsv[2] / 100, + r, g, b, rd = Math.round; + + if (s == 0) { + v *= 255; + return [v, v, v]; + } else { + var vh = h * 6, + vi = vh >> 0, + v1 = v * (1 - s), + v2 = v * (1 - s * (vh - vi)), + v3 = v * (1 - s * (1 - (vh - vi))); + + switch(vi) { + case 0: + r = v; g = v3; b = v1; + break; + case 1: + r = v2; g = v; b = v1; + break; + case 2: + r = v1; g = v; b = v3; + break; + case 3: + r = v1; g = v2; b = v; + break; + case 4: + r = v3; g = v1; b = v; + break; + default: + r = v; g = v1; b = v2; + } + return [rd(r * 255), + rd(g * 255), + rd(b * 255)]; + } + } + }; + //Generic number interpolator + var delta = function(x, y, a, b, theta) { + return a + (b - a) * (y - theta) / (y - x); + }; + //Add renderer methods. + Ext.apply(Renderers, { + color: function(fieldName, minColor, maxColor, minValue, maxValue) { + var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/, + minColorMatch = minColor.match(re), + maxColorMatch = maxColor.match(re), + interpolate = function(theta) { + return [ delta(minValue, maxValue, minColor[0], maxColor[0], theta), + delta(minValue, maxValue, minColor[1], maxColor[1], theta), + delta(minValue, maxValue, minColor[2], maxColor[2], theta) ]; + }; + minColor = ColorManager.rgbToHsv([ +minColorMatch[1], +minColorMatch[2], +minColorMatch[3] ]); + maxColor = ColorManager.rgbToHsv([ +maxColorMatch[1], +maxColorMatch[2], +maxColorMatch[3] ]); + //Return the renderer + return function(sprite, record, attr, index, store) { + var value = +record.get(fieldName), + rgb = ColorManager.hsvToRgb(interpolate(value)), + rgbString = 'rgb(' + rgb[0] + ', ' + rgb[1] + ', ' + rgb[2] + ')'; + return Ext.apply(attr, { + fill: rgbString + }); + }; + }, + + grayscale: function(fieldName, minColor, maxColor, minValue, maxValue) { + var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/, + minColorMatch = minColor.match(re), + maxColorMatch = maxColor.match(re), + interpolate = function(theta) { + var ans = delta(minValue, maxValue, +minColorMatch[1], +maxColorMatch[1], theta) >> 0; + return [ ans, ans, ans ]; + }; + //Return the renderer + return function(sprite, record, attr, index, store) { + var value = +record.get(fieldName), + rgb = interpolate(value), + rgbString = 'rgb(' + rgb[0] + ', ' + rgb[1] + ', ' + rgb[2] + ')'; + + return Ext.apply(attr, { + fill: rgbString, + strokeFill: 'rgb(0, 0, 0)' + }); + }; + }, + + radius: function(fieldName, minRadius, maxRadius, minValue, maxValue) { + var interpolate = function(theta) { + return delta(minValue, maxValue, minRadius, maxRadius, theta); + }; + //Return the renderer + return function(sprite, record, attr, index, store) { + var value = +record.get(fieldName), + radius = interpolate(value); + + return Ext.apply(attr, { + radius: radius, + size: radius + }); + }; + } + }); +})(); + +Ext.onReady(function () { + //current renderer configuration + var rendererConfiguration = { + xField: 'data1', + yField: 'data2', + color: false, + colorFrom: 'rgb(250, 20, 20)', + colorTo: 'rgb(127, 0, 240)', + scale: false, + scaleFrom: 'rgb(20, 20, 20)', + scaleTo: 'rgb(220, 220, 220)', + radius: false, + radiusSize: 50 + }; + //update the visualization with the new renderer configuration + function refresh() { + var chart = Ext.getCmp('chartCmp'), + series = chart.series.items, + len = series.length, + rc = rendererConfiguration, + color, grayscale, radius, s; + + for(var i = 0; i < len; i++) { + s = series[i]; + s.xField = rc.xField; + s.yField = rc.yField; + color = rc.color? Renderers.color(rc.color, rc.colorFrom, rc.colorTo, 0, 100) : function(a, b, attr) { return attr; }; + grayscale = rc.grayscale? Renderers.grayscale(rc.grayscale, rc.scaleFrom, rc.scaleTo, 0, 100) : function(a, b, attr) { return attr; }; + radius = rc.radius? Renderers.radius(rc.radius, 10, rc.radiusSize, 0, 100) : function(a, b, attr) { return attr; }; + s.renderer = function(sprite, record, attr, index, store) { + return radius(sprite, record, grayscale(sprite, record, color(sprite, record, attr, index, store), index, store), index, store); + }; + } + chart.redraw(); + } + //form selection callbacks/handlers. + var xAxisHandler = function(elem) { + var xField = elem.text; + rendererConfiguration.xField = xField; + refresh(); + }; + + var yAxisHandler = function(elem) { + var yField = elem.text; + rendererConfiguration.yField = yField; + refresh(); + }; + + var colorVariableHandler = function(elem) { + var color = elem.text; + rendererConfiguration.color = color; + rendererConfiguration.grayscale = false; + refresh(); + }; + + var grayscaleVariableHandler = function(elem) { + var color = elem.text; + rendererConfiguration.grayscale = color; + rendererConfiguration.color = false; + refresh(); + }; + + var scaleFromHandler = function(elem) { + var from = elem.text; + rendererConfiguration.scaleFrom = from; + refresh(); + }; + + var scaleToHandler = function(elem) { + var to = elem.text; + rendererConfiguration.scaleTo = to; + refresh(); + }; + + var colorFromHandler = function(elem) { + var from = elem.text; + rendererConfiguration.colorFrom = from; + refresh(); + }; + + var colorToHandler = function(elem) { + var to = elem.text; + rendererConfiguration.colorTo = to; + refresh(); + }; + + var radiusHandler = function(elem) { + var radius = elem.text; + rendererConfiguration.radius = radius; + refresh(); + }; + + var radiusSizeHandler = function(elem) { + var radius = elem.text; + rendererConfiguration.radiusSize = parseInt(radius, 10); + refresh(); + }; + + var xAxisMenu = Ext.create('Ext.menu.Menu', { + id: 'xAxisMenu', + items: [ { + text: 'data1', + handler: xAxisHandler, + checked: true, + group: 'x' + }, + { + text: 'data2', + handler: xAxisHandler, + checked: false, + group: 'x' + }, + { + text: 'data3', + handler: xAxisHandler, + checked: false, + group: 'x' + } ] + }); + + var yAxisMenu = Ext.create('Ext.menu.Menu', { + id: 'yAxisMenu', + items: [ { + text: 'data1', + handler: yAxisHandler, + checked: false, + group: 'y' + }, + { + text: 'data2', + handler: yAxisHandler, + checked: true, + group: 'y' + }, + { + text: 'data3', + handler: yAxisHandler, + checked: false, + group: 'y' + } ] + }); + + var colorMenu = Ext.create('Ext.menu.Menu', { + id: 'colorMenu', + items: [ { text: 'data1', handler: colorVariableHandler, checked: false, group: 'color' }, + { text: 'data2', handler: colorVariableHandler, checked: false, group: 'color' }, + { text: 'data3', handler: colorVariableHandler, checked: false, group: 'color' }, + { text: 'Color From', + menu: { + items: [{ text: 'rgb(250, 20, 20)', handler: colorToHandler, checked: true, group: 'colorrange' }, + { text: 'rgb(20, 250, 20)', handler: colorToHandler, checked: false, group: 'colorrange' }, + { text: 'rgb(20, 20, 250)', handler: colorToHandler, checked: false, group: 'colorrange' }, + { text: 'rgb(127, 0, 240)', handler: colorFromHandler, checked: false, group: 'colorrange' }, + { text: 'rgb(213, 70, 121)', handler: colorToHandler, checked: false, group: 'colorrange' }, + { text: 'rgb(44, 153, 201)', handler: colorFromHandler, checked: false, group: 'colorrange' }, + { text: 'rgb(146, 6, 157)', handler: colorFromHandler, checked: false, group: 'colorrange' }, + { text: 'rgb(49, 149, 0)', handler: colorFromHandler, checked: false, group: 'colorrange' }, + { text: 'rgb(249, 153, 0)', handler: colorFromHandler, checked: false, group: 'colorrange' }] + } + }, + { text: 'Color To', + menu: { + items: [{ text: 'rgb(250, 20, 20)', handler: colorToHandler, checked: false, group: 'tocolorrange' }, + { text: 'rgb(20, 250, 20)', handler: colorToHandler, checked: false, group: 'tocolorrange' }, + { text: 'rgb(20, 20, 250)', handler: colorToHandler, checked: false, group: 'tocolorrange' }, + { text: 'rgb(127, 0, 220)', handler: colorFromHandler, checked: true, group: 'tocolorrange' }, + { text: 'rgb(213, 70, 121)', handler: colorToHandler, checked: false, group: 'tocolorrange' }, + { text: 'rgb(44, 153, 201)', handler: colorToHandler, checked: false, group: 'tocolorrange' }, + { text: 'rgb(146, 6, 157)' , handler: colorToHandler, checked: false, group: 'tocolorrange' }, + { text: 'rgb(49, 149, 0)', handler: colorToHandler, checked: false, group: 'tocolorrange' }, + { text: 'rgb(249, 153, 0)', handler: colorToHandler, checked: false, group: 'tocolorrange' }] + } + } + ] + }); + + var grayscaleMenu = Ext.create('Ext.menu.Menu', { + id: 'grayscaleMenu', + items: [ { text: 'data1', handler: grayscaleVariableHandler, checked: false, group: 'gs' }, + { text: 'data2', handler: grayscaleVariableHandler, checked: false, group: 'gs' }, + { text: 'data3', handler: grayscaleVariableHandler, checked: false, group: 'gs' }, + { text: 'Scale From', + menu: { + items: [{ text: 'rgb(20, 20, 20)', handler: scaleFromHandler, checked: true, group: 'gsrange' }, + { text: 'rgb(80, 80, 80)', handler: scaleFromHandler, checked: false, group: 'gsrange' }, + { text: 'rgb(120, 120, 120)', handler: scaleFromHandler, checked: false, group: 'gsrange' }, + { text: 'rgb(180, 180, 180)', handler: scaleFromHandler, checked: false, group: 'gsrange' }, + { text: 'rgb(220, 220, 220)', handler: scaleFromHandler, checked: false, group: 'gsrange' }, + { text: 'rgb(250, 250, 250)', handler: scaleFromHandler, checked: false, group: 'gsrange' }] + } + }, + { text: 'Scale To', + menu: { + items: [{ text: 'rgb(20, 20, 20)', handler: scaleToHandler, checked: false, group: 'togsrange' }, + { text: 'rgb(80, 80, 80)', handler: scaleToHandler, checked: false, group: 'togsrange' }, + { text: 'rgb(120, 120, 120)', handler: scaleToHandler, checked: false, group: 'togsrange' }, + { text: 'rgb(180, 180, 180)', handler: scaleToHandler, checked: false, group: 'togsrange' }, + { text: 'rgb(220, 220, 220)', handler: scaleToHandler, checked: true, group: 'togsrange' }, + { text: 'rgb(250, 250, 250)', handler: scaleToHandler, checked: false, group: 'togsrange' }] + } + } + ] + }); + + var radiusMenu = Ext.create('Ext.menu.Menu', { + id: 'radiusMenu', + style: { + overflow: 'visible' // For the Combo popup + }, + items: [ { text: 'data1', handler: radiusHandler, checked: false, group: 'radius' }, + { text: 'data2', handler: radiusHandler, checked: false, group: 'radius' }, + { text: 'data3', handler: radiusHandler, checked: false, group: 'radius' }, + { text: 'Max Radius', + menu: { + items: [{ text: '20', handler: radiusSizeHandler, checked: false, group: 'sradius' }, + { text: '30', handler: radiusSizeHandler, checked: false, group: 'sradius' }, + { text: '40', handler: radiusSizeHandler, checked: false, group: 'sradius' }, + { text: '50', handler: radiusSizeHandler, checked: true, group: 'sradius' }, + { text: '60', handler: radiusSizeHandler, checked: false, group: 'sradius' }] + } + } + ] + }); + + var win = Ext.create('Ext.Window', { + width: 800, + height: 600, + hidden: false, + maximizable: true, + title: 'Scatter Chart Renderer', + renderTo: Ext.getBody(), + layout: 'fit', + tbar: [ + { + text: 'Reload Data', + handler: function() { + store1.loadData(generateData()); + } + }, + { + text: 'Select X Axis', + menu: xAxisMenu + }, + { + text: 'Select Y Axis', + menu: yAxisMenu + }, + + { + text: 'Select Color', + menu: colorMenu + }, + { + text: 'Select Grayscale', + menu: grayscaleMenu + }, + { + text: 'Select Radius', + menu: radiusMenu + } + ], + items: { + id: 'chartCmp', + xtype: 'chart', + style: 'background:#fff', + animate: true, + store: store1, + axes: false, + insetPadding: 50, + series: [{ + type: 'scatter', + axis: false, + xField: 'data1', + yField: 'data2', + color: '#ccc', + markerConfig: { + type: 'circle', + radius: 20, + size: 20 + } + }] + } + }); +});