利用JavaScript实现数据可视化

fm3d

贡献于2015-08-09

字数:0 关键词: 图表/报表制作 Java JavaScript

STEPHEN A. THOMAS DATA VISUALIZATION WITH JAVASCRIPT DATA VISUALIZATION WITH JAVASCRIPT SHELVE IN: COMPUTERS/WEB PROGRAMMING $39.95 ($45.95 CDN) www.nostarch.com TH E FINEST IN GEEK ENTERTAINMENT ™ MADE VISUAL. YOUR DATA You’ve got data to communicate. But what kind of visualization do you choose, how do you build it, and how do you ensure that it’s up to the demands of the Web? In Data Visualization with JavaScript, you’ll learn how practical visualizations for your data. Step-by-step to use JavaScript, HTML, and CSS to build the most examples walk you through creating, integrating, and debugging different types of visualizations and Then you’ll move on to more advanced topics, line, and scatter graphs, in no time. will have you building basic visualizations, like bar, • Create tree maps, heat maps, network graphs, word clouds, and timelines • Map geographic data, and build sparklines and composite charts • Add interactivity and retrieve data with AJAX “I LI E FLAT.” This book uses a durable binding that won’t snap shut. • Manage data in the browser and build data-driven web applications • Harness the power of the Flotr2, Flot, Chronoline.js, D3.js, Underscore.js, and Backbone.js libraries If you already know your way around building a web page but aren’t quite sure how to build a good visualization, Data Visualization with JavaScript will help you get your feet wet without throwing you into the deep end. Before you know it, you’ll be well on your way to creating simple, powerful data visualizations. and has developed complex JavaScript visualizations A B O U T T H E AUTHOR Stephen A. Thomas specializes in frontend development at Georgia Tech’s Department of Education Technology for the health-care and security industries. He writes and conferences around the world. speaks about data visualization in publications and at including how to: DATA VISUALIZATION WITH JAVASCRIPT DATA VISUALIZATION WITH JAVASCRIPT THOMAS SFI-00000 Data Visualization with JavaScript Data Visualization with JavaScript Stephen A. Thomas DATA VISUALIZATION WITH JAVASCRIPT. Copyright © 2015 by Stephen A. Thomas. All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher. Printed in USA First printing 19 18 17 16 15 1 2 3 4 5 6 7 8 9 ISBN-10: 1-59327-605-2 ISBN-13: 978-1-59327-605-8 Publisher: William Pollock Production Editor: Laurel Chun Cover Illustration: Beth Middleworth Developmental Editor: Seph Kramer Technical Reviewer: Christopher Keen Copyeditor: Rachel Monaghan Compositor: Lynn L’Heureux Proofreader: Emelie Burnette Indexer: BIM Indexing & Proofreading Services The visualization on the cover is inspired by the work of Mike Bostock. It is described in “Creating a Unique Visualization” on page 252. For information on distribution, translations, or bulk sales, please contact No Starch Press, Inc. directly: No Starch Press, Inc. 245 8th Street, San Francisco, CA 94103 phone: 415.863.9900; info@nostarch.com www.nostarch.com The Library of Congress Cataloging-in-Publication Data Thomas, Stephen A., 1962- Data visualization with JavaScript / by Stephen A. Thomas. pages cm ISBN 978-1-59327-605-8 -- ISBN 1-59327-605-2 1. Information visualization--Data processing. 2. JavaScript (Computer program language) I. Title. QA76.9.I52T46 2015 005.2'762--dc23 2014039759 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names mentioned herein may be the trademarks of their respective owners. Rather than use a trademark symbol with every occurrence of a trademarked name, we are using the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. The information in this book is distributed on an “As Is” basis, without warranty. While every precaution has been taken in the preparation of this work, neither the author nor No Starch Press, Inc. shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in it. About the Author Stephen A. Thomas specializes in frontend development at Georgia Tech’s Depart- ment of Education Technology and has developed complex JavaScript visualiza- tions for the health-care and security industries. He writes and speaks about data visualization in publications and at conferences around the world. About the Technical Reviewer Chris Keen resides in Atlanta, Georgia, and has been writing JavaScript since 2004. Chris has had the honor of working on visualizations ranging from an SVG tweet map at Weather.com to full-blown interactive maps with Leaflet.js at Endgame Systems. Chris is currently infatuated with making data dashboards using Backbone, Epoxy, and D3. Chris recently founded Keen Concepts (http:// keenconcepts.io/), and he consults on JavaScript-rich web applications. Brief Contents Acknowledgments...........................................................................................................xvi Introduction........................................................................................................................ 1 Chapter 1: Graphing Data................................................................................................. 5 Chapter 2: Making Charts Interactive............................................................................ 47 Chapter 3: Integrating Charts on a Page...................................................................... 89 Chapter 4: Creating Specialized Graphs......................................................................119 Chapter 5: Displaying Timelines....................................................................................147 Chapter 6: Visualizing Geographic Data......................................................................179 Chapter 7: Custom Visualizations with D3.js............................................................... 223 Chapter 8: Managing Data in the Browser.................................................................. 269 Chapter 9: Building Data-Driven Web Applications: Part 1 ..................................... 295 Chapter 10: Building Data-Driven Web Applications: Part 2 ................................... 327 Index................................................................................................................................ 353 Contents in Detail Acknowledgments.....................................................................................................xvi Introduction.................................................................................................................... 1 The Book’s Philosophy...................................................................................................... 2 The Book’s Contents......................................................................................................... 3 Source Code for Examples............................................................................................... 4 Chapter 1: Graphing Data......................................................................................... 5 Creating a Basic Bar Chart................................................................................................ 6 Step 1: Include the Required JavaScript............................................................... 6 Step 2: Set Aside a
Element to Hold the Chart......................................... 7 Step 3: Define the Data........................................................................................... 7 Step 4: Draw the Chart............................................................................................ 8 Step 5: Fix the Vertical Axis.................................................................................... 9 Step 6: Fix the Horizontal Axis............................................................................. 10 Step 7: Adjust the Styling.......................................................................................12 Step 8: Vary the Bar Color......................................................................................13 Step 9: Work Around Flotr2 “Bugs”..................................................................... 14 Plotting Continuous Data with a Line Chart................................................................. 15 Step 1: Define the Data......................................................................................... 15 Step 2: Graph the CO2 Data................................................................................. 16 Step 3: Add the Temperature Data.......................................................................17 Step 4: Improve the Chart’s Readability...............................................................17 Step 5: Clarify the Temperature Measurements................................................ 18 Step 6: Label the Chart......................................................................................... 20 Step 7: Work Around Flotr2 “Bugs”..................................................................... 21 Emphasizing Fractions Using a Pie Chart...................................................................... 21 Step 1: Define the Data......................................................................................... 23 Step 2: Draw the Chart.......................................................................................... 23 Step 3: Label the Values........................................................................................ 24 Step 4: Work Around Flotr2 “Bugs”..................................................................... 25 Plotting X/Y Data with a Scatter Chart.......................................................................... 25 Step 1: Define the Data......................................................................................... 26 Step 2: Format the Data........................................................................................ 26 Step 3: Plot the Data.............................................................................................. 26 Step 4: Adjust the Chart’s Axes............................................................................ 27 Step 5: Label the Data........................................................................................... 28 Step 6: Clarify the X-Axis....................................................................................... 29 Step 7: Answer Users’ Questions......................................................................... 30 Step 8: Work Around Flotr2 “Bugs”..................................................................... 33 Adding Magnitudes to X/Y Data with a Bubble Chart................................................ 34 Step 1: Define the Data......................................................................................... 34 Step 2: Create a Background for the Chart......................................................... 35 Step 3: Plot the Data.............................................................................................. 36 x | Co ntents in Detail Step 4: Add the Background................................................................................ 37 Step 5: Color the Bubbles..................................................................................... 38 Step 6: Adjust the Legend Styles......................................................................... 40 Step 7: Work Around Flotr2 “Bugs”..................................................................... 41 Displaying Multidimensional Data with a Radar Chart................................................ 41 Step 1: Define the Data......................................................................................... 42 Step 2: Create the Chart....................................................................................... 44 Step 3: Work Around Flotr2 “Bugs”..................................................................... 45 Summing Up..................................................................................................................... 46 Chapter 2: Making Charts Interactive............................................................... 47 Selecting Chart Content................................................................................................. 48 Step 1: Include the Required JavaScript Libraries.............................................. 49 Step 2: Set Aside a
Element to Hold the Chart....................................... 50 Step 3: Prepare the Data....................................................................................... 50 Step 4: Draw the Chart.......................................................................................... 51 Step 5: Add the Controls...................................................................................... 52 Step 6: Define the Data Structure for the Interaction........................................ 54 Step 7: Determine Chart Data Based on the Interaction State........................ 55 Step 8: Add the Controls Using JavaScript......................................................... 57 Step 9: Respond to the Interaction Controls...................................................... 58 Zooming In on Charts...................................................................................................... 59 Step 1: Prepare the Page....................................................................................... 60 Step 2: Draw the Chart.......................................................................................... 60 Step 3: Prepare the Data to Support Interaction................................................61 Step 4: Prepare to Accept Interaction Events..................................................... 62 Step 5: Enable the Interaction.............................................................................. 63 Tracking Data Values....................................................................................................... 65 Step 1: Set Aside a
Element to Hold the Charts..................................... 66 Step 2: Prepare the Data....................................................................................... 67 Step 3: Draw the Charts........................................................................................ 68 Step 4: Implement the Interaction....................................................................... 71 Retrieving Data Using AJAX........................................................................................... 75 Step 1: Understand the Source Data....................................................................76 Step 2: Get the First Level of Data via AJAX...................................................... 77 Step 3: Process the First Level of Data................................................................ 80 Step 4: Get the Real Data...................................................................................... 81 Step 5: Process the Data....................................................................................... 84 Step 6: Create the Chart....................................................................................... 85 Summing Up..................................................................................................................... 88 Chapter 3: Integrating Charts on a Page......................................................... 89 Creating a Classic Sparkline........................................................................................... 91 Step 1: Include the Required JavaScript Libraries.............................................. 91 Step 2: Create the HTML Markup for the Sparkline........................................... 91 Step 3: Draw the Sparkline.................................................................................... 92 Step 4: Adjust the Chart Style.............................................................................. 93 Contents in Detail | xi Charting Many Variables................................................................................................. 94 Step 1: Prepare the HTML Markup....................................................................... 94 Step 2: Draw the Charts........................................................................................ 95 Step 3: Establish a Default Style for the Charts.................................................. 96 Step 4: Modify the Default Style for Special Classes......................................... 97 Step 5: Create a Unique Style for a Specific Chart............................................. 99 Annotating Sparklines................................................................................................... 101 Step 1: Prepare the Data..................................................................................... 102 Step 2: Prepare the HTML Markup.................................................................... 102 Step 3: Add the Chart.......................................................................................... 102 Step 4: Add the Primary Annotation.................................................................. 103 Step 5: Provide Additional Information............................................................. 105 Drawing Composite Charts.......................................................................................... 105 Step 1: Draw the Trading Volume Chart............................................................ 106 Step 2: Add the Closing Price Chart.................................................................. 106 Step 3: Add the Annotations.............................................................................. 107 Step 4: Show Details as a Chart.......................................................................... 108 Responding to Click Events...........................................................................................110 Step 1: Add the Chart...........................................................................................110 Step 2: Handle Click Events.................................................................................111 Step 3: Improve the Transitions...........................................................................112 Step 4: Animate.....................................................................................................114 Updating Charts in Real Time........................................................................................115 Step 1: Retrieve the Data......................................................................................116 Step 2: Update the Visualization.........................................................................116 Summing Up....................................................................................................................117 Chapter 4: Creating Specialized Graphs..........................................................119 Visualizing Hierarchies with Tree Maps....................................................................... 120 Step 1: Include the Required Libraries.............................................................. 120 Step 2: Prepare the Data......................................................................................121 Step 3: Draw the Tree Map..................................................................................121 Step 4: Vary the Shading to Show Additional Data.......................................... 122 Highlighting Regions with a Heat Map........................................................................ 125 Step 1: Include the Required JavaScript........................................................... 126 Step 2: Define the Visualization Data................................................................ 127 Step 3: Create the Background Image.............................................................. 127 Step 4: Set Aside an HTML Element to Contain the Visualization................. 128 Step 5: Format the Data...................................................................................... 128 Step 6: Draw the Map.......................................................................................... 129 Step 7: Adjust the Heat Map z-index................................................................. 130 Showing Relationships with Network Graphs............................................................. 130 Step 1: Include the Required Libraries.............................................................. 130 Step 2: Prepare the Data......................................................................................131 Step 3: Define the Graph’s Nodes..................................................................... 132 xii | Co ntents in Detail Step 4: Connect the Nodes with Edges............................................................ 133 Step 5: Automate the Layout.............................................................................. 134 Step 6: Add Interactivity......................................................................................137 Revealing Language Patterns with Word Clouds....................................................... 138 Step 1: Include the Required Libraries.............................................................. 139 Step 2: Prepare the Data..................................................................................... 140 Step 3: Add the Required Markup......................................................................141 Step 4: Create a Simple Cloud............................................................................142 Step 5: Add Interactivity..................................................................................... 143 Summing Up................................................................................................................... 146 Chapter 5: Displaying Timelines..........................................................................147 Building Timelines with a Library................................................................................. 148 Step 1: Include the Required Libraries.............................................................. 148 Step 2: Prepare the Data......................................................................................149 Step 3: Draw the Timeline................................................................................... 150 Step 4: Set Chronoline.js Options for the Data................................................ 150 Building Timelines with JavaScript............................................................................... 153 Step 1: Prepare the HTML Skeleton................................................................... 154 Step 2: Start JavaScript Execution..................................................................... 154 Step 3: Create the Timeline in Semantic HTML................................................ 155 Step 4: Include the Supporting Content........................................................... 157 Step 5: Optionally Take Advantage of jQuery...................................................159 Step 6: Fix Timeline Problems with CSS.............................................................159 Step 7: Add Styles to Visually Structure the Timeline.......................................161 Step 8: Add Interactivity..................................................................................... 163 Using a Web Component...............................................................................................167 Step 1: Preview the Standard Component........................................................ 168 Step 2: Include the Required Components.......................................................170 Step 3: Prepare the Data......................................................................................170 Step 4: Create a Default Timeline.......................................................................172 Step 5: Adjust the Timeline Styles......................................................................174 Summing Up....................................................................................................................177 Chapter 6: Visualizing Geographic Data.........................................................179 Using Map Fonts............................................................................................................ 180 Step 1: Include the Fonts in the Page................................................................ 180 Step 2: Display One Country...............................................................................181 Step 3: Combine Multiple Countries into a Single Map.................................. 182 Step 4: Vary the Countries Based on the Data................................................. 183 Step 5: Add a Legend.......................................................................................... 185 Working with Scalable Vector Graphics...................................................................... 186 Step 1: Create the SVG Map............................................................................... 188 Step 2: Embed the Map in the Page.................................................................. 189 Step 3: Collect the Data...................................................................................... 190 Step 4: Define the Color Scheme....................................................................... 191 Step 5: Color the Map......................................................................................... 192 Contents in Detail | xiii Step 6: Add a Legend.......................................................................................... 193 Step 7: Add Interactions.......................................................................................194 Including Maps for Context.......................................................................................... 197 Step 1: Set Up the Web Page............................................................................. 198 Step 2: Prepare the Data..................................................................................... 198 Step 3: Choose a Map Style................................................................................ 199 Step 4: Draw the Map.......................................................................................... 199 Step 5: Add the Sightings...................................................................................200 Integrating a Full-Featured Mapping Library............................................................. 201 Step 1: Prepare the Data..................................................................................... 201 Step 2: Set Up the Web Page and Libraries...................................................... 202 Step 3: Draw the Base Map................................................................................. 203 Step 4: Add the Routes to the Map................................................................... 205 Step 5: Add an Animation Control..................................................................... 207 Step 6: Prepare the Animation........................................................................... 210 Step 7: Animate the Routes.................................................................................211 Step 8: Create Labels for the Stops....................................................................214 Step 9: Build the Label Animation..................................................................... 216 Step 10: Incorporate Label Animation in the Animation Step........................ 218 Step 11: Add a Title.............................................................................................. 221 Summing Up................................................................................................................... 222 Chapter 7: Custom Visualizations with D3.js................................................ 223 Adapting a Traditional Chart Type............................................................................... 224 Step 1: Prepare the Data..................................................................................... 225 Step 2: Set Up the Web Page............................................................................. 225 Step 3: Create a Stage for the Visualization...................................................... 226 Step 4: Control the Chart’s Dimensions............................................................ 227 Step 5: Draw the Chart Framework.................................................................... 228 Step 6: Add the Data to the Chart..................................................................... 231 Step 7: Answer Users’ Questions....................................................................... 232 Creating a Force-Directed Network Graph................................................................ 232 Step 1: Prepare the Data..................................................................................... 233 Step 2: Set Up the Page...................................................................................... 234 Step 3: Create a Stage for the Visualization...................................................... 235 Step 4: Draw the Graph’s Nodes........................................................................ 235 Step 5: Draw the Graph’s Edges........................................................................ 238 Step 6: Position the Elements............................................................................. 238 Step 7: Add Force Direction to the Graph........................................................ 240 Step 8: Add Interactivity..................................................................................... 242 Step 9: Experiment with Other Enhancements................................................ 245 Creating a Scalable Map............................................................................................... 245 Step 1: Prepare the Data..................................................................................... 245 Step 2: Set Up the Page...................................................................................... 246 Step 3: Create a Map Projection........................................................................ 246 Step 4: Initialize the SVG Container................................................................... 247 Step 5: Retrieve the Map Data........................................................................... 247 xiv | Co ntents in Detail Step 6: Draw the Map.......................................................................................... 248 Step 7: Retrieve the Weather Data..................................................................... 249 Step 8: Plot the Data............................................................................................ 249 Step 9: Add Interactivity..................................................................................... 250 Creating a Unique Visualization................................................................................... 252 Step 1: Prepare the Data..................................................................................... 253 Step 2: Set Up the Page...................................................................................... 253 Step 3: Create a Stage for the Visualization...................................................... 254 Step 4: Create Scales........................................................................................... 254 Step 5: Retrieve the Data.................................................................................... 256 Step 6: Draw the Visualization............................................................................ 258 Step 7: Color the Areas....................................................................................... 259 Step 8: Make the Visualization Interactive........................................................ 262 Summing Up................................................................................................................... 267 Chapter 8: Managing Data in the Browser.................................................... 269 Using Functional Programming.................................................................................... 270 Step 1: Start with an Imperative Version........................................................... 271 Step 2: Debug the Imperative Code................................................................. 271 Step 3: Understand the Problems Imperative Programming May Introduce................................................................ 272 Step 4: Rewrite Using Functional Programming Style..................................... 273 Step 5: Evaluate Performance............................................................................ 273 Step 6: Fix the Performance Problem.................................................................274 Working with Arrays....................................................................................................... 275 Extracting Elements by Position........................................................................ 275 Combining Arrays................................................................................................ 278 Removing Invalid Data Values............................................................................ 280 Finding Elements in an Array............................................................................. 281 Generating Arrays................................................................................................ 282 Enhancing Objects........................................................................................................ 283 Working with Keys and Values............................................................................ 283 Cleaning Up Object Subsets.............................................................................. 285 Updating Attributes............................................................................................ 286 Manipulating Collections.............................................................................................. 288 Working with Iteration Utilities........................................................................... 289 Finding Elements in a Collection.......................................................................290 Testing a Collection............................................................................................. 292 Rearranging Collections..................................................................................... 292 Summing Up................................................................................................................... 294 Chapter 9: Building Data-Driven Web Applications: Part 1 .................. 295 Frameworks and Libraries............................................................................................. 297 Step 1: Select an Application Library................................................................ 297 Step 2: Install Development Tools..................................................................... 298 Step 3: Define a New Project.............................................................................. 298 Step 4: Add Our Unique Dependencies........................................................... 301 Contents in Detail | xv Models and Views.......................................................................................................... 302 Step 1: Define the Application’s Models........................................................... 303 Step 2: Implement the Model............................................................................304 Step 3: Define the Application’s Collections....................................................306 Step 4: Define the Application’s Main View...................................................... 307 Step 5: Define the Main View Templates............................................................311 Step 6: Refine the Main View...............................................................................314 Views for Visualizations...................................................................................................316 Step 1: Define the Additional Views...................................................................317 Step 2: Implement the Details View....................................................................317 Step 3: Implement the Properties View..............................................................318 Step 4: Implement the Map View....................................................................... 322 Step 5: Implement the Charts View................................................................... 325 Summing Up................................................................................................................... 326 Chapter 10: Building Data-Driven Web Applications: Part 2 ................ 3 27 Connecting with the Nike+ Service............................................................................. 328 Step 1: Authorize Users....................................................................................... 328 Step 2: Accept the Nike+ Response..................................................................330 Step 3: Page the Collection................................................................................330 Step 4: Dynamically Update the View................................................................ 334 Step 5: Filter the Collection................................................................................ 335 Step 6: Parse the Response................................................................................ 336 Step 7: Retrieve Details....................................................................................... 336 Putting It All Together...................................................................................................340 Step 1: Create a Backbone.js Router.................................................................340 Step 2: Support Run Models Outside of Any Collection................................ 342 Step 3: Let Users Change Views......................................................................... 345 Step 4: Fine-Tune the Application...................................................................... 349 Summing Up................................................................................................................... 351 Index.............................................................................................................................. 353 Acknowledgments Even though it’s been said many times, there’s no getting around the fact that a book is the work of many people other than the author. This book certainly wouldn’t have been possible without the patience of Seph and the other fine folks at No Starch Press. There simply is no better publisher for technical books. Kudos also to Chris for the technical review, though, of course, the remaining mistakes are mine alone. I owe a special thanks to NickC for his generosity; it’s such a plea- sure to meet folks that appreciate the true community spirit of the Web and web development. Finally, shout-outs to the team developing the Open Academic Environment and my colleagues at the Georgia Institute of Technology; working with them is a true pleasure. Introduction It’s getting hard to ignore the importance of data in our lives. Data is critical to the largest social organizations in human history (giants like Facebook and Google), and its collection has widespread geopolitical implications, as we all saw with the NSA surveillance scandal. But it’s also getting easier to ignore the data itself. One estimate suggests that 99.5% of the data our systems collect goes to waste. 2 | Introduction Data visualization is a tool that addresses this gap. Effective visualizations clarify; they transform abstract collections of numbers into shapes and forms that viewers quickly grasp and understand. The best visualizations impart this under- standing intuitively. Viewers comprehend the data immediately—without thinking. This frees viewers to more fully consider the implications of the data: the stories it tells, the insights it reveals, or even the warnings it offers. If you’re developing websites or web applications today, there’s a good chance you have data to communicate—data best presented in a good visual- ization. But how do you know what kind of visualization is appropriate? And even more importantly, how do you actually create one? In the chapters that follow, we explore dozens of different visualizations, techniques, and toolkits. Each example discusses the appropriateness of the visualization (and suggests possible alterna- tives) and provides step-by-step instructions for adding the visualization to your web pages. The Book’s Philosophy In creating this book, I’ve tried to follow four main principles to make sure it pro- vides meaningful and practical guidance. Implementation vs. Design This book won’t teach you how to design data visualizations. Quite honestly, there are other authors far better qualified than me for that (Edward Tufte, for example). Instead, this book will focus on implementing visualizations. When appropriate, I’ll take a slightly bigger picture view to discuss the strengths and weaknesses of particular visualization strategies, but the main goal is to show you how to create a wide range of visualizations. (I recognize that sometimes the boss absolutely insists on a pie chart.) Code vs. Styling As you might guess from the title, this book focuses on how to use Java­ Script code to create visualizations. The examples don’t assume you’re a JavaScript expert—and I’ll be sure to explain any code more complicated than a basic jQuery selector—but I won’t spend much time discussing styles for the visualizations. Fortunately, styling visualizations is pretty much the same as styling other web content. Basic experience with HTML and CSS will serve you well when you add visualizations to your pages. Simple vs. Complex Most of the book’s examples are simple, straightforward visualizations. Com- plex visualizations can be engaging and compelling, but studying a lot of advanced code usually isn’t the best way to learn the craft. In these examples, I’ll try to stay as simple as possible so you can clearly see how to use the vari- ous tools and techniques. Simple doesn’t mean boring, however, and even the simplest visualizations can be enlightening and inspiring. Introduction | 3 Reality vs. an Ideal World When you begin building your own visualizations, you’ll discover that the real world is rarely as kind as you’d wish. Open source libraries have bugs, third-party servers have security issues, and not every user has updated to the latest and greatest web browser. I’ve addressed these realities in the examples in this book. I’ll show you how to accommodate older browsers when it’s practical, how to comply with security constraints such as Cross- Origin Resource Sharing (CORS), and how to work around bugs in other folks’ code. The Book’s Contents The chapters that follow cover a variety of visualization techniques and the JavaScript libraries that we can use to implement them. >> Chapter 1 begins with the most basic visualizations—static charts and plots—using the Flotr2 library. >> Chapter 2 adds interactivity to the visualizations, giving users the chance to select content, zoom in, and track values. The chapter also shows how to retrieve data for visualizations directly from the Web. For variety, its examples use the Flot library, which is based on jQuery. >> Chapter 3 looks at integrating multiple visualizations and with other content on a web page; it uses the jQuery sparklines library. >> In Chapter 4, we consider visualizations other than standard charts and plots, including tree maps, heat maps, network graphs, and word clouds. Each example focuses on a particular JavaScript library designed specifically for the visualization type. >> Chapter 5 covers time-based visualizations. It looks at several ways to visual- ize timelines, including traditional libraries; pure HTML, CSS, and JavaScript; and full-featured web components. >> In Chapter 6, we consider geographic data as we look at different ways to incorporate maps into our visualizations. >> Chapter 7 introduces the powerful D3.js library, a flexible and full-featured toolkit for building custom visualizations of almost any type. >> Beginning in Chapter 8, we consider other aspects of web-based visualiza- tions. This chapter shows off the Underscore.js library, which makes it easy to prepare the data that drives our visualizations. >> Finally, Chapters 9 and 10 walk through the development of a complete, single-page web application that relies on data visualization. Here we’ll see how to use modern development tools such as Yeoman and the Backbone.js library. 4 | Introduction Source Code for Examples To make the text as clear and readable as possible, examples usually contain iso- lated snippets of JavaScript, plus occasional fragments of HTML or CSS. Complete source code for all examples is available on GitHub at http://jsDataV.is/source/. 1Graphing Data Many people think of data visualization as intri- cate interactive graphics of dazzling complex- ity. Creating effective visualizations, however, doesn’t require Picasso’s artistic skill or Turing’s programming expertise. In fact, when you con- sider the ultimate purpose of data visualization— helping users understand data—simplicity is one of the most important features of an effective visualization. Simple, straightforward charts are often the easiest to understand. 6 | Cha pter 1 After all, users have seen hundreds or thousands of bar charts, line charts, X/Y plots, and the like. They know the conventions that underlie these charts, so they can interpret a well-designed example effortlessly. If a simple, static chart presents the data best, use it. You’ll spend less effort creating your visualization, and your users will spend less effort trying to understand it. There are many high-quality tools and libraries to help you get started with simple visualizations. With these tools, you can avoid reinventing the wheel, and you can be assured of a reasonably attractive presentation by sticking with the library defaults. We’ll look at several of these tools throughout the book, but for this chapter we’ll use the Flotr2 library (http://www.humblesoftware.com/flotr2/). Flotr2 makes it easy to add standard bar charts, line charts, and pie charts to any web page, and it also supports some less common chart types. We’ll take a look at all of these techniques in the examples that follow. Here’s what you’ll learn: >> How to create a basic bar chart >> How to plot continuous data with a line chart >> How to emphasize fractions with a pie chart >> How to plot X/Y data with a scatter chart >> How to show magnitudes of X/Y data with a bubble chart >> How to display multidimensional data with a radar chart Creating a Basic Bar Chart If you’re ever in doubt about what type of chart best explains your data, your first consideration should probably be the basic bar chart. We see bar charts so often that it’s easy to overlook how effective they can be. Bar charts can show the evo- lution of a value over time, or they can provide a straightforward comparison of multiple values. Let’s walk through the steps to build one. Step 1: Include the Required JavaScript Since we’re using the Flotr2 library to create the chart, we need to include that library in our web pages. The Flotr2 package isn’t currently popular enough for public con- tent distribution networks, so you’ll need to download a copy and host it on your own web server. We’ll use the minimized version (flotr2.min.js) since it provides the best performance. Flotr2 doesn’t require any other JavaScript libraries (such as jQuery), but it does rely on the HTML canvas feature. Major modern browsers (Safari, Chrome, Firefox) support canvas, but until version 9, Internet Explorer (IE) did not. Unfor- tunately, there are still millions of users with IE8 (or even earlier). To support those users, we can include an additional library (excanvas.min.js) in our pages. That library is available from Google (https://code.google.com/p/explorercanvas/). Start with the following skeleton for your HTML document: Graphing Data | 7 u Since other browsers don’t need excanvas.min.js, we use some special markup at u to make sure that only IE8 and earlier will load it. Also, notice that we’re including the JavaScript libraries at the end of the document. This approach lets the browser load the document’s entire HTML markup and begin laying out the page while it waits for the server to provide the JavaScript libraries. Step 2: Set Aside a
Element to Hold the Chart Within our document, we need to create a
element to contain the chart. This element must have an explicit height and width, or Flotr2 won’t be able to construct the chart. We can indicate the element’s size in a CSS style sheet, or we can place it directly on the element itself. Here’s how the document might look with the latter approach.
Note that we’ve given the
an explicit id ("chart") so we can reference it later. You’ll need to use a basic template like this (importing the Flotr2 library and setting up the
) for all the charts in this chapter. Step 3: Define the Data Now we can tackle the data that we want to display. For this example, I’ll use the number of Manchester City wins in the English Premier League for the past seven years. Of course you’ll want to substitute your actual data values, either with inline JavaScript (like the following example) or by another means (such as an AJAX call to the server). 8 | Cha pter 1 As you can see, we have three layers of arrays. Let’s start from the inside and work our way out. For Flotr2 charts, each data point is entered in a two-item array with an x-value and y-value. In our case we’re using the year as the x-value and the number of wins as the y-value. We collect all these values in another array called a series. We place this series inside one more outer array. We could enter multiple series into this outer array, but for now we’re showing only one series. Here’s a quick summary of each layer: >> Each data point consists of an x-value and a y-value packaged in an array. >> Each series consists of a set of data points packaged in an array. >> The data to chart consists of one or more series packaged in an array. Step 4: Draw the Chart That’s all the setup we need. A simple call to the Flotr2 library, as shown here, creates our first attempt at a chart. window.onload = function () { Flotr.draw( document.getElementById("chart"), wins, { bars: { show: true } } ); }; First we make sure the browser has loaded our document; otherwise, the chart
might not be present. That’s the point of window.onload. Once that event occurs, we call Flotr.draw with three parameters: the HTML element to con- tain the chart, the data for the chart, and any chart options (in this case, we specify options only to tell Flotr2 to create a bar chart from the data). Since Flotr2 doesn’t require jQuery, we haven’t taken advantage of any of jQuery’s shortcuts in this example. If your page already includes jQuery, you can use the standard jQuery conventions for the Flotr2 charts in this chapter to execute the script after the window has loaded, and to find the
container for the chart. Figure 1-1 shows what you’ll see on the web page. Graphing Data | 9 25.0 20.0 15.0 2005.0 2006.0 2007.0 2008.0 2009.0 2010.0 2011.0 2012.0 2013.0 Figure 1-1: The Flotr2 library turns data into a basic (if unpolished) bar chart. Now you have a bar chart, but it’s not showing the information very effec- tively. Let’s add some options incrementally until we get what we want. Step 5: Fix the Vertical Axis The most glaring problem with the vertical axis is its scale. By default, Flotr2 auto- matically calculates the range of the axis from the minimum and maximum values in the data. In our case the minimum value is 11 wins (from 2007), so Flotr2 dutifully uses that as its y-axis minimum. In bar charts, however, it’s almost always best to make 0 the y-axis minimum. If you don’t use 0, you risk overemphasizing the dif- ferences between values and confusing your users. Anyone who glances at the chart in Figure 1-1, for example, might think that Manchester City did not win any matches in 2007. That certainly wouldn’t do the team any justice. Another problem with the vertical axis is the formatting. Flotr2 defaults to a precision of one decimal place, so it adds the superfluous “.0” to all the labels. We can fix both of these problems by specifying some y-axis options. Flotr.draw(document.getElementById("chart"), [wins], { bars: { show: true }, yaxis: { min: 0, tickDecimals: 0 } }); 10 | Cha pter 1 The min property sets the minimum value for the y-axis, and the tickDecimals property tells Flotr2 how many decimal places to show for the labels. In our case we don’t want any decimal places. As you can see in Figure 1-2, adding these options definitely improves the vertical axis since the values now start at zero and are formatted appropriately for integers. 30 20 2005.0 2006.0 2007.0 2008.0 2009.0 2010.0 2011.0 2012.0 2013.0 25 15 10 5 0 Figure 1-2: Simple options help Flotr2 construct a better vertical axis. Step 6: Fix the Horizontal Axis The horizontal axis needs some work as well. Just as with the y-axis, Flotr2 assumes that the x-axis values are real numbers and shows one decimal place in the labels. Since we’re charting years, we could simply set the precision to 0, as we did for the y-axis. But that’s not a very general solution, since it won’t work when the x-values are non-numeric categories (like team names). For the more general case, let’s first change our data to use simple numbers rather than years for the x-values. Then we’ll create an array that maps those simple numbers to arbitrary strings, which we can use as labels. var wins = [[[0,13],[1,11],[2,15],[3,15],[4,18],[5,21],[6,28]]]; var years = [ [0, "2006"], [1, "2007"], [2, "2008"], [3, "2009"], [4, "2010"], [5, "2011"], [6, "2012"] ]; Graphing Data | 11 As you can see, instead of using the actual years for the x-values, we’re simply using 0, 1, 2, and so on. We then define a second array that maps those integer values to strings. Although here our strings are years (and thus numbers), they could be anything. Another problem is a lack of spacing between the bars. By default, each bar takes up its full horizontal space, but that makes the chart look very cramped. We can adjust that with the barWidth property. Let’s set it to 0.5 so that each bar takes up only half the available space. Here’s how we pass those options to Flotr2. Flotr.draw(document.getElementById("chart"), wins, { bars: { show: true, barWidth: 0.5 }, yaxis: { min: 0, tickDecimals: 0 }, xaxis: { u ticks: years } }); Note at u that we use the ticks property of the x-axis to tell Flotr2 which labels match which x-values. Now we’re starting to get somewhere with our chart, as shown in Figure 1-3. The x-axis labels are appropriate for years, and there is space between the bars to improve the chart’s legibility. 30 20 2006 2007 2008 2009 2010 2011 2012 25 15 10 5 0 Figure 1-3: We can define our own labels for the horizontal axis. 12 | Cha pter 1 Step 7: Adjust the Styling Now that the chart is functional and readable, we can pay some attention to the aesthetics. Let’s add a title, get rid of the unnecessary grid lines, and adjust the coloring of the bars. Flotr.draw(document.getElementById("chart"), wins, { title: "Manchester City Wins", colors: ["#89AFD2"], bars: { show: true, barWidth: 0.5, shadowSize: 0, fillOpacity: 1, lineWidth: 0 }, yaxis: { min: 0, tickDecimals: 0 }, xaxis: { ticks: years }, grid: { horizontalLines: false, verticalLines: false } }); As you can see in Figure 1-4, we now have a bar chart that Manchester City fans can be proud of. 30 25 20 15 10 5 0 2006 2007 2008 2009 2010 2011 2012 Manchester City Wins Figure 1-4: Additional options let us adjust the visual styles of the chart. Graphing Data | 13 For any data set of moderate size, the standard bar chart is often the most effective visualization. Users are already familiar with its conventions, so they don’t have to put any extra effort into understanding the format. The bars themselves offer a clear visual contrast with the background, and they use a single linear dimension (height) to show differences between values, so users easily grasp the salient data. Step 8: Vary the Bar Color So far our chart has been monochromatic. That makes sense because we’re show- ing the same value (Manchester City wins) across time. But bar charts are also good for comparing different values. Suppose, for example, we wanted to show the total wins for multiple teams in one year. In that case, it makes sense to use a different color for each team’s bar. Let’s go over how we can do that. First we need to restructure the data somewhat. Previously we’ve shown only a single series. Now we want a different series for each team. Creating multiple series lets Flotr2 color each independently. The following example shows how the new data series compares with the old. We’ve left the wins array in the code for comparison, but it’s the wins2 array that we’re going to show now. Notice how the nesting of the arrays changes. Also, we’re going to label each bar with the team abbreviation instead of the year. var wins = [[[0,13],[1,11],[2,15],[3,15],[4,18],[5,21],[6,28]]]; var wins2 = [[[0,28]],[[1,28]],[[2,21]],[[3,20]],[[4,19]]]; var teams = [ [0, "MCI"], [1, "MUN"], [2, "ARS"], [3, "TOT"], [4, "NEW"] ]; With those changes, our data is structured appropriately, and we can ask Flotr2 to draw the chart. When we do that, let’s use different colors for each team. Everything else is the same as before. Flotr.draw(document.getElementById("chart"), wins2, { title: "Premier League Wins (2011-2012)", colors: ["#89AFD2", "#1D1D1D", "#DF021D", "#0E204B", "#E67840"], bars: { show: true, barWidth: 0.5, shadowSize: 0, fillOpacity: 1, lineWidth: 0 }, yaxis: { min: 0, tickDecimals: 0 }, 14 | Cha pter 1 xaxis: { ticks: teams }, grid: { horizontalLines: false, verticalLines: false } }); As you can see in Figure 1-5, with a few minor adjustments we’ve completely changed the focus of our bar chart. Instead of showing a single team at different points in time, we’re now comparing different teams at the same point in time. That’s the versatility of a simple bar chart. 30 25 20 15 10 5 0 MCI MUN ARS TOT NEW Premier League Wins (2011-2012) Figure 1-5: Bar charts can compare different quantities at one point in time as well as the same quantity at different points in time. We’ve used a lot of different code fragments to put together these examples. If you want to see a complete example in a single file, check out this book’s source code at http://jsDataV.is/source/. Step 9: Work Around Flotr2 “Bugs” If you’re building large web pages with a lot of content, you may run into a Flotr2 “bug” that can be quite annoying. I’ve put “bug” in quotation marks because the Flotr2 behavior is deliberate, but I believe it’s not correct. In the process of con- structing its charts, Flotr2 creates dummy HTML elements so it can calculate their sizes. Flotr2 doesn’t intend these dummy elements to be visible on the page, so it “hides” them by positioning them off the screen. Unfortunately, what Flotr2 thinks is off the screen isn’t always. Specifically, line 2,281 of flotr2.js is: D.setStyles(div, { "position" : "absolute", "top" : "-10000px" }); Graphing Data | 15 Flotr2 intends to place these dummy elements 10,000 pixels above the top of the browser window. However, CSS absolute positioning can be relative to the containing element, which is not always the browser window. So if your document is more than 10,000 pixels high, you may find Flotr2 scattering text in random- looking locations throughout the page. There are a couple of ways to work around this bug, at least until the Flotr2 code is revised. One option is to modify the code yourself. Flotr2 is open source, so you can freely download the full source code and modify it appropriately. One simple modification would position the dummy elements far to the right or left rather than above. Instead of "top" you could change the code to "right". If you’re not comfortable making changes to the library’s source code, another option is to find and hide those dummy elements yourself. You should do this after you’ve called Flotr.draw() for the last time. The latest version of jQuery can banish these extra- neous elements with the following statement: $(".flotr-dummy-div").parent().hide(); Plotting Continuous Data with a Line Chart Bar charts work great for visualizing a modest amount of data, but for more signifi- cant amounts of data, a line chart can present the information much more effec- tively. Line charts are especially good at revealing overall trends in data without bogging the user down in individual data points. For our example, we’ll look at two measures that may be related: carbon dioxide (CO2) concentration in the atmosphere and global temperatures. We want to show how both measures have changed over time, and we’d like to see how strongly related the values are. A line chart is a perfect visualization tool for look- ing at these trends. Just like for the bar chart, you’ll need to include the Flotr2 library in your web page and create a
element to contain the chart. Let’s start prepping the data. Step 1: Define the Data We’ll begin with CO2 concentration measurements. The US National Oceanographic and Atmospheric Administration (NOAA) publishes measurements (http://www.esrl​ .noaa.gov/gmd/ccgg/trends/co2_data_mlo.html) taken at Mauna Loa, Hawaii, from 1959 to the present day. The first few values are shown in the following excerpt. var co2 = [ [ 1959, 315.97 ], [ 1960, 316.91 ], [ 1961, 317.64 ], [ 1962, 318.45 ], // Data set continues... 16 | Cha pter 1 NOAA also publishes measurements of mean global surface temperature (http://www.ncdc.noaa.gov/cmb-faq/anomalies.php). These values measure the dif- ference from the baseline, which is currently taken to be the average temperature over the entire 20th century. Since the CO2 measurements begin in 1959, we’ll use that as our starting point for temperature as well. var temp = [ [ 1959, 0.0776 ], [ 1960, 0.0280 ], [ 1961, 0.1028 ], [ 1962, 0.1289 ], // Data set continues... Step 2: Graph the CO2 Data Graphing one data set is quite easy with Flotr2. We simply call the draw() method of the Flotr object. The only parameters the method requires are a reference to the HTML element in which to place the graph, and the data itself. The lines prop- erty of the data object indicates that we want a line chart. Flotr.draw( document.getElementById("chart"), [{ data: co2, lines: {show:true} }] ); Since Flotr2 does not require jQuery, we’re not using any jQuery conve- nience functions in our example. If you do have jQuery on your pages, you can simplify the preceding code a little. In either case, Figure 1-6 shows the result. 380 360 340 320 1960 1970 1980 1990 2000 2010 Figure 1-6: The first chart shows one data set. Graphing Data | 17 The chart clearly shows the trend in CO2 concentration for the past 50-plus years. Step 3: Add the Temperature Data With a simple addition to our code, we can include temperature measurements in our chart. Flotr.draw( document.getElementById("chart"), [ { data: co2, lines: {show:true} }, { data: temp, lines: {show:true}, yaxis: 2 } ] ); Note that we include the yaxis option for the temperature data and give it a value of 2. That tells Flotr2 to use a different y-scale for the temperature data. The chart in Figure 1-7 now shows both measurements for the years in ques- tion, but it’s gotten a little cramped and confusing. The values butt up against the edges of the chart, and the grid lines are hard for users to interpret when there are multiple vertical axes. 380 360 340 320 1960 1970 1980 1990 2000 2010 0.00 0.20 0.40 0.60 Figure 1-7: A single chart can show multiple data sets. Step 4: Improve the Chart’s Readability By using more Flotr2 options, we can make several improvements in our line chart’s readability. First we can eliminate the grid lines, since they aren’t relevant for the temperature measurements. 18 | Cha pter 1 We can also extend the range of both vertical axes to provide a bit of breathing room for the chart. Both of these changes are additional options to the draw() method. Flotr.draw( document.getElementById("chart"), [ { data: co2, lines: {show:true} }, { data: temp, lines: {show:true}, yaxis: 2 } ],{ u grid: {horizontalLines: false, verticalLines: false}, v yaxis: {min: 300, max: 400}, w y2axis: {min: -0.15, max: 0.69} } ); The grid options at u turn off the grid lines by setting both the horizontalLines and verticalLines properties to false. The yaxis options at v specify the minimum and maximum value for the first vertical axis (CO2 concentra- tion), while the y2axis options at w specify those values for the second vertical axis (temperature difference). The resulting graph in Figure 1-8 is cleaner and easier to read. 380 360 340 320 1960 1970 1980 1990 2000 2010 0.00 0.20 0.40 0.60 300 400 Figure 1-8: Removing grid lines and expanding the axes makes the chart easier to read. Step 5: Clarify the Temperature Measurements The temperature measurements might still be confusing to users, since they’re not really temperatures; they’re actually deviations from the 20th-century average. Let’s convey that distinction by adding a line for that 20th-century average and Graphing Data | 19 explicitly labeling it. The simplest way to do that is to create a “dummy” data set and add that to the chart. The extra data set has nothing but zeros. var zero = []; for (var yr=1959; yr<2012; yr++) { zero.push([yr, 0]); }; When we add that data set to the chart, we need to indicate that it corre- sponds to the second y-axis. And since we want this line to appear as part of the chart framework rather than as another data set, let’s deemphasize it somewhat by setting its width to one pixel, coloring it dark gray, and disabling shadows. Flotr.draw( document.getElementById("chart"), [ { data: zero, lines: {show:true, lineWidth: 1}, yaxis: 2, shadowSize: 0, color: "#545454" }, { data: co2, lines: {show:true} }, { data: temp, lines: {show:true}, yaxis: 2 } ],{ grid: {horizontalLines: false, verticalLines: false}, yaxis: {min: 300, max: 400}, y2axis: {min: -0.15, max: 0.69} } ); As you can see, we’ve placed the zero line first among the data sets. With that order, Flotr2 will draw the actual data on top of the zero line, as shown in Fig- ure 1-9, reinforcing its role as chart framework instead of data. 380 360 340 320 1960 1970 1980 1990 2000 2010 0.00 0.20 0.40 0.60 300 400 Figure 1-9: A dummy data set can emphasize a position on a chart axis. 20 | Cha pter 1 Step 6: Label the Chart For the last step in this example, we’ll add appropriate labels to the chart. That includes an overall title, as well as labels for individual data sets. And to make it clear which axis refers to temperature, we’ll add a “°C” suffix to the temperature scale. We identify the label for each data series in the label option for that series. The overall chart title merits its own option, and we add the “°C” suffix using a tickFormatter() function. Flotr.draw( document.getElementById("chart"), [ { data: zero, label: "20th-Century Baseline Temperature", lines: {show:true, lineWidth: 1}, shadowSize: 0, color: "#545454" }, { data: temp, label: "Yearly Temperature Difference (°C)", lines: {show:true} }, { data: co2, yaxis: 2, label: "CO2 Concentration (ppm)", lines: {show:true} } ], { title: "Global Temperature and CO2 Concentration (NOAA Data)", grid: {horizontalLines: false, verticalLines: false}, y2axis: {min: -0.15, max: 0.69, u tickFormatter: function(val) {return val+" °C";}} yaxis: {min: 300, max: 400}, } ); For each value on the axis, the formatter function is called with the value, and Flotr2 expects it to return a string to use for the label. As you can see at u, we simply append the " °C" string to the value. Notice that we’ve also swapped the position of the CO2 and temperature graphs. We’re now passing the temperature data series ahead of the CO2 series. We did that so that the two temperature quantities (baseline and difference) appear next to each other in the legend, making their connection a little clearer to the user. Graphing Data | 21 And because the temperature now appears first in the legend, we’ve also swapped the axes, so the temperature axis is on the left. Finally, we’ve adjusted the title of the chart for the same reason. Figure 1-10 shows the result. 0.60 ºC 0.40 ºC 0.20 ºC 0.00 ºC 1960 1970 1980 1990 2000 2010 300 320 340 360 380 400 20th-Century Baseline Temperature Yearly Temperature Difference (ºC) CO Concentration (ppm)2 Global Temperature and CO Concentration (NOAA Data)2 Figure 1-10: Labeling the axes and adding a legend completes the chart. A line chart like Figure 1-10 excels in visualizing this kind of data. Each data set contains over 50 points, making it impractical to present each individual point. And in fact, individual data points are not the focus of the visualization. Rather, we want to show trends—the trends of each data set as well as that data set’s correla- tion to the others. Connecting the points with lines leads the user right to those trends and to the heart of our visualization. Step 7: Work Around Flotr2 “Bugs” Be sure to refer to Step 9 of “Creating a Basic Bar Chart” on page 14 to see how to work around some “bugs” in the Flotr2 library. Emphasizing Fractions Using a Pie Chart Pie charts don’t get a lot of love in the visualization community, and for a pretty good reason: they’re rarely the most effective way to communicate data. We will walk through the steps to create pie charts in this section, but first let’s take some time to understand the problems they introduce. Figure 1-11, for example, shows a simple pie chart. Can you tell from the chart which color is the largest? The smallest? 22 | Cha pter 1 Figure 1-11: Pie charts can make it hard to compare values. It’s very hard to tell. That’s because humans are not particularly good at judging the relative size of areas, especially if those areas aren’t rectangles. If we really wanted to compare these five values, a bar chart works much better. Fig- ure 1-12 shows the same values in a bar chart. Figure 1-12: Bar charts usually make comparisons easier. Now, of course, it’s easy to rank each color. With a bar chart we only have to compare one dimension—height. This yields a simple rule of thumb: if you’re com- paring different values against one another, consider a bar chart first. It will almost always provide the best visualization. One case, however, where pie charts can be quite effective is when we want to compare a single partial value against a whole. Say, for example, we want to visualize the percentage of the world’s population that lives in poverty. In that case, a pie chart may work quite well. Here’s how we can construct such a chart using Flotr2. Just as in Step 1 of “Creating a Basic Bar Chart” on page 6, we need to include the Flotr2 library in our web page and set aside a
element to contain the chart we’ll construct. Graphing Data | 23 Step 1: Define the Data The data here is quite straightforward. According to the World Bank (http://www​ .newgeography.com/content/003325-alleviating-world-poverty-a-progress-report), at the end of 2008, 22.4 percent of the world’s population lived on less than $1.25/day. That’s the fraction that we want to emphasize with our chart. var data = [[[0,22.4]],[[1,77.6]]]; Here we have an array with two data series: one for the percentage of the population in poverty (22.4) and a second series for the rest (77.6). Each series itself consists of an array of points. In this example, and for pie charts in general, there is only one point in each series, with an x-value and a y-value (which are each stored together in yet another, inner array). For pie charts, the x-values are irrelevant, so we simply include the placeholder values 0 and 1. Step 2: Draw the Chart To draw the chart, we call the draw() method of the Flotr object. That method takes three parameters: the element in our HTML document in which to place the chart, the data for our chart, and any options. We’ll start with the minimum set of options required for a pie chart. window.onload = function () { Flotr.draw(document.getElementById("chart"), data, { pie: { show: true }, yaxis: { u showLabels: false }, xaxis: { v showLabels: false }, grid: { w horizontalLines: false, x verticalLines: false } }); } As you can see, Flotr2 requires a few more options for a minimum pie chart than it does for other common chart types. For both the x- and y-axes we need to disable labels, which we do by setting the showLabels property to false at u and v. We also have to turn off the grid lines, as a grid doesn’t make a lot of sense for a pie chart. We accomplish that by setting the verticalLines and horizontalLines properties of the grid option to false at w and x. Since Flotr2 doesn’t require jQuery, we’re not using any of the jQuery con- venience functions in this example. If you do have jQuery for your pages, you can simplify this code a bit. 24 | Cha pter 1 Figure 1-13 is a start, but it’s hard to tell exactly what the graph intends to show. 22.40% 77.60% Figure 1-13: Without effective labeling, pie charts can be difficult to interpret. Step 3: Label the Values The next step is to add some text labels and a legend to indicate what the chart is displaying. To label each quantity separately, we have to change the structure of our data. Instead of using an array of series, we’ll create an object to store each series. Each object’s data property will contain the corresponding series, and we’ll add a label property for the text labels. var data = [ {data: [[0,22.4]], label: "Extreme Poverty"}, {data: [[1,77.6]]} ]; With our data structured this way, Flotr2 will automatically identify labels associated with each series. Now when we call the draw() method, we just need to add a title option. Flotr2 will add the title above the graph and create a simple legend identifying the pie portions with our labels. To make the chart a little more engaging, we’ll pose a question in our title. That’s why we’re labeling only one of the areas in the chart: the labeled area answers the question in the title. Flotr.draw(document.getElementById("chart"),data, { title: "How Much of the World Lives on $1.25/Day?", pie: { show: true }, yaxis: { showLabels: false }, xaxis: { showLabels: false }, Graphing Data | 25 grid: { horizontalLines: false, verticalLines: false } }); The chart in Figure 1-14 reveals the data quite clearly. 22.40% 77.60% Extreme Poverty How Much of the World Lives on $1.25/Day? Figure 1-14: Labels and titles can help make a chart engaging. Although pie charts have a bad reputation in the data visualization com- munity, there are some applications for which they are quite effective. They’re not very good at letting users compare multiple values, but as shown in this example, they do provide a nice and easily understandable picture showing the proportion of a single value within a whole. Step 4: Work Around Flotr2 “Bugs” Be sure to refer to Step 9 of “Creating a Basic Bar Chart” on page 14 to see how to work around some “bugs” in the Flotr2 library. Plotting X/Y Data with a Scatter Chart A bar chart is often most effective for visualizing data that consists primarily of a single quantity (such as the number of wins in the bar charts we created earlier). But if we want to explore the relationship between two different quantities, a scat- ter chart can be more effective. Suppose, for example, we wish to visualize the relationship between a country’s health-care spending (one quantity) and its life expectancy (the second quantity). Let’s step through an example to see how to create a scatter chart for that data. 26 | Cha pter 1 Just as in Step 1 of “Creating a Basic Bar Chart” on page 6, we need to include the Flotr2 library in our web page and set aside a
element to contain the chart we’ll construct. Step 1: Define the Data For this example, we’ll use the 2012 report from the Organisation for Eco- nomic Co-operation and Development (OECD; http://www.oecd-ilibrary.org/ social-issues-migration-health/data/oecd-health-statistics_health-data-en). This report includes figures for health-care spending as a percent of gross domestic product, and average life expectancy at birth. (Although the report was released in late 2012, it contains data for 2010.) Here you can see a short excerpt of that data stored in a JavaScript array: var health_data = [ { country: "Australia", spending: 9.1, life: 81.8 }, { country: "Austria", spending: 11.0, life: 80.7 }, { country: "Belgium", spending: 10.5, life: 80.3 }, // Data set continues... Step 2: Format the Data As is often the case, we’ll need to restructure the original data a bit so that it matches the format Flotr2 requires. The JavaScript code for that is shown next. We start with an empty data array and step through the source data. For each element in the source health_data, we extract the data point for our chart and push that data point into the data array. var data = []; for (var i = 0; i < health_data.length; i++) { data.push([ health_data[i].spending, health_data[i].life ]); }; Since Flotr2 doesn’t require jQuery, we’re not using any of the jQuery con- venience functions in this example. But if you’re using jQuery for other reasons in your page, you could, for example, use the .map() function to simplify the code for this restructuring. (In Step 7 of “Selecting Chart Content”on page 55, there’s a detailed example of the jQuery .map() function.) Step 3: Plot the Data Now all we need to do is call the draw() method of the Flotr object to create our chart. For a first attempt, we’ll stick with the default options. Graphing Data | 27 Flotr.draw( document.getElementById("chart"), [{ data: data, points: {show:true} }] ); As you can see, Flotr2 expects at least two parameters. The first is the element in our HTML document in which we want the chart placed, and the second is the data for the chart. The data takes the form of an array. In general, Flotr2 can draw multiple series on the same chart, so that array might have multiple objects. In our case, however, we’re charting only one series, so the array has a single object. That object identifies the data itself, and it tells Flotr2 not to show points instead of lines. Figure 1-15 shows our result. Notice how the points are pressed right up against the edges of the chart. 82.0 80.0 78.0 76.0 7.5 10.0 12.5 15.0 17.5 Figure 1-15: The default scatter chart options don’t provide any margins. Step 4: Adjust the Chart’s Axes The first attempt isn’t too bad, but Flotr2 automatically calculates the ranges for each axis, and its default algorithm usually results in a chart that’s too cramped. Flotr2 does have an autoscale option; if you set it, the library attempts to find sen- sible ranges for the associated axes automatically. Unfortunately, in my experience the ranges Flotr2 suggests rarely improve the default option significantly, so in most cases we’re better off explicitly setting them. Here’s how we do that for our chart: Flotr.draw( document.getElementById("chart"), [{ data: data, 28 | Cha pter 1 points: {show:true} }], { xaxis: {min: 5, max: 20}, yaxis: {min: 70, max: 85} } ); We’ve added a third parameter to the draw() method that contains our options, which in this case are properties for the x- and y-axes. In each case, we’re explicitly setting a minimum and maximum value. By specifying ranges that give the data a little breathing room, we’ve made the chart in Figure 1-16 much easier to read. 85.0 80.0 75.0 70.0 5.0 10.0 15.0 20.0 Figure 1-16: Specifying our own axes makes the chart easier to read. Step 5: Label the Data Our chart so far looks reasonably nice, but it doesn’t tell users what they’re seeing. We need to add some labels to identify the data. A few more options can clarify the chart: Flotr.draw( document.getElementById("chart"), [{ data: data, points: {show:true} }], { title: "Life Expectancy vs. Health-Care Spending", subtitle: "(by country, 2010 OECD data)", xaxis: {min: 5, max: 20, utickDecimals: 0, title: "Spending as Percentage of GDP"}, Graphing Data | 29 yaxis: {min: 70, max: 85, vtickDecimals: 0, title: "Years"} } ); The title and subtitle options give the chart its overall title and subtitle, while the title properties within the xaxis and yaxis options name the labels for those axes. In addition to adding labels, we’ve told Flotr2 to drop the unnecessary decimal point from the x- and y-axis values by changing the tickDecimals property at u and v. The chart in Figure 1-17 looks much better. 85 80 75 70 5 10 15 20 (by country, 2010 OECD data) Years Spending as Percentage of GDP Life Expectancy vs. Health-Care Spending Figure 1-17: Labels and titles clarify the chart’s content. Step 6: Clarify the X-Axis Although our chart has definitely improved since our first attempt, there is still one nagging problem with the data presentation. The x-axis represents a percentage, but the labels for that axis show whole numbers. That discrepancy might cause our users some initial confusion, so let’s get rid of it. Flotr2 allows us to format the axis labels however we want. In this example, we simply wish to add a percentage sym- bol to the value. That’s easy enough: Flotr.draw( document.getElementById("chart"), [{ data: data, points: {show:true} }], { title: "Life Expectancy vs. Health-Care Spending", subtitle: "(by country, 2010 OECD data)", 30 | Cha pter 1 xaxis: {min: 5, max: 20, tickDecimals: 0, title: "Spending as Percentage of GDP", u tickFormatter: function(val) {return val+"%"}}, yaxis: {min: 70, max: 85, tickDecimals: 0, title: "Years"} } ); The trick is the tickFormatter property of the xaxis options at u in the preced- ing code. That property specifies a function. When tickFormatter is present, Flotr2 doesn’t draw the labels automatically. Instead, at each point where it would draw a label, it calls our function. The parameter passed to the function is the numeric value for the label. Flotr2 expects the function to return a string that it will use as the label. In our case we’re simply adding a percent sign after the value. In Figure 1-18, with the addition of the percentage values labeling the hori- zontal axis, we have a chart that presents the data clearly. 85 80 75 70 5% 10% 15% 20% (by country, 2010 OECD data) Years Spending as Percentage of GDP Life Expectancy vs. Health-Care Spending Figure 1-18: Formatting the axis labels clarifies the content. The scatter chart excels at revealing relationships between two different variables. In this example, we can see how life expectancy relates to health-care spending. In aggregate, more spending yields longer life. Step 7: Answer Users’ Questions Now that our chart successfully presents the data, we can start to look more care- fully at the visualization from our users’ perspective. We especially want to antici- pate any questions that users might have and try to answer them directly on the chart. There are at least three questions that emerge in the chart as it now stands: 1. What countries are shown? 2. Are there any regional differences? 3. What’s that data point way over on the right? Graphing Data | 31 One way to answer those questions would be to add mouseovers (or tool tips) to each data point. But we’re not going to use that approach in this example for a couple of reasons. First (and most obviously), interactive visualizations are the subject of Chapter 2; this chapter considers only static charts and graphs. Secondly, mouseovers and tool tips are ineffective for users accessing our site on a touch device, such as a smartphone or tablet. If we required users to have a mouse to fully understand our visualization, we might be neglecting a significant (and rapidly grow- ing) number of them. Our approach to this problem will be to divide our data into multiple series so that we can color and label each independently. Here’s the first step in breaking the data into regions: var pacific_data = [ { country: "Australia", spending: 9.1, life: 81.8 }, { country: "New Zealand", spending: 10.1, life: 81.0 }, ]; var europe_data = [ { country: "Austria", spending: 11.0, life: 80.7 }, { country: "Belgium", spending: 10.5, life: 80.3 }, { country: "Czech Republic", spending: 7.5, life: 77.7 }, // Data set continues... var us_data = [ { country: "United States", spending: 17.6, life: 78.7 } ]; Here, we’re giving the United States its own series, separate from the Americas series. That’s because the United States is the outlier data point on the far right of the chart. Our users probably want to know the specific country for that point, not just its region. For the other countries, a region alone is probably enough identi- fication. As before, we need to restructure these arrays into Flotr2’s format. The code is the same as in Step 4; we’re just repeating it for each data set. var pacific=[], europe=[], americas=[], mideast=[], asia=[], us=[]; for (i = 0; i < pacific_data.length; i++) { pacific.push([ pacific_data[i].spending, pacific_data[i].life ]); } for (i = 0; i < europe_data.length; i++) { europe.push([ europe_data[i].spending, europe_data[i].life ]); } // Code continues... Once we’ve separated the countries, we can pass their data to Flotr2 as distinct series. Here we see why Flotr2 expects arrays as its data parameter. Each series is a separate object in the array. 32 | Cha pter 1 Flotr.draw( document.getElementById("chart"), [ { data: pacific, points: {show:true} }, { data: europe, points: {show:true} }, { data: americas, points: {show:true} }, { data: mideast, points: {show:true} }, { data: asia, points: {show:true} }, { data: us, points: {show:true} } ],{ title: "Life Expectancy vs. Health-Care Spending", subtitle: "(by country, 2010 OECD data)", xaxis: {min: 5, max: 20, tickDecimals: 0, title: "Spending as Percentage of GDP", tickFormatter: function(val) {return val+"%"}}, yaxis: {min: 70, max: 85, tickDecimals: 0, title: "Years"} } ); With the countries in different data series based on regions, Flotr2 now col- ors the regions distinctly, as shown in Figure 1-19. 85 80 75 70 5% 10% 15% 20% (by country, 2010 OECD data) Years Spending as Percentage of GDP Life Expectancy vs. Health-Care Spending Figure 1-19: Splitting the data into multiple data sets lets us assign different colors to each. For the final enhancement, we add a legend to the chart identifying the regions. Graphing Data | 33 Flotr.draw( document.getElementById("chart"), [ { data: pacific, label: "Pacific", points: {show:true} }, { data: europe, label: "Europe", points: {show:true} }, { data: americas, label: "Americas", points: {show:true} }, { data: mideast, label: "Middle East", points: {show:true} }, { data: asia, label: "Asia", points: {show:true} }, { data: us, label: "United States", points: {show:true} } ],{ title: "Life Expectancy vs. Health-Care Spending (2010 OECD data)", u xaxis: {min: 5, max: 25, tickDecimals: 0, title: "Spending as Percentage of GDP", tickFormatter: function(val) {return val+"%"}}, yaxis: {min: 70, max: 85, tickDecimals: 0, title: "Years"}, v legend: {position: "ne"} } ); In order to make room for the legend, we increase the range of the x-axis at u and position the legend in the northeast quadrant at v. This addition gives us the final chart shown in Figure 1-20. 85 80 75 70 5% 10% 15% 20% 25% Years Spending as Percentage of GDP Life Expectancy vs. Health-Care Spending (2010 OECD data) Asia Europe Middle East Pacific Americas United States Figure 1-20: Adding a legend completes the chart. Step 8: Work Around Flotr2 “Bugs” Be sure to refer to Step 9 of “Creating a Basic Bar Chart” on page 14 to see how to work around some “bugs” in the Flotr2 library. 34 | Cha pter 1 Adding Magnitudes to X/Y Data with a Bubble Chart Traditional scatter charts, like those described in the previous example, show the relationship between two values: the x-axis and the y-axis. Sometimes, however, two values are not adequate for the data we want to visualize. If we need to visual- ize three variables, we could use a scatter plot framework for two of the variables and then vary the size of the points according to the third variable. The resulting chart is a bubble chart. Using bubble charts effectively requires some caution, though. As we saw earlier with pie charts, humans are not very good at accurately judging the relative areas of nonrectangular shapes, so bubble charts don’t lend themselves to precise comparisons of the bubble size. But if your third variable conveys only the general sense of a quantity rather than an accurate measurement, a bubble chart may be appropriate. For this example we’ll use a bubble chart to visualize the path of Hurricane Katrina in 2005. Our x- and y-values will represent position (latitude and longitude), and we’ll ensure our users can interpret those values very accurately. For the third value—the bubble area—we’ll use the storm’s sustained wind speed. Since wind speed is only a general value anyway (as the wind gusts and subsides), a general impression is sufficient. Just as in Step 1 of “Creating a Basic Bar Chart” on page 6, we need to include the Flotr2 library in our web page and set aside a
element to contain the chart we’ll construct. Step 1: Define the Data We’ll start our example with data taken from Hurricane Katrina observations by United States National Oceanic and Atmospheric Administration (NOAA). The data includes the latitude and longitude of the observation and the sustained wind speed in miles per hour. var katrina = [ { north: 23.2, west: 75.5, wind: 35 }, { north: 24.0, west: 76.4, wind: 35 }, { north: 25.2, west: 77.0, wind: 45 }, // Data set continues... For the bubble chart, Flotr2 needs each data point to be an array rather than an object, so let’s build a simple function to convert the source data into that format. To make the function more general, we can use an optional parameter to specify a filter function. And while we’re extracting data points, we can reverse the sign of the longitude so that west to east displays left to right. Graphing Data | 35 function get_points(source_array, filter_function) { u var result = []; for (var i=0; i= 74) && (obs.wind < 95); }); To have Flotr2 assign different colors to different strengths, we divide the data into multiple series with the following code. Each series gets its own color. In addition to the five hurricane categories, we’ve also parsed out the points for tropical storm and tropical depression strength. Flotr.draw( document.getElementById("chart"), [ { data: get_points(katrina, function(obs) { return (obs.wind < 39); }), color: "#74add1", bubbles: {show:true, baseRadius: 0.3, lineWidth: 1} },{ // Options continue... },{ data: get_points(katrina, function(obs) { return (obs.wind >= 157); }), color: "#d73027", label: "Category 5", bubbles: {show:true, baseRadius: 0.3, lineWidth: 1} } ],{ grid: { backgroundImage: "img/gulf.png", horizontalLines: false, verticalLines: false }, yaxis: {showLabels: false, min: 23.607, max: 33.657}, xaxis: {showLabels: false, min: -94.298, max: -77.586}, legend: {position: "sw"} } ); We’ve also added labels for the hurricane categories and placed a legend in the lower left of the chart, as you can see in Figure 1-24. 40 | Cha pter 1 Figure 1-24: Different colors can indicate wind strength. Step 6: Adjust the Legend Styles By default, Flotr2 seems to prefer all elements as large as possible. The legend in Figure 1-24 is a good example: it looks cramped and unattractive. Fortunately, the fix is rather simple: we simply add some CSS styles to give the legend padding. We can also set the legend’s background color explicitly rather than relying on Flotr2’s manipulation of opacity. .flotr-legend { padding: 5px; background-color: #ececec; } To prevent Flotr2 from creating its own background for the legend, set the opacity to 0. Flotr.draw( document.getElementById("chart") // Additional options... legend: {position: "sw", backgroundOpacity: 0,}, // Additional options... With that final tweak, we have the finished product of Figure 1-25. We don’t want to use the Flotr2 options to specify a title, because Flotr2 will shrink the chart area by an unpredictable amount (since we cannot predict the font sizing in the users’ browsers). That would distort our latitude transformation. Of course, it’s easy enough to use HTML to provide the title. Graphing Data | 41 Figure 1-25: A bubble chart shows a third dimension (wind speed), as well as position. The bubble chart adds another dimension to the two-dimensional scatter chart. In fact, as in our example, it can add two further dimensions. The example uses bubble size to represent wind speed and color to indicate the hurricane’s classification. Both of these additional values require care, however. Humans are not good at comparing two-dimensional areas, nor can they easily compare rela- tive shades or colors. We should never use the extra bubble chart dimensions to convey critical data or precise quantities. Rather, they work best in examples such as this—neither the exact wind speed nor the specific classification need be as precise as the location. Few people can tell the difference between 100- and 110-mile-per-hour winds, but they certainly know the difference between New Orleans and Dallas. Step 7: Work Around Flotr2 “Bugs” Be sure to refer to Step 9 of “Creating a Basic Bar Chart” on page 14 to see how to work around some “bugs” in the Flotr2 library. Displaying Multidimensional Data with a Radar Chart If you have data with many dimensions, a radar chart may be the most effective way to visualize it. Radar charts are not as common as other charts, though, and their unfamiliarity makes them a little harder for users to interpret. If you design a radar chart, be careful not to increase that burden. 42 | Cha pter 1 Radar charts are most effective when your data has several characteristics: >> You don’t have too many data points to show. Half a dozen data points is about the maximum that a radar chart can accommodate. >> The data points have multiple dimensions. With two or even three dimen- sions to your data, you would probably be better off with a more tradi- tional chart type. Radar charts come into play with data of four or more dimensions. >> Each data dimension is a scale that can at least be ranked (from good to bad, say), if not assigned a number outright. Radar charts don’t work well with data dimensions that are merely arbitrary categories (such as political party or nationality). A classic use for radar charts is analyzing the performance of players on a sports team. Consider, for example, the 2012 starting lineup of Miami Heat, a team in the National Basketball Association (NBA). There are only five data points (the five players). There are multiple dimensions—points, assists, rebounds, blocks, steals, and so on—and each of those dimensions has a natural numeric value. Table 1-1 shows the players’ 2011–2012 season averages per game, as well as the team totals (which include the contributions of nonstarters). Table 1-1: Miami Heat 2011–2012 Season Player Points Rebounds Assists Steals Blocks Chris Bosh 17. 2 7.9 1.6 0.8 0.8 Shane Battier 5.4 2.6 1.2 1.0 0.5 LeBron James 28.0 8.4 6.1 1.9 0.8 Dwyane Wade 22.3 5.0 4.5 1.7 1.3 Mario Chalmers 10.2 2.9 3.6 1.4 0.2 Team total 98.2 41.3 19.3 8.5 5.3 Just as in Step 1 of “Creating a Basic Bar Chart” on page 6, we need to include the Flotr2 library in our web page and set aside a
element to contain the chart we’ll construct. Step 1: Define the Data We’ll start with a typical JavaScript expression of the team’s statistics. For our example we’ll start with an array of objects corresponding to each starter, and a separate object for the entire team. var players = [ { player: "Chris Bosh", points: 17.2, rebounds: 7.9, assists: 1.6, steals: 0.8, blocks: 0.8 }, { player: "Shane Battier", points: 5.4, rebounds: 2.6, assists: 1.2, steals: 1.0, blocks: 0.5 }, Graphing Data | 43 { player: "LeBron James", points: 28.0, rebounds: 8.4, assists: 6.1, steals: 1.9, blocks: 0.8 }, { player: "Dwyane Wade", points: 22.3, rebounds: 5.0, assists: 4.5, steals: 1.7, blocks: 1.3 }, { player: "Mario Chalmers", points: 10.2, rebounds: 2.9, assists: 3.6, steals: 1.4, blocks: 0.2 } ]; var team = { points: 98.2, rebounds: 41.3, assists: 19.3, steals: 8.5, blocks: 5.3 }; For an effective radar plot, we need to normalize all the values to a com- mon scale. In this example, let’s translate raw statistics into team percentage. For example, instead of visualizing LeBron James’s scoring as 28.0, we’ll show it as 29 percent (28.0/98.2). There are a couple of functions we can use to convert the raw statistics into an object to chart. The first function returns the statistics object for a single player. It simply searches through the players array looking for that player’s name. The second function steps through each statistic in the team object, gets the cor- responding statistic for the named player, and normalizes the value. The returned object will have a label property equal to the player’s name, and an array of nor- malized statistics for that player. var get_player = function(name) { for (var i=0; i> How to let users select the content for a chart >> How to let users zoom into a chart to see more details >> How to make a chart respond to user mouse movements >> How to dynamically get data for a chart using an AJAX service Selecting Chart Content If you’re presenting data to a large audience on the Web, you may find that differ- ent users are especially interested in different aspects of your data. With global GDP data, for example, we might expect that individual users would be most inter- ested in the data for their own region of the world. If we can anticipate inquiries like this from the user, we can construct our visualization to answer them. In this example, we’re targeting a worldwide audience, and we want to show data for all regions. To accommodate individual users, however, we can make the regions selectable; that is, users will be able to show or hide the data from each region. If some users don’t care about data for particular regions, they can simply choose not to show it. Interactive visualizations usually require more thought than simple, static charts. Not only must the original presentation of data be effective, but the way the user controls the presentation and the way the presentation responds must be effective as well. It usually helps to consider each of those requirements explicitly. 1. Make sure the initial, static presentation shows the data effectively. 2. Add any user controls to the page and ensure they make sense for the visualization. 3. Add the code that makes the controls work. We’ll tackle each of these phases in the following example. Making Charts Interactive | 49 Step 1: Include the Required JavaScript Libraries Since we’re using the Flot library to create the chart, we need to include that library in our web pages. And since Flot requires jQuery, we’ll include that in our pages as well. Fortunately, both jQuery and Flot are popular libraries, and they are available on public content distribution networks (CDNs). That gives you the option of loading both from a CDN instead of hosting them on your own site. There are several advantages to relying on a CDN: Better performance  If the user has previously visited other websites that retrieved the libraries from the same CDN, then the libraries may already exist in the browser’s local cache. In that case the browser simply retrieves them from the cache, avoiding the delay of additional network requests. (See the second disadvantage in the next list for a different view on performance.) Lower cost  One way or another, the cost of your site is likely based on how much bandwidth you use. If your users are able to retrieve libraries from a CDN, then the bandwidth required to service their requests won’t count against your site. Of course there are also disadvantages to CDNs as well. Loss of control  If the CDN goes down, then the libraries your page needs won’t be available. That puts your site’s functionality at the mercy of the CDN. There are approaches to mitigate such failures. You can try to retrieve from the CDN and fall back to your own hosted copy if the CDN request fails. Implementing such a fallback is tricky, though, and it could introduce errors in your code. Lack of flexibility  With CDN-hosted libraries, you’re generally stuck with a limited set of options. For example, in this case we need both the jQuery and Flot libraries. CDNs provide those libraries only as distinct files, so to get both we’ll need two network requests. If we host the libraries ourselves, on the other hand, we can combine them into a single file and cut the required number of requests in half. For high-latency networks (such as mobile net- works), the number of requests may be the biggest factor in determining the performance of your web page. There isn’t a clear-cut answer for all cases, so you’ll have to weigh the options against your own requirements. For this example (and the others in this chapter), we’ll use the CloudFlare CDN. In addition to the jQuery library, Flot relies on the HTML canvas feature. To support IE8 and earlier, we'll include the excanvas.min.js library in our pages and make sure that only IE8 and earlier will load it, just like we did for our bar chart in Chapter 1. Also, since excanvas isn’t available on a public CDN, we’ll have to host it on our own server. Here’s the skeleton to start with: 50 | Cha pter 2 As you can see, we’re including the JavaScript libraries at the end of the document. This approach lets the browser load the document’s entire HTML markup and begin laying out the page while it waits for the server to provide the JavaScript libraries. Step 2: Set Aside a
Element to Hold the Chart Within our document, we need to create a
element to contain the chart we’ll construct. This element must have an explicit height and width, or Flot won’t be able to construct the chart. We can indicate the element’s size in a CSS style sheet, or we can place it directly on the element itself. Here’s how the document might look with the latter approach. u
Note at u that we’ve given the
an explicit id so we can reference it later. Step 3: Prepare the Data In later examples we’ll see how to get the data directly from the World Bank’s web service, but for this example, let’s keep things simple and assume we have the data already downloaded and formatted for JavaScript. (For brevity, only excerpts are shown here. The book’s source code includes the full data set.) Making Charts Interactive | 51 var eas = [[1960,0.1558],[1961,0.1547],[1962,0.1574], // Data continues... var ecs = [[1960,0.4421],[1961,0.4706],[1962,0.5145], // Data continues... var lcn = [[1960,0.0811],[1961,0.0860],[1962,0.0990], // Data continues... var mea = [[1968,0.0383],[1969,0.0426],[1970,0.0471], // Data continues... var sas = [[1960,0.0478],[1961,0.0383],[1962,0.0389], // Data continues... var ssf = [[1960,0.0297],[1961,0.0308],[1962,0.0334], // Data continues... This data includes the historical GDP (in current US dollars) for major regions of the world, from 1960 to 2011. The names of the variables are the World Bank region codes. QQ Note: At the time of this writing, World Bank data for North America was temporarily unavailable. Step 4: Draw the Chart Before we add any interactivity, let’s check out the chart itself. The Flot library pro- vides a simple function call to create a static graph. We call the jQuery extension plot and pass it two parameters. The first parameter identifies the HTML element that should contain the chart, and the second parameter provides the data as an array of data sets. In this case, we pass in an array with the series we defined earlier for each region. $(function () { $.plot($("#chart"), [ eas, ecs, lcn, mea, sas, ssf ]); }); Figure 2-1 shows the resulting chart. 25 20 15 10 5 0 1960 1965 1970 1975 1980 1985 1990 1995 2000 2005 2010 Figure 2-1: Flot can show a static line chart well with just default options. 52 | Cha pter 2 It looks like we’ve done a good job of capturing and presenting the data statically, so we can move on to the next phase. Step 5: Add the Controls Now that we have a chart we’re happy with, we can add the HTML controls to interact with it. For this example, our goal is fairly simple: our users should be able to pick which regions appear on the graph. We’ll give them that option with a set of checkboxes, one for each region. Here’s the markup to include the checkboxes. You may be surprised to see that we’ve placed the controls inside the