Home > charts > Scrolling and zooming chart with ChartScroller

Scrolling and zooming chart with ChartScroller

Some time ago I presented scrolling chart by using modified axis renderer (ScrollableAxisRenderer). I rethought this concept and come to the point that axis renderer should render axis not scroll the chart, so chart scrolling should be implemented as separate component. This is especially true in case of charts with many axes and renderers. My new idea was to create nonvisual component which will take reference to a chart and add appropriate listeners modifying axes minimum/maximum to achieve scrolling /zooming.

It was the challenge to find the way to easily convert mouse position to data coordinates and vice versa. According to documentation DataTransform objects should be used for this purpose, but unfortunately this documentation is quite incomplete. I especially like this sentence “In theory, a chart can contain multiple overlaid DataTransform objects.” – what does it mean “in theory” ? Having two vertical or horizontal axes is quite common case and in such case different data transformation have to be done for each axis. If charting sources were open it would at least be possible to figure out how data transformation is working reading code…

Anyway, finally I have found that chart series (Series) inherits two function (localToData() and dataToLocal()) to transform points to and from data coordinates. Using these functions I have implemented component named ChartScroller.

All you have to do to enable chart scrolling/zooming using ChartScroller is create instance of ChartScroller and pass reference to the chart to it. You can do it in MXML using the code similar to the one below:

<charts:ChartScroller id="scroller" chart="{chart}" />

<mx:ColumnChart id="chart" width="100%" height="100%"
    gutterLeft="40" gutterRight="10" dataProvider="{dp}">
    <mx:series>
        <mx:ColumnSeries id="series1" xField="x" yField="y2" />
        <mx:ColumnSeries id="series2" xField="x" yField="y1" />
    </mx:series>
</mx:ColumnChart>

ChartScroller is hosted on http://code.google.com/p/reusable-fx/. Currently charts with LinearAxis or DateTimeAxis are supported.

Basic Example

View source is enabled, you can download zipped sources from here.

Example – using ChartScroller with many axes

You can use ChartScroller for chart with multiple axes, so that different axes can be scrolled separately. To scroll/zoom concrete axis grab series using this axis or axis renderer.

View source is enabled, you can download zipped sources from here.

Example – ChartScroller properties

This example demonstrates how you can adjust behavior of ChartScroller by setting some of it public properties.

ChartScroller dispatches change event every time axis minimum/maximum value is modified. It also dispatches valueCommit event after specified time from last modification. This event may be used to retrieve new data or update other controls based on new axes minimum/maximum values. I will present example retrieving data from remote service on valueCommit event in separate post.

