Telerik blogs

Remember when creating a chart on the web was virtually impossible? I do. I remember using the .NET framework to render the chart on the server and return a static image via a handler. The only way to have interactive charts in those days was to open Excel. As a developer, I have always claimed that if Excel is in your list of "Recently Used Programs", things are not going your way.

Fast forward a few years, and the story is completely different. Since then, Microsoft introduced Vector Markup Language (VML), which allowed us to draw charts on the web, and thusly make them interactive. That standard did not enjoy broad success. However it's 2nd cousin, Scalable Vector Graphics (SVG), has been incredibly successful and enjoys support on ALL major desktop browsers. Between SVG and VML, you can reach just about every device and every browser version. Fortunately, Kendo UI DataViz supports both formats and will oscillate between the two automatically depending on what your browser currently supports. If it can use SVG, it will. Otherwise it falls back to VML, which enjoys support all the way back to IE 5.

Check out the sample dashboard I put together for this demonstration. It's using the all new Flat theme, as well as Bootstrap 3.

Kendo UI DataViz has great animations and beautiful interactions. It's designed to be cross-browser and to deliver a premium experience on mobile devices.

However, as our needs were met by the emerging standards, the change in the variety of form factors affected how we wanted to use the web. Having a minimum resolution is not an option anymore. This presents new challenges.

Responsive Design Changes

This simple app is already kind of responsive thanks to Bootstrap right out of the box. Only not really.

If you test this page in any of the multiple "Responsive Design" testing utilities, you will see that the charts draw themselves to the size of the container, but after a resize, it all goes to pot. As you decrease the screen size or resize the page, you will notice that the white space between the charts and gauges will decrease, and eventually they will stack on top of each other. However, the charts themselves never change size. This causes them to be left aligned at approximately tablet size and at phone size, the top two charts extend off the page and cause horizontal scrolling.

A Look Under The Hood

To understand how Kendo UI is drawing these charts, we can take a look under the hood. If you inspect any of the charts on the page, you will see the div element that was used to create the chart, and then below that, either VML or SVG (depending on what your browser supports).

Notice that the chart has a static size for the width and height? Where do these numbers come from?

Initial Chart Width

Charts are by default 600 pixels wide by 400 pixels tall. These are the dimensions that you get if you don't statically define them in the chartArea configuration object. If the container that you are placing the chart in is less than the max default width, it will draw the chart as big as the container. So to summarize all that...

By default, Kendo UI DataViz will draw charts to fill their container up to a maximum width of 600 pixels.

In the case of the current Boostrap layout, I have a two different layouts going on.

  1. Up top we have two charts. The maximum width of a container in Bootstrap is 1200 pixels. Each of the columns is 600 pixels minus 30 pixels of padding. That means that each of the charts can be a maximum of 570 pixels. As the page decreases in size, the size of the columns reduces when the width gets below 1200 pixels as columns in Bootstrap are sized to a percentage of the available real estate. Bootstrap will stack the columns for us when they get down to 570 pixels, but this is a no go for mobile devices. What we want is for the charts to resize themselves down as far as Bootstrap will let us.

  2. Below the charts we have Radial Gauges. Each gets to occupy 25% of a maximum of 1200 pixels, but they are inside a well, so they only get 290 pixels at the top range. The gauge is unique in that it will expand width-wise to fill the container, but most of it will be white space. By default, the horizontal gauge appears to occupy 280 pixels at it's widest point. This can be overridden with the gaugeArea configuration value.

Resizing Charts

Now that we know how the widgets behave out of the box, and in conjunction with the responsive CSS framework (Bootstrap 3 in this case), it's time to tackle the issue of getting these charts to redraw themselves when the browser is resized.

A Note On The Fascination With Browser Resizing

Just as an observation, we love responsive design because we like to slowly collapse the page and watch what it does. While this is admittedly "cool", it has no real function other than to entertain us. In reality, your user is probably not going to resize your page and watch what it does unless your core user base is web developers.

All this to say that keep in mind as we implement these features, the user will like be accessing this on a form factor. The only real resizing they are going to be doing is when their device goes from portrait to landscape or vice-versa.

Here We Go

Since the charts are statically sized, we need to redraw them as their container changes shape. There is an API for this called - believe it or not - redraw. Both the standard chart widget and the gauges have this method.

To implement this we need to do the following things...

  1. Attach an event listener to the window resize event
  2. Get all of the charts/gauges on the page
  3. Call redraw on each chart/widget

Conveniently enough, jQuery exposes the window resize() event, so all we need to do is handle the callback.

Handle Window Resize Event

// listen for the window resize event
$(window).resize(function() {
  // get jiggy with it
});

I can select any chart or gauge on the page by looking for a k-chart or k-gauge CSS class. These classes get added to the chart element by Kendo UI when they are initialized. Once I have them, I can loop through them to call redraw.

Enumerate All Charts/Widgets On The Page

// listen for the window resize event
$(window).resize(function() {
  // for any chart or gauge widget
  $(".k-chart, .k-gauge").each(function() {
    // redraw here
  });
});

