Jul 9, 2013
Mary Sammal

Gauging by Appearances

Whenever someone talks about data visualization, the natural interpretation is to think of charts and charting, displaying trends and relationships through a visual representation of a set of interrelated data.

However, although beneficial, that's not the only way to visualize data. Another method that's especially important when displaying a single value that changes frequently is to use some kind of gauge. Examples around in our daily lives: simple thermometers are linear gauges, for example, whereas the speedometer in your car is generally a circular gauge. In essence, we want to discover at a glance the value of a particular measurement at that time. We aren't particularly interested in the change of that value over time (for which we would probably use a line chart with the X-axis as the time axis), just in its value right now. Certainly we could display a big bold number (say, “55 MPH”), but sometimes we can get other information from glancing at a gauge, for example how close are we to the “red zone” on a tachometer.

In our DevExtreme Web and DevExtreme Complete packages we have also provided a set of gauge widgets.

DevExtreme Gauges

Here's an example of some of the beautiful gauges that you can provide your users with DevExtreme. These are not static images, by any means; they are live HTML5/JS client-side widgets that respond dynamically to changes in their values.

Let's explore.

Basic Shapes

DevExtreme data visualization library provides two types of gauges: a circular gauge (dxCircularGauge) and a linear gauge (dxLinearGauge). Sometimes one is more appropriate than the other: it's up to you to decide based upon your designs and desires.

To use them we must first add a named div element with a non-zero width and height to the HTML page.

HTML
<div id="circularGaugeContainer" style="height:220px;margin: 0px auto"></div>
<div id="linearGaugeContainer" style="height:100px;width:320px;margin: 0px auto"></div>

Now we can use JavaScript in order to display the different types of gauges. As usual in these scripted gadgets, we use the standard document loaded event from jQuery to create the gauges:

JavaScript
$(function () {
    $("#circularGaugeContainer").dxCircularGauge({});
    $("#linearGaugeContainer").dxLinearGauge({});
})

This is the result.

Since we haven't defined any data for the scales, both scales default from 0 to 100. The same goes for the value to display in the gauge: we haven't yet defined it, so the needles are set to zero.

(Oh, forgot to say that although we are using jQuery to define and display the gauges in this article, you can also use the Knockout-style MVVM to do the same.)

The next step is to tune up the gauges as your task requires.

Configuring the Gauge Appearance

Yesterday I surfed the web looking for a good old movie to stream and watch. And I thought that it would be nice to use a gauge to visually indicate a film's rating. We'll create a gauge that does this. Here's the definition for what I want the gauge to display:
  • The scale runs from 1 to 10 with a tick mark at every integer.
  • The gauge is a semi-circle (we call this the geometry of the gauge).
  • We want to indicate on the scale whether the film is bad (1-4), good(4-8), or excellent (8-10). We'll use color for this and make bad movies reddish, good ones orangey, and excellent ones green.
  • Finally we need a needle to show the current movie's rating.

DevExtreme Data Visualization library makes this definition easy: we just define a configuration object that's passed to the function that creates the gauge.

JavaScript
$(function () {
    $("#circularGaugeContainer").dxCircularGauge({
        scale: {
            startValue: 1,
            endValue: 10,
            majorTick: {
                tickInterval: 1
            }
        },
        geometry: {
            startAngle: -180,
            endAngle: 0
        },
        needles: [{ value: 7 }],
        rangeContainer: {
            ranges: [{
                    startValue: 1,
                    endValue: 4,
                    color: "#E19094" // reddish
                }, {
                    startValue: 4,
                    endValue: 8,
                    color: "#FCBB69" // orangey
                }, {
                    startValue: 8,
                    endValue: 10,
                    color: "#A6C567" // greenish
                }           
            ]
        }  
    });
});

And here is the resulting gauge:

