DevSecOpsARTIGO

Gráfico Cascata no Flex

Após um longo período sem artigos, volto à ativa com um bem interessante e bastante usual para quem desenvolve sistemas de apoio à decisão e sistemas de business intelligence.

O gráfico de cascata (waterfall, ou flying bricks chart, em inglês)
é uma ferramenta que facilita a demonstração de parcelas de um valor.
Ele é muito utilizado na apresentação da divisão da receita e exibição
do que resta de lucro em DRE, da entrada de caixa ao saldo final em
demonstrativos de Fluxo de Caixa, mas pode-se utilizá-lo em qualquer
situação em que seja necessário mostrar a “quebra” de um número.

Neste artigo vou demonstrar como desenvolver um gráfico de cascata em Adobe Flex, estendendo um ColumnChart de forma simples obtendo como resultado o exemplo abaixo.

Primeiro precisamos entender qual a estrutura do gráfico de cascata. Ele é um gráfico de colunas do tipo empilhado (stacked) com seis séries, conforme demonstrado na figura abaixo:

  1. Base, que será invisível;
  2. Vermelho Positivo, série da cor vermelha que será exibida acima do zero, ex. (-) Custos, no gráfico acima;
  3. Verde Positivo, série da cor verde que será exibida acima do zero, ex. Resultado não Op.;
  4. Vermelho Negativo, série da cor vermelha que será exibida abaixo do zero, ex. (-) Despesas;
  5. Verde Negativo, série da cor verde que será exibida abaixo do zero, ex. Resultado não Op.;
  6. Saldo, série da cor azul, ex. Lajir.

No componente que criaremos apenas será necessário passar um DataProvider com as colunas: eixo, valor e isSaldo. Com base nos dados deste DataProvider, o Gráfico Cascata criará todas as seis séries necessárias, já com os valores calculados.

Veja como o componente é implementado abaixo.