Inside the loop, jQuery gives me the element that chart or gauge was initialized from. I don't know if it's a chart of a gauge though. In order to get the widget instance so I can call the redraw method, I have to know if I'm dealing with a chart or a gauge. I could write an ugly if statement to look at the classes, but there is a better way.

PROTIP ALERT!

Late last week, Kamen Bundev on the team tweeted this:

Ah yes - this is just what I need here. I don't need to know the specific widget instance because I know they both have a redraw on them. I can get the widget instance by using the kendo.widgetInstance utility method and then I'll double check to make sure that the redraw method is there before I call it.

Getting The Widget Instance And Redrawing

// listen for the window resize event
$(window).resize(function() {
  // for any chart or gauge widget
  $(".k-chart, .k-gauge").each(function() {
    // get the instance of the chart/gauge
    var chart = kendo.widgetInstance($(this), kendo.dataviz.ui);
    // redraw the chart/gauge
    if (chart && chart.redraw) {
      chart.redraw();
    }
  });
});

At this point, the charts will now redraw themselves as we resize the page, thusly getting smaller along with the container, but without losing resolution or text size.

However, you may notice that the animations fire over and over again.

Try It

This goes back to my comment about resizing. It's not something that we really need to be concerned over, but just to be on the safe side, we can turn these transitions off during the resize. That way they fire the first time the user sees them, but not when they are redrawn.

Make Sure Transitions Are Off

// listen to the window resize event
$(window).resize(function() {
  // for any chart or gauge widget
  $(".k-chart, .k-gauge").each(function() {
    // get the instance of the chart/gauage
    var chart = kendo.widgetInstance($(this), kendo.dataviz.ui);
    // make sure transitions are off
    chart.options.transitions = false;
    // redraw the chart/gauge
    if (chart && chart.redraw) {
      chart.redraw();
    }
  });
});

That's a whole lot better and smoother.

What HTML5 Giveth, Mobile Taketh Away

SVG is great and enjoys really good support on mobile, except in the case of Android 2.3 and lower. Ouch. That hurts because frankly, a LOT of users are still on that operating system. In fact, the largest single distribution is still 2.3.

The good news is that even old Android supports canvas! The drawback is that charts drawn on canvas are not interactive. However, static charts on mobile perform much better than interactive ones and actually give a lighter and quicker experience to the user. That is to say, it is preferable to deliver your charts statically on mobile devices when you can.

What I want here is to give my desktop users a full, interactive experience with SVG and VML, and give my mobile users a light and fast experience by switching over to canvas. As of the Q2 release, you can now do this with Kendo UI DataViz.

This Is How You Canvas

For this, I am going to be using another Kendo UI utility method. It's the kendo.support object which Kendo UI uses internally for feature detection. There are two options here. I can look for Android by checking the operating system, but it's easier to just use the kendo.support.mobileOS boolean flag. All my mobile users will be getting static charts. I can add in a clause just before the charts are created to check the OS and then draw the charts in the appropriate format.

Use Canvas If Mobile

// set the default rendering mode to svg
kendo.dataviz.ui.Chart.fn.options.renderAs = "svg";
// if this is a mobile device
if (kendo.support.mobileOS) {
  // canvas for chart for you!
  kendo.dataviz.ui.Chart.fn.options.renderAs = "canvas";
}

Test this with your browser dev tools at http://jsbin.com/aqajoy/10. You can also just visit the link on your desktop and see the animations. Now visit it on your mobile device and notice that the images are static. Also notice that as you rotate from landscape to portrait and back again, the charts all resize themselves appropriately. It seems like a lot of code, but have actually written very little. Here is the complete code for making all of the charts responsive AND compatible with unsexy Android.

Responsive Charts

// set the default rendering mode to svg
kendo.dataviz.ui.Chart.fn.options.renderAs = "svg";
// if this is a mobile device
if (kendo.support.mobileOS) {
  // canvas for chart for you!
  kendo.dataviz.ui.Chart.fn.options.renderAs = "canvas";
}

// listen to the window resize event
$(window).resize(function() {
  // for any chart or gauge widget
  $(".k-chart, .k-gauge").each(function() {
    // get the instance of the chart/gauage
    var chart = kendo.widgetInstance($(this), kendo.dataviz.ui);
    // make sure transitions are off
    chart.options.transitions = false;
    // redraw the chart/gauge
    chart.redraw();
  });
});

Stay Responsive

This was a fun exercise for me because I knew that the charts were statically sized, but I wasn't sure how hard it was going to be to make them responsive. It was really quite easy. The hardest part for me was learning the new Bootstrap grid system! Darnit if they don't change things on you JUST as you think you've pretty much got it all down.

You can of course grab a download of Kendo UI DataViz yourself and see how easy it is to create responsive dashboards with your favorite responsive CSS framework.


Burke Holland is the Director of Developer Relations at Telerik
About the Author

Burke Holland

Burke Holland is a web developer living in Nashville, TN and was the Director of Developer Relations at Progress. He enjoys working with and meeting developers who are building mobile apps with jQuery / HTML5 and loves to hack on social API's. Burke worked for Progress as a Developer Advocate focusing on Kendo UI.

Comments

Comments are disabled in preview mode.