Pretty straightforward, I'm sure you'll agree. Let's go even further and create a linear gauge to display the percentages of positive and negative ratings the movie was awarded. Here are the requirements:

  • The scale should range from 0 to 100. We'll not show any labels with this scale, instead using a marker to display the percentage of positive reviews.
  • A range bar that shows the percentage of positive reviews in green, and the percentage of negative reviews in red.
  • A marker that shows the percentage of positive reviews.
  • The scale should be hidden behind the range bar.

Again it's straightforward to define the configuration object that accomplishes this.

JavaScript
$(function () {
    var positiveVotes = 33,
        negativeVotes = 57,
        positivePercentage = function() {
            return positiveVotes * 100 / (negativeVotes + positiveVotes);
        };

    $("#linearGaugeContainer").dxLinearGauge({
        scale: {
            startValue: 0,
            endValue: 100,
            label: { visible: false }
        },
        markers: [
            { value: positivePercentage(), offset: -5 }
        ],
        rangeBars: [
            { value: positivePercentage(), color: "green", backgroundColor: "red", offset: -5 }
        ]
    });
});

And here is the result:

Changing the value dynamically

All that configuration is very handy, but it's also very static. We should jazz it up a little and update the indicators dynamically.

For the circular gauge, let's add a list of films depicted by their movie posters. The gauge needle will indicate the rating of the selected movie.

HTML
<div style="width:375px;margin: 0px auto">
    <img class="moviePoster" width="90" src="https://ia.media-imdb.com/images/M/MV5BMTI3ODM3MDkzNl5BMl5BanBnXkFtZTcwMzgwNDUyMQ@@._V1_SX214_.jpg" alt="His Girl Friday" data-rating="8"/>
    <img class="moviePoster" width="90" src="https://ia.media-imdb.com/images/M/MV5BMTM5MzQ4NTk1MV5BMl5BanBnXkFtZTcwNzkyMzU1MQ@@._V1_SY317_CR51,0,214,317_.jpg" alt="Roal Wedding" data-rating="6.6"/>
    <img class="moviePoster" width="90" src="https://ia.media-imdb.com/images/M/MV5BMTU0Nzk1MjU2Nl5BMl5BanBnXkFtZTcwNzkyMTM4NA@@._V1_SX214_.jpg" alt="The Screaming Skull" data-rating="3"/>
    <img class="moviePoster" width="90" src="https://ia.media-imdb.com/images/M/MV5BMjAxNTQzMDU5OV5BMl5BanBnXkFtZTcwOTkyMzcyMQ@@._V1_SY317_CR9,0,214,317_.jpg" alt="A Star Is Born" data-rating="7.5"/>
</div>

As you can see, I hardcoded the rating to the img elements (in the data-rating attribute). Yes, it is a rude but the simplest solution to implement this task. I want to make an accent on how to change the needle's value, not how to get a film rating. Although, you can improve my example and get real values using, for instance, the IMDb API.

We'll add a click event handler to each of the poster images. In this event handler we'll retrieve the circular gauge object, and then set the needle's value (see a full code here).

JavaScript
$("img.moviePoster").click(function() {
    var gauge = $("#circularGaugeContainer").dxCircularGauge("instance"); 
    gauge.needleValue(0, $(this).data("rating"));
});

For our linear gauge, let's add two buttons. Clicking these buttons you can give your voice for or against a film. The gauge's range bar and marker will move respectively (see a full code here).

HTML
<div>
    <button class="vote" data-sign="plus">+1</button>
    <button class="vote" data-sign="minus">-1</button>
</div> 
JavaScript
$("button.vote").click(function(){
    var gauge = $("#linearGaugeContainer").dxLinearGauge("instance");   
    if($(this).data("sign") === "plus") {
        positiveVotes++;
    } else {
        negativeVotes++;
    }
    gauge.rangeBarValue(0,positivePercentage());
    gauge.markerValue(0,positivePercentage());
});

Summary

As you have seen, it was relatively simple to implement these visually attractive gauges and make them useful (in some sense). If you want to learn more, there are more examples in our Visualization Gallery and more details in our documentation. Happy gauging! :)