package br.com.igormusardo.component.chart<br />{<br />	import mx.charts.*;<br />	import mx.charts.chartClasses.IAxis;<br />	import mx.charts.series.ColumnSeries;<br />	import mx.charts.series.ColumnSet;<br />	import mx.charts.series.items.*;<br />	import mx.collections.ArrayCollection;<br />	import mx.effects.easing.*;<br />	import mx.formatters.NumberFormatter;<br />	import mx.graphics.GradientEntry;<br />	import mx.graphics.LinearGradient;<br />	import mx.graphics.SolidColor;<br />	import mx.graphics.Stroke;<br />	import mx.utils.ObjectUtil;<br /> <br />	public class WaterfallChart extends ColumnChart<br />	{<br />		[Bindable]<br />		private var _calculateRange:Boolean;<br /> <br />		[Bindable]<br />		private var _backgroundColor:uint;<br /> <br />		[Bindable]<br />		private var _best:Number;<br /> <br />		[Bindable]<br />		private var _precision:Number;<br /> <br />		[Bindable]<br />		private var _decimalSeparator:String;<br /> <br />		[Bindable]<br />		private var _thousandsSeparator:String;<br /> <br />		private var dataProviderOriginal:ArrayCollection = new ArrayCollection();<br />		private var format:NumberFormatter = new NumberFormatter;		<br />		private var	columnBase:ColumnSeries = new ColumnSeries();<br />		private var	columnSaldo:ColumnSeries = new ColumnSeries();<br />		private var	columnVermelhoPositivo:ColumnSeries = new ColumnSeries();<br />		private var	columnVerdePositivo:ColumnSeries = new ColumnSeries();<br />		private var	columnVermelhoNegativo:ColumnSeries = new ColumnSeries();<br />		private var	columnVerdeNegativo:ColumnSeries = new ColumnSeries();<br /> <br />		public function WaterfallChart()<br />		{<br />			super();	<br />			calculateRange = true;<br />			backgroundColor = 0xFFFFFF;<br />			best = 1;<br />			precision = 0;<br />			decimalSeparator = \\\',\\\';<br />			thousandsSeparator = \\\'.\\\';			<br />			createChart();<br />		}<br /> <br />		override protected function initializationComplete():void<br />		{<br />			changeStyles();<br />			super.initializationComplete()<br />		}<br /> <br /> <br />		//Propriedades <br />		////////////////////////////////////////////////////////////////////////////////////////<br />		//calculateRange, quando Verdadeiro o componente calcula a diferença entre as séries, exibindo somente os valores que somaram ou reduziram de uma série para a outra.<br />		public function set calculateRange(value:Boolean):void<br />		{<br />			_calculateRange = value;<br />			changeDataProvider();	<br />		}<br /> <br />		public function get calculateRange():Boolean<br />		{<br />			return _calculateRange;	<br />		}<br /> <br />		public function set backgroundColor(value:uint):void<br />		{<br />			_backgroundColor = value;	<br />			changeStyles();	<br />		}<br /> <br />		public function get backgroundColor():uint<br />		{<br />			return _backgroundColor;	<br />		}<br /> <br />		//best, define qual é o melhor (1 melhor para cima, verde quando aumenta e vermelho quando diminui, 2 melhor para baixo, verde quando diminiui e vermelho quando aumente)<br />		public function set best(value:Number):void<br />		{<br />			_best = value;	<br />			changeDataProvider();	<br />		}<br /> <br />		public function get best():Number<br />		{<br />			return _best;	<br />		}<br /> <br />		//precision, define o número de casas decimais.<br />		public function set precision(value:Number):void<br />		{<br />			_precision = value;<br />			format.precision=_precision;<br />		    invalidateProperties();<br />		    invalidateDisplayList();   		<br />		}<br /> <br />		public function get precision():Number<br />		{<br />			return _precision;	<br />		}	<br /> <br />		//decimalSeparator, define qual o separador de decimal, padrão ,<br />		public function set decimalSeparator(value:String):void<br />		{<br />			_decimalSeparator = value;	<br />    		format.decimalSeparatorTo=_decimalSeparator;<br />		    invalidateProperties();<br />		    invalidateDisplayList();   		<br />		}<br /> <br />		public function get decimalSeparator():String<br />		{<br />			return _decimalSeparator;	<br />		}	<br /> <br />		//thousandsSeparator, define qual o separador de milhar, padrão .<br />		public function set thousandsSeparator(value:String):void<br />		{<br />			_thousandsSeparator = value;	<br />    		format.thousandsSeparatorTo=_thousandsSeparator;<br />		    invalidateProperties();<br />		    invalidateDisplayList();   		<br />		}<br /> <br />		public function get thousandsSeparator():String<br />		{<br />			return _thousandsSeparator;	<br />		}	<br /> <br />		private function createChart():void		<br />		{<br />			seriesFilters=[];<br />			dataTipMode="single";<br />			dataTipFunction=chartTipFunction;			<br />			maxLabelWidth=100;<br /> <br />			var columnSet:ColumnSet = new ColumnSet();<br />			var hAxis:CategoryAxis = new CategoryAxis()<br />			var vAxis:LinearAxis = new LinearAxis()<br />			var columnSerie:ColumnSeries = new ColumnSeries();<br />			var stroke:Stroke;<br />			var linearGradient:LinearGradient;<br />			var solidColor:SolidColor;<br />			var gradientEntry:GradientEntry;<br />			var gradArray:Array;<br /> <br />			vAxis.labelFunction = alteraLabelVertical;	<br />			verticalAxis = vAxis;<br /> <br />			hAxis.dataProvider = this.dataProvider;<br />			hAxis.categoryField = "eixo";<br />			hAxis.labelFunction = alteraLabelHorizontal;		<br />			horizontalAxis = hAxis;<br /> <br />			//Define o columnSet do gráfico<br />			columnSet.type = "stacked";<br />			columnSet.allowNegativeForStacked = true;<br /> <br />			/////////////////////////////////////////////////////////////////////////////////<br />			//Início da configuração da série vlrSaldo<br />			//Define a configuração da linha<br />			stroke = new Stroke();<br />			stroke.alpha = 0;<br />			stroke.weight = 0;<br /> <br />			//Início configuração Degradê de cores para a série vlrSaldo			<br />			linearGradient = new LinearGradient();<br />			linearGradient.angle = 0;<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x003ea5;<br />			gradientEntry.ratio = 0;<br />			gradientEntry.alpha = 1;<br /> <br />			gradArray = new Array();		<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x0060ff;<br />			gradientEntry.ratio = .5;<br />			gradientEntry.alpha = 1;<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x003ea5;<br />			gradientEntry.ratio = 1;<br />			gradientEntry.alpha = 1;						<br />			gradArray.push(gradientEntry);<br /> <br />			linearGradient.entries = gradArray;<br />			//Fim configuração Degradê de cores para a série vlrSaldo<br /> <br />			columnSaldo.yField = "vlrSaldo";<br />			columnSaldo.labelField = "vlrSaldo";<br />			columnSaldo.setStyle("stroke",stroke);<br />			columnSaldo.setStyle("fill",linearGradient);<br />			//Fim configuração da série vlrSaldo<br /> <br />			//Inclui a série vlrSaldo às séries do ColumnSet<br />			columnSet.series.push(columnSaldo);<br />			/////////////////////////////////////////////////////////////////////////////////<br /> <br />			/////////////////////////////////////////////////////////////////////////////////<br />			//Início da configuração da série vlrBase<br /> <br />			columnBase.yField = "vlrBase";<br />			columnBase.setStyle("stroke",stroke);<br />			//Fim configuração da série vlrSaldo<br /> <br />			//Inclui a série vlrBase às séries do ColumnSet<br />			columnSet.series.push(columnBase);<br />			/////////////////////////////////////////////////////////////////////////////////<br /> <br />			/////////////////////////////////////////////////////////////////////////////////<br />			//Início da configuração da série vlrVermelhoPositivo<br />			//Define a configuração da linha<br />			stroke = new Stroke();<br />			stroke.alpha = 0;<br />			stroke.weight = 0;<br /> <br />			//Início configuração Degradê de cores para a série vlrVermelhoPositivo			<br />			linearGradient = new LinearGradient();<br />			linearGradient.angle = 0;<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0xa50000;<br />			gradientEntry.ratio = 0;<br />			gradientEntry.alpha = 1;<br /> <br />			gradArray = new Array();		<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0xff0000;<br />			gradientEntry.ratio = .5;<br />			gradientEntry.alpha = 1;<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0xa50000;<br />			gradientEntry.ratio = 1;<br />			gradientEntry.alpha = 1;						<br />			gradArray.push(gradientEntry);<br /> <br />			linearGradient.entries = gradArray;<br />			//Fim configuração Degradê de cores para a série vlrVermelhoPositivo<br /> <br />			columnVermelhoPositivo.yField = "vlrVermelhoPositivo";<br />			columnVermelhoPositivo.labelField = "vlrVermelhoPositivo";<br />			columnVermelhoPositivo.setStyle("stroke",stroke);<br />			columnVermelhoPositivo.setStyle("fill",linearGradient);<br />			//Fim configuração da série vlrSaldo<br /> <br />			//Inclui a série vlrVermelhoPositivo às séries do ColumnSet<br />			columnSet.series.push(columnVermelhoPositivo);<br />			/////////////////////////////////////////////////////////////////////////////////<br /> <br />			/////////////////////////////////////////////////////////////////////////////////<br />			//Início da configuração da série vlrVerdePositivo<br />			//Define a configuração da linha<br />			stroke = new Stroke();<br />			stroke.alpha = 0;<br />			stroke.weight = 0;<br /> <br />			//Início configuração Degradê de cores para a série vlrVerdePositivo			<br />			linearGradient = new LinearGradient();<br />			linearGradient.angle = 0;<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x00a500;<br />			gradientEntry.ratio = 0;<br />			gradientEntry.alpha = 1;<br /> <br />			gradArray = new Array();		<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x60ff00;<br />			gradientEntry.ratio = .5;<br />			gradientEntry.alpha = 1;<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x00a500;<br />			gradientEntry.ratio = 1;<br />			gradientEntry.alpha = 1;						<br />			gradArray.push(gradientEntry);<br /> <br />			linearGradient.entries = gradArray;<br />			//Fim configuração Degradê de cores para a série vlrVerdePositivo<br /> <br />			columnVerdePositivo.yField = "vlrVerdePositivo";<br />			columnVerdePositivo.labelField = "vlrVerdePositivo";<br />			columnVerdePositivo.setStyle("stroke",stroke);<br />			columnVerdePositivo.setStyle("fill",linearGradient);<br />			//Fim configuração da série vlrVerdePositivo<br /> <br />			//Inclui a série vlrVerdePositivo às séries do ColumnSet<br />			columnSet.series.push(columnVerdePositivo);<br />			/////////////////////////////////////////////////////////////////////////////////<br /> <br />			/////////////////////////////////////////////////////////////////////////////////<br />			//Início da configuração da série vlrVermelhoNegativo<br />			//Define a configuração da linha<br />			stroke = new Stroke();<br />			stroke.alpha = 0;<br />			stroke.weight = 0;<br /> <br />			//Início configuração Degradê de cores para a série vlrVermelhoNegativo			<br />			linearGradient = new LinearGradient();<br />			linearGradient.angle = 0;<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0xa50000;<br />			gradientEntry.ratio = 0;<br />			gradientEntry.alpha = 1;<br /> <br />			gradArray = new Array();		<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0xff0000;<br />			gradientEntry.ratio = .5;<br />			gradientEntry.alpha = 1;<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0xa50000;<br />			gradientEntry.ratio = 1;<br />			gradientEntry.alpha = 1;						<br />			gradArray.push(gradientEntry);<br /> <br />			linearGradient.entries = gradArray;<br />			//Fim configuração Degradê de cores para a série vlrVermelhoNegativo<br /> <br />			columnVermelhoNegativo.yField = "vlrVermelhoNegativo";<br />			columnVermelhoNegativo.labelField = "vlrVermelhoNegativo";<br />			columnVermelhoNegativo.setStyle("stroke",stroke);<br />			columnVermelhoNegativo.setStyle("fill",linearGradient);<br />			//Fim configuração da série vlrVermelhoNegativo<br /> <br />			//Inclui a série vlrVermelhoNegativo às séries do ColumnSet<br />			columnSet.series.push(columnVermelhoNegativo);<br />			/////////////////////////////////////////////////////////////////////////////////<br /> <br />			/////////////////////////////////////////////////////////////////////////////////<br />			//Início da configuração da série vlrVerdeNegativo<br />			//Define a configuração da linha<br />			stroke = new Stroke();<br />			stroke.alpha = 0;<br />			stroke.weight = 0;<br /> <br />			//Início configuração Degradê de cores para a série vlrVerdeNegativo			<br />			linearGradient = new LinearGradient();<br />			linearGradient.angle = 0;<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x00a500;<br />			gradientEntry.ratio = 0;<br />			gradientEntry.alpha = 1;<br /> <br />			gradArray = new Array();		<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x60ff00;<br />			gradientEntry.ratio = .5;<br />			gradientEntry.alpha = 1;<br />			gradArray.push(gradientEntry);<br /> <br />			gradientEntry = new GradientEntry()<br />			gradientEntry.color = 0x00a500;<br />			gradientEntry.ratio = 1;<br />			gradientEntry.alpha = 1;						<br />			gradArray.push(gradientEntry);<br /> <br />			linearGradient.entries = gradArray;<br />			//Fim configuração Degradê de cores para a série vlrVerdeNegativo<br /> <br />			columnVerdeNegativo.yField = "vlrVerdeNegativo";<br />			columnVerdeNegativo.labelField = "vlrVerdeNegativo";<br />			columnVerdeNegativo.setStyle("stroke",stroke);<br />			columnVerdeNegativo.setStyle("fill",linearGradient);<br />			//Fim configuração da série vlrVerdeNegativo<br /> <br />			//Inclui a série vlrVerdeNegativo às séries do ColumnSet<br />			columnSet.series.push(columnVerdeNegativo);<br /> <br />			/////////////////////////////////////////////////////////////////////////////////<br />			setStyle("columnWidthRatio",0.9);<br /> <br />			series = [columnSet];<br />		}<br /> <br />		//Métodos formatação do gráfico<br />		////////////////////////////////////////////////////////////////////////////////////////<br />		//chartTipFunction, exibe o popup com os valores ao posicionar o mouse sobre a série.<br />		private function chartTipFunction(hitData:HitData):String<br />		{		<br />			return format.format(hitData.item.vlrValor);<br />		}<br /> <br />		private function alteraLabelHorizontal(item:Object, prevValue:Object, axis:CategoryAxis, categoryItem:Object):String<br />		{<br />			var retorno:String="";<br />			var tamanho:int=String(item).length;<br /> <br />			retorno=String(item)<br /> <br />			return retorno;<br />		}<br /> <br />		private function alteraLabelVertical(item:Object, prevValue:Object, axis:IAxis):String<br />		{				<br />			return format.format(item);<br />		}<br /> <br />		private function changeStyles():void<br />		{<br />			//Início configuração da cor de fundo do gráfico<br />			var bgi:GridLines = new GridLines();<br />			bgi.setStyle("horizontalStroke", new Stroke(_backgroundColor, 1));<br />			bgi.setStyle("horizontalFill", new SolidColor(_backgroundColor, 100));<br />			bgi.setStyle("horizontalAlternateFill", new SolidColor(_backgroundColor, 100));<br />			backgroundElements = [bgi]<br />			//Fim configuração da cor de fundo do gráfico	<br /> <br />			//Início configuração da cor da série Base<br />			var solidColor:SolidColor = new SolidColor();<br />			solidColor.alpha = 1;<br />			solidColor.color = _backgroundColor;<br />			columnBase.setStyle("fill",solidColor);<br />			//Fim configuração da cor da série Base<br /> <br />		    invalidateProperties();<br />		    invalidateDisplayList();<br />		}<br /> <br /> <br />		//Série base (invisível) do gráfico<br />		private function calculaSerieBase(vlrSaldoAnterior:Number,vlrValorCorrente:Number):Number<br />		{<br />			var retorno:Number;<br />			var vlrSaldoAtual:Number=vlrSaldoAnterior+vlrValorCorrente;<br /> <br />			if ((vlrSaldoAnterior>0 && vlrSaldoAtual<0)||(vlrSaldoAnterior<0 && vlrSaldoAtual>0))<br />			{<br />				retorno=0;<br />			}<br />			else<br />			{<br />				if (vlrSaldoAnterior>0 && vlrSaldoAtual>0)<br />				{<br />					retorno=vlrSaldoAnterior-calculaSerieDebitoPositivo(vlrSaldoAnterior,vlrValorCorrente);<br />				}<br />				else<br />				{<br />					if (vlrSaldoAnterior<0 && vlrSaldoAtual<0)<br />					{<br />						retorno=vlrSaldoAnterior+calculaSerieCreditoNegativo(vlrSaldoAnterior,vlrValorCorrente);<br />					}<br />					else<br />					{<br />						retorno=0;<br />					}		<br />				}<br />			}<br /> <br />			return retorno;<br />		}<br /> <br />		//Série verde valor positivo<br />		private function calculaSerieCreditoPositivo(vlrSaldoAnterior:Number, vlrValorCorrente:Number):Number<br />		{<br />			var retorno:Number;<br /> <br />			if (vlrValorCorrente<=0)<br />			{<br />				retorno=0;<br />			}<br />			else <br />			{<br />				if (vlrSaldoAnterior<0)<br />				{<br />					if (vlrValorCorrente>-vlrSaldoAnterior)<br />					{<br />						retorno=vlrValorCorrente+vlrSaldoAnterior;<br />					}<br />					else<br />					{<br />						retorno=0;<br />					}<br />				}<br />				else<br />				{<br />					retorno=vlrValorCorrente;<br />				}<br />			}<br />			return retorno;<br />		}	<br /> <br /> <br />		//Série verde valor negativo<br />		private function calculaSerieCreditoNegativo(vlrSaldoAnterior:Number, vlrValorCorrente:Number):Number<br />		{<br />			var retorno:Number;<br /> <br />			if (vlrValorCorrente<=0)<br />			{<br />				retorno=0;<br />			}<br />			else <br />			{<br />				if (vlrSaldoAnterior>=0)<br />				{<br />					retorno=0;<br />				}<br />				else<br />				{<br />					if (vlrValorCorrente>-vlrSaldoAnterior)<br />					{<br />						retorno=vlrSaldoAnterior;<br />					}<br />					else<br />					{<br />						retorno=-vlrValorCorrente;<br />					}<br />				}<br />			}<br />			return retorno;<br />		}	<br /> <br />		//Série vermelho valor positivo<br />		private function calculaSerieDebitoPositivo(vlrSaldoAnterior:Number, vlrValorCorrente:Number):Number<br />		{<br />			var retorno:Number;<br /> <br />			if (vlrValorCorrente>=0)<br />			{<br />				retorno=0;<br />			}<br />			else <br />			{<br />				if (vlrSaldoAnterior<=0)<br />				{<br />					retorno=0;<br />				}<br />				else<br />				{<br />					if(vlrSaldoAnterior<=Math.abs(vlrValorCorrente))<br />					{<br />						retorno=vlrSaldoAnterior;<br />					}<br />					else<br />					{<br />						retorno=-vlrValorCorrente;<br />					}<br />				}<br />			}<br />			return retorno;<br />		}<br /> <br /> <br />		//Série vermelho valor negativo<br />		private function calculaSerieDebitoNegativo(vlrSaldoAnterior:Number, vlrValorCorrente:Number):Number<br />		{<br />			var retorno:Number;<br /> <br />			if (vlrValorCorrente>=0)<br />			{<br />				retorno=0;<br />			}<br />			else <br />			{<br />				if (vlrSaldoAnterior>0)<br />				{<br />					if(Math.abs(vlrValorCorrente)<=vlrSaldoAnterior)<br />					{<br />						retorno=0;<br />					}<br />					else<br />					{<br />						retorno=vlrSaldoAnterior+vlrValorCorrente;<br />					}<br />				}<br />				else<br />				{<br />					retorno=vlrValorCorrente;<br />				}<br />			}<br /> <br />			return retorno;<br />		}				<br /> <br />		//Métodos Geração das séries<br />		////////////////////////////////////////////////////////////////////////////////////////<br />		override public function set dataProvider(value:Object):void<br />    	{<br />			if(value is ArrayCollection)<br />				dataProviderOriginal = value as ArrayCollection;<br />			else<br />				dataProviderOriginal = new ArrayCollection(value as Array);<br />			changeDataProvider();<br />     	}<br /> <br />     	private function changeDataProvider():void<br />     	{    		<br />     		if(dataProviderOriginal.length == 0)<br />     			return;<br /> <br />     		var value:Object = ObjectUtil.copy(dataProviderOriginal);<br />    		var dataProviderOriginalDP:Array = new Array;<br />    		var vlrValorCorrente:Number;<br />    		var vlrSaldoAnterior:Number;<br /> <br />    		//Verifica se o array é válido<br />    		if(value[0].eixo==null || value[0].valor==null || value[0].isSaldo==null)<br />    		{<br />    			throw new Error(\\\'Array inválido, deve possuir os campos: eixo:String, valor:Number e isSaldo:Boolean\\\');<br />    			return;<br />    		}<br /> <br />    		format.useNegativeSign=\\\'-\\\';<br />    		format.useThousandsSeparator=true;<br />    		format.rounding="nearest";	<br /> <br />			if(calculateRange && value != null)<br />			{<br />				for(var index:int = value.length-1; index >= 0; index--)<br />				{<br />					if(value[index].isSaldo != true)			<br />						if(index > 0)<br />							value[index].valor = value[index].valor - value[index-1].valor;<br />					if(index==value.length-1 && value[index].isSaldo == true)<br />					{<br />						value.addItem(ObjectUtil.copy(value[index]));<br />						value[index].isSaldo = false;<br />					}					<br />				}<br />			}<br /> <br />    		//Percorre o array de dataProviderOriginal, montando as séries do gráfico<br />			for each (var Obj:Object in value)<br />			{<br />				if (Obj.isSaldo==true)<br />					vlrSaldoAnterior=0;<br /> <br />				vlrValorCorrente=Obj.valor;<br /> <br />				dataProviderOriginalDP.push({<br />							eixo:Obj.eixo,<br />							vlrSaldo:(Obj.isSaldo==true?vlrValorCorrente:0), //Se for saldo PLOTA esta série<br />							vlrBase:(Obj.isSaldo==true?0: //Se for saldo NÃO plota esta série<br />														calculaSerieBase(vlrSaldoAnterior,vlrValorCorrente)),<br />							vlrVermelhoPositivo:(Obj.isSaldo==true?0 //Se for saldo NÃO plota esta série<br />																	:(_best==2? //Se for melhor pra baixo inverte a cor do melhor pra cima<br />																				calculaSerieCreditoPositivo(vlrSaldoAnterior,vlrValorCorrente)<br />																				:calculaSerieDebitoPositivo(vlrSaldoAnterior,vlrValorCorrente))),<br />							vlrVerdePositivo:(Obj.isSaldo==true?0 //Se for saldo NÃO plota esta série<br />																	:(_best==2? //Se for melhor pra baixo inverte a cor do melhor pra cima<br />																				calculaSerieDebitoPositivo(vlrSaldoAnterior,vlrValorCorrente)<br />																				:calculaSerieCreditoPositivo(vlrSaldoAnterior,vlrValorCorrente))),<br />							vlrVermelhoNegativo:(Obj.isSaldo==true?0 //Se for saldo NÃO plota esta série<br />																	:(_best==2? //Se for melhor pra baixo inverte a cor do melhor pra cima<br />																				calculaSerieCreditoNegativo(vlrSaldoAnterior,vlrValorCorrente)<br />																				:calculaSerieDebitoNegativo(vlrSaldoAnterior,vlrValorCorrente))),<br />							vlrVerdeNegativo:(Obj.isSaldo==true?0 //Se for saldo NÃO plota esta série<br />																:(_best==2? //Se for melhor pra baixo inverte a cor do melhor pra cima<br />																			calculaSerieDebitoNegativo(vlrSaldoAnterior,vlrValorCorrente)<br />																			:calculaSerieCreditoNegativo(vlrSaldoAnterior,vlrValorCorrente))),<br />							vlrValor:vlrValorCorrente<br />						});<br /> <br />				vlrSaldoAnterior+=vlrValorCorrente;<br />			}<br /> <br />    		super.dataProvider = dataProviderOriginalDP;<br />		    invalidateProperties();<br />		    invalidateDisplayList();<br />     	}<br /> <br />	}<br />}

Para utilizar o novo componente, utilize o código:

<?xml version="1.0" encoding="utf-8"?><br /><mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:ns1="br.com.igormusardo.component.chart.*" backgroundGradientAlphas="[1.0, 1.0]" backgroundGradientColors="[#FFFFFF, #FFFFFF]"><br />	<ns1:WaterfallChart id="wfc" top="10" left="10" right="10" bottom="10" showDataTips="true" calculateRange="false" best="1"><br />		<ns1:dataProvider><br />			<mx:Array><br />				<mx:Object eixo="ROB" valor="12850" isSaldo="true"/><br />				<mx:Object eixo="(-) Deduções" valor="-1500" isSaldo="false"/><br />				<mx:Object eixo="ROL" valor="11350" isSaldo="true"/><br />				<mx:Object eixo="(-) Custos" valor="-8200" isSaldo="false"/><br />				<mx:Object eixo="Lucro Bruto" valor="3150" isSaldo="true"/><br />				<mx:Object eixo="(-) Desp. Op." valor="-3150" isSaldo="false"/><br />				<mx:Object eixo="(-) Desp. Fi." valor="-1200" isSaldo="false"/><br />				<mx:Object eixo="Res. Não Op. " valor="3500" isSaldo="false"/><br />				<mx:Object eixo="Lajir" valor="2300" isSaldo="true"/><br />			</mx:Array><br />		</ns1:dataProvider><br />	</ns1:WaterfallChart><br /></mx:Application>

O resultado obtido é o demonstrado abaixo.

Se quiser fazer teste com o comportamento do gráfico teste-o logo abaixo.

Se preferir, faça o download do gráfico cascata já compilado em SWC. Download Gráfico Cascata.

Divirta-se.

*

artigo originalmente publicado em http://www.igormusardo.com.br/

é Consultor de Inteligência para e-Commerce e já deixou sua marca em grandes empresas como Sadia SA (BRF Foods), CINQ Technologies e Buscapé Company.

Ver perfil