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:

- Base, que será invisível;
- Vermelho Positivo, série da cor vermelha que será exibida acima do zero, ex. (-) Custos, no gráfico acima;
- Verde Positivo, série da cor verde que será exibida acima do zero, ex. Resultado não Op.;
- Vermelho Negativo, série da cor vermelha que será exibida abaixo do zero, ex. (-) Despesas;
- Verde Negativo, série da cor verde que será exibida abaixo do zero, ex. Resultado não Op.;
- 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/







