Home > charts > Scrolling and zooming chart with ChartScroller

Scrolling and zooming chart with ChartScroller

July 10th, 2009

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…!

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