views:

1217

answers:

1

I want to build a LineChart component where the color of the line is indicative on how high the value is. I should be able to do this buy just using a gradient stroke (see below) but for some reason the gradient only goes from left to right and the "angle" property is being ignored. How could i do this?

    <mx:PlotChart id="bpChart" width="514" height="144" dataProvider="{measurementsXLC}"   >
 <mx:series>
  <mx:LineSeries id="bpSeries" displayName="Series 1" yField="value" xField="date" showDataEffect="fade" stroke="{lstroke}">
   <mx:lineStroke>
    <mx:LinearGradientStroke angle="270.0" weight="3"  scaleMode="vertical"  >
        <mx:entries>
         <mx:GradientEntry color="#ff0000" ratio="0.0"/>
         <mx:GradientEntry color="#00ff00" ratio="1.0"/>          
        </mx:entries>
       </mx:LinearGradientStroke>
   </mx:lineStroke>
   <mx:itemRenderer>
    <mx:Component>
     <mx:CircleItemRenderer >

     </mx:CircleItemRenderer>
    </mx:Component>     
   </mx:itemRenderer>
  </mx:LineSeries>
  <mx:LineSeries id="bpSeries2" displayName="Series 1" yField="value2" xField="date" showDataEffect="fade"  />
 </mx:series>
 <mx:horizontalAxis>
  <mx:DateTimeAxis id="dateAxis" dataUnits="milliseconds" labelUnits="days" />
 </mx:horizontalAxis>
 <mx:verticalAxis>
  <mx:LinearAxis baseAtZero="false" autoAdjust="true" interval="5" />

 </mx:verticalAxis>
</mx:PlotChart>
+1  A: 

I would expect that you would need to create a custom lineSegmentRenderer for the line series chart. The current lineSegmentRenderer is a ShadowLineRenderer. Without actually solving the entire problem myself, i would create a new class based on ShadowLineRenderer and change the updateDisplayList method to draw the line exactly as you needed it. Then change the lineSegmentRenderer property of your line series to use this renderer.

If it helps I had to do a very similar thing but with the AreaRenderer. The area gradient was required to be based on the total chart and not to color the full gradient for any area that was displayed (eg with the regular AreaRenderer, if the area just covers the first 20% of the y axis it still used the full gradient which was an undesirable feature for my project). Here's the solution to my problem where i created my own AreaRenderer and updated the updateDisplayList method:

override protected function updateDisplayList(unscaledWidth:Number,
              unscaledHeight:Number):void
 {
  super.updateDisplayList(unscaledWidth, unscaledHeight);

  var fill:IFill = GraphicsUtilities.fillFromStyle(getStyle("areaFill"));
  var stroke:IStroke = getStyle("areaStroke");
  var form:String = getStyle("form");

  var g:Graphics = graphics;
  g.clear();

  if (!_area)
   return;

  var boundary:Array /* of Object */ = _area.filteredCache;
  var n:int = boundary.length;
  if (n <= 1)
   return;

  var xMin:Number;
  var xMax:Number = xMin = boundary[0].x;
  var yMin:Number;
  var yMax:Number = yMin = boundary[0].y;

  var i:int;
  var v:Object;

  for (i = 0; i < n; i++)
  {
   v = boundary[i];

   xMin = Math.min(xMin, v.x);
   yMin = Math.min(yMin, v.y);
   xMax = Math.max(xMax, v.x);
   yMax = Math.max(yMax, v.y);

   if (!isNaN(v.min))
   {
    yMin = Math.min(yMin, v.min);
    yMax = Math.max(yMax, v.min);
   }
  }

  if (fill)
   fill.begin(g, new Rectangle(0, 0, unscaledWidth, unscaledHeight));

  GraphicsUtilities.drawPolyLine(g, boundary, 0, n,
          "x", "y", stroke, form);

  g.lineStyle(0,0,0); 

  if(boundary[0].element.minField != null && boundary[0].element.minField != "")
  {
   g.lineTo(boundary[n - 1].x, boundary[n - 1].min);  

   GraphicsUtilities.drawPolyLine(g, boundary, n - 1, -1,
           "x", "min", noStroke, form, false);
  }
  else
  {
   g.lineTo(boundary[n - 1].x, _area.renderedBase);  
   g.lineTo(boundary[0].x, _area.renderedBase);
  }

  g.lineStyle(0, 0, 0);
  g.lineTo(boundary[0].x, boundary[0].y);

  g.endFill();
 }
James Hay