Categories: charts Tags: , , ,
  1. July 16th, 2009 at 16:00 | #1

    Great work, Excellent stuff!!

  2. JAIME
    July 22nd, 2009 at 16:23 | #2

    Perfect solution but… how about CategoryAxis? I’m trying to solve this problem but i don’t now a valid solution.

    Any idea?

  3. Iwo Banas
    July 23rd, 2009 at 22:55 | #3

    @JAIME
    Unfortunately ChartScroller can’t be used with CategoryAxis since it doesn’t have minimum/maximum properties.

    The good news is that you can simulate CategoryAxis behaviour by using LinearAxis with parseFunction and labelFunction. I will post an example demonstrating how to do that tomorrow.

  4. Iwo Banas
    July 25th, 2009 at 00:39 | #4

    I didn’t have time to post a full example but I can give you some hints how to simulate CategoryAxis with LinearAxis (assume “dp” is data provider and “cat” is category field):

    • Declare series without xField property (that way index of item will be used as x value).
    • Create category label function which will convert item index to category label.
      public function categoryLabelFunction(labelValue:Object,
          previousValue:Object, axis:IAxis):String
      {
          if (labelValue >= 0 && labelValue < dp.length)
              return dp[int(labelValue)].cat;
          return "";
      }
      
    • Declare LinearAxis using created category function. Setting “interval” property to 1 will prevent the same category label to be repeated many times.
      <mx:horizontalAxis>
          <mx:LinearAxis labelFunction="categoryLabelFunction" interval="1" />
      </mx:horizontalAxis>
      

    Hope this will be of some help to you.

    I’ll be on holiday next week so I will not be able to answer any further questions till August.

  5. July 28th, 2009 at 10:50 | #5

    hi Iwo,
    that’s really a great stuff! thanx very much.. I have a question about scroll and zoom, is it possible to control these from buttons in addition to mouse events?

  6. Iwo Banas
    August 4th, 2009 at 18:33 | #6

    Hi Turker,

    Currently ChartScroller supports zooming/scrolling based on mouse events only.

    Zooming and scrolling is done simply by modifying axis minimum/maximum properties so you can modify it from button click event handler as well.

    Alternatively you can extend ChartScroller and use protected zoomChart() and scrollChart() functions. Note that before calling these functions you have to initialize ChartScroller by calling one of initializeFor*() functions.

    Cheers,
    Iwo

  7. Franziska
    August 7th, 2009 at 17:34 | #7

    Hey,

    thanks for this!! I need this with a LineChart (with dynamic Dataprovider) and the Category Axis.. your example at the top works well with CategoryAxis, but the LineSeries are loosing the reference to the axis.. means, that “lineSeries.xField” doesnt work. Since I have multiple lineSeries I need the “xField”-Property.. is there a way to manipulate this also?

  8. Iwo Banas
    August 7th, 2009 at 22:33 | #8

    Hi Franziska,
    I have created separate post about using ChartScroller together with LinearAxis simulating CategoryAxis. Hope this will be of some help.

  9. bhav
    August 22nd, 2009 at 18:44 | #9

    Hi,

    I am getting following error when I am compiling the given example.
    1046: Type was not found or was not a compile-time constant: ChartScroller
    can you pls let me know the reason.
    Thanks,
    Bhav.

  10. Iwo Banas
    August 25th, 2009 at 18:22 | #10

    Hi,
    It seams that you haven’t included ChartScroller in your project (it is not a standard Flex component). Download the latest binary release from http://code.google.com/p/reusable-fx/downloads/list and copy ReusableFx.swc into /libs folder.

  11. David
    August 27th, 2009 at 02:02 | #11

    I’m just now learning Flex and am looking for a class that provides a general ability to slide anything with click and drag, not just charts. I looked at your source but it seems that sliding is built in to the chart class. I’m trying to implement an historical timeline that is very “long” and that can be scrolled left or right, that contains tick marks and photos. HOpe this makes sense and is not too far off-topic. Thanks!

  12. Gourab
    October 10th, 2009 at 05:16 | #12

    Great work, Iwo.
    Just one thing. Take this data set and we dont see anything in the view.
    Probably the scale minimizes out. Am I missing something ?

    Thanks again.

    Gourab

  13. Gourab
    October 10th, 2009 at 05:19 | #13

    Further to my post above – Somehow my data set I posted is filtered out or isnt being seen in my post. In your linearaxis just change the values of x to huge to say 98, 200, 400 , 500, 1890, 2500, 3400, 4000 etc.

  14. Gourab
    October 10th, 2009 at 05:37 | #14

    I think I figured it out . You set the min-max to a small range for the bars to be wide enough and then scroll about – stupid me!

  15. Bill R.
    November 21st, 2009 at 04:23 | #15

    ChartScroller is frankly the coolest chart modification I’ve run across. It has a great “gee-whiz” factor. Thank you for sharing as it is absolutely brilliant.

  16. alfredo
    February 4th, 2010 at 13:47 | #16

    Hello! great component! The only missing thing is:
    After scrolling and zooming in the chart, i want to go back to the first view where all data was fitting in my chart. Is there a function (autofitaxis)? How can i implement this?
    Many Thanks in advance!

  17. alfredo
    February 4th, 2010 at 13:56 | #17

    @alfredo
    Hello Iwo,
    you wrote the solution in another post,
    this code will fit the axis:

    axis.minimum=NaN;
    axis.maximum=NaN;

    thank you!

  18. Kalavati Singh
    February 4th, 2010 at 15:02 | #18

    Hi,
    Excellent work. Can I use the same in my project. If any thing related to Licensing please let me know

  19. Iwo Banas
    February 4th, 2010 at 15:44 | #19

    Sure you can use it!
    It’s released under MPL license (the same as Flex SDK) so if you improve it you should publish changes (of course only changes to my component not the code of your application).
    For example you can commit it to the google code project or simply send me a diff.

  20. Scott Stewart
    February 8th, 2010 at 20:03 | #20

    Hi, I love this component, however it does have one limitation for me–the scroll wheel. Macs still do not (to my knowledge) support the scroll wheel, and some laptops dont have them either.

    Id like to modify your component to handle a keyboard event for zooming(such as using the + and – for zooming). How would you recommend doing this?

  21. Ahe
    March 29th, 2010 at 14:56 | #21

    Hi,

    Excellent work, very helpful. i want to use your component but i dont know how, i have linechart instead of columnchart,and the data of my dataprovider is like this :
    public var tableauGraph:ArrayCollection = new ArrayCollection([
    {gare: "Reiner", heure: "10:00", numero: 69000,ordre: 10},
    {gare: "Rein", heure: "10:30", numero: 69000,ordre: 11},
    {gare: "trdf", heure: "10:45", numero: 69000,ordre: 12},
    {gare: "Rei", heure: "11:00", numero: 69000,ordre: 13},
    {gare: "Rein", heure: "10:00", numero: 69100,ordre: 3},
    {gare: "Reibv", heure: "10:45", numero: 69100,ordre: 4},
    {gare: "fgf", heure: "10:55", numero: 69100,ordre: 5},
    {gare: "trtrdg", heure: "11:00", numero: 69100,ordre: 6},
    {gare: "trdf", heure: "12:00", numero: 69100,ordre: 7}
    ]);

    now i want in Xaxes “gare” and in the Yaxes “heure”, i cant print the label of heure! can you help me?

    Thanks and sorry for my english.

  22. Kishore
    May 4th, 2010 at 10:07 | #22

    Will it work for the stacked charts… with different series..
    I am using column chart which has 6 column series and need to scroll chart.
    Will this work. I would like to use this example.
    Good scroll bar example really…!

  23. tianbaowen
    August 28th, 2010 at 06:53 | #23

    here,i found one.It’s great!http://www.connectedpixel.com/blog/scrollingcharts

  24. December 8th, 2010 at 21:12 | #24

    Terrific!

    Do you mind if I slightly changed your components and put your post on the Russian language to keep a reference to the source?

  25. January 6th, 2011 at 15:02 | #25

    Tks….
    And 4 Flex 4?

  26. Boris
    February 4th, 2011 at 11:28 | #26

    hi!
    Thank you for your work. I have a question:
    1 I use your code to work with CandlestickChart. This chart is updated on a timer. How to make sure that-be when you add a new value, old moved to the left (with the axis Y)? There is now a zoom-out the whole chart.

    Thank you.

  27. Debanjan
    March 20th, 2011 at 21:01 | #27

    Hi Iwo.. gr8 work..unfortunately..i am not yet able to get it work on a bar chart..any help will be appreciated..
    cheers.

  28. EW
    June 3rd, 2011 at 09:59 | #28

    Hi, Excellent work, very helpful. I have a question about performance with Large Data Sets, I have a chart with 10000+ data points, it is slow when Scrolling and zooming the chart, but the CPU and ram is not fully in use.
    Thx

  29. Nick
    October 5th, 2011 at 13:09 | #29

    Hi Iwo,

    Thank you for the helpful tutorial and nice code.
    I have two question though.
    1. When I use the scrolling (setting minimum and maximum), if I have something drawn on the chart (on it CartesianDataCanvas) and if the draw goes out of sight, next time I scroll back to its position, it is gone!
    I use addDataChild to add a graphic.
    2. Something similar happens if I add another LineSeries with less data. While scrolling, the line segments can disappear at once.
    Can you please advice on this?
    Thanks!

  30. prasad
    November 2nd, 2011 at 08:27 | #30

    hi ,
    i using column chart where it contain n number of bars i want to set horizontal scroll bar , i take example above but in that i find an error ( The prefix “charts” for element “charts:ScrollableAxisRenderer” is not bound.) the charts tag where it comes from?

    this is the line i got error.

    Please give me a solution thanks in advance..

  1. August 26th, 2009 at 18:45 | #1
  2. March 3rd, 2010 at 12:15 | #2