HTML5 Graphing and Data Visualization Cookbook

This is not a beginner\'s book but is intended for JavaScript developers who want to expand their skills into graphing, canvas, object-oriented programming in practice, third-party modification, and overall data strategy and data visualization.

Ben Fhala

344 Pages

23910 Reads



PDF Format

3.58 MB

HTML Learning

Download PDF format

  • Ben Fhala   
  • 344 Pages   
  • 26 Feb 2015
  • Page - 1

    read more..

  • Page - 2

    HTML5 Graphing and Data Visualization Cookbook Learn how to create interactive HTML5 charts and graphs with canvas, JavaScript, and open source tools Ben Fhala BIRMINGHAM - MUMBAI read more..

  • Page - 3

    HTML5 Graphing and Data Visualization Cookbook Copyright © 2012 Packt Publishing All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been read more..

  • Page - 4

    Credits Author Ben Fhala Reviewer Chris Valleskey Acquisition Editor Joanna Finchen Lead Technical Editor Kedar Bhat Technical Editors Prasad Dalvi Joyslita D'souza Ankita Meshram Copy Editors Brandt D'Mello Insiya Morbiwala Aditya Nair Laxmi Subramanian Project Coordinator Michelle Quadros Proofreader Chris Smith Indexer Hemangini Bari Graphics Valentina Dsilva Production Coordinator Nilesh R. Mohite Cover Work read more..

  • Page - 5

    About the Author Ben Fhala discovered his passion for data visualization six years ago while he was working at Parsons in New York, in their data visualization department PIIM. He is the owner of the online video training school,, and an Adobe ACP. He enjoys spending most of his time learning and teaching, and has a love for visual programming and read more..

  • Page - 6

    About the Reviewer Chris Valleskey is a young and creative thinker who currently lives in Chicago, Illinois. He started freelancing at the age of 17 and continued this role throughout college until graduating in 2011 with a Bachelor of Arts in Graphic Design and Philosophy. Although he has a normal job in the city, he enjoys spending time with his close friends as read more..

  • Page - 7 You might want to visit your book. Did you know that Packt offers eBook versions of every book published, with PDF and ePub and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at for more details. At, you can also read a collection of read more..

  • Page - 8

    Preface 1 Chapter 1: Drawing Shapes in Canvas 7 Introduction 7 Graphics with 2D canvas 8 Starting from basic shapes 14 Creating shapes using paths 19 Creating complex shapes 24 Adding more vertices 31 Overlapping shapes to create other shapes 35 Chapter 2: Advanced Drawing in Canvas 37 Introduction 37 Drawing arcs 37 Drawing curves with a control point 40 Creating a Bezier curve read more..

  • Page - 9

    ii Table of Contents Chapter 4: Let's Curve Things Up 105 Introduction 105 Building a bubble chart 105 Creating a pie chart 114 Using a doughnut chart to show relationships 119 Leveraging a radar 123 Structuring a tree chart 129 Chapter 5: Getting Out of the Box 137 Introduction 137 Revisiting lines: making the line chart interactive 145 Tree mapping and recursiveness 150 Adding read more..

  • Page - 10

    iii Table of Contents Adding markers and events 272 Customizing controls and overlapping maps 275 Redesigning maps using styles 280 Chapter 10: Maps in Action 287 Introduction 287 Connecting a Twitter feed to a Google map 288 Building an advanced interactive marker 293 Adding multiple tweets into an InfoWindow bubble 297 Customizing the look and feel of markers 303 Index 325 read more..

  • Page - 11

    read more..

  • Page - 12

    of the Internet in the early nineties and until today, more and more data has been exposed digital media and news, and social media to private sector information, user information, and so on. With the overload of data on the Web it's easy to overlook information, as it's much harder to read and analyze in data format. That's where we come in. Our goal in read more..

  • Page - 13

    Preface 2 By the end of this book, you will have a strong working foundation in data visualization, graphing, data strategy, and HTML5 Canvas. What this book covers Chapter 1, Drawing Shapes in Canvas, introduces you to working with canvas. We will spend the majority of our time working with canvas when creating our charts. In this chapter, we will focus on getting read more..

  • Page - 14

    Preface 3 Chapter 9, Using Google Maps, explores some of the features available on Google Maps to get us ready to work with mapping in general. Mapping on its own isn't data visualization, but after we establish our base understanding of how to work with maps, we will have a very stable background that will enable us to create many cutting-edge, cool read more..

  • Page - 15

    Preface 4 When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold: map.mapTypes.set('grayStyle', grayStyle); map.setMapTypeId('grayStyle'); New terms and important words are shown in bold. Words that you see on the screen, in menus or dialog boxes for example, appear in the text like this: "Select the Ser read more..

  • Page - 16

    Preface 5 Errata Although we have taken every care to ensure the accuracy of our content, mistakes do code—we would be grateful if you would report this to us. By doing so, you can save other errata, please report them by visiting, selecting your book, clicking on the errata submission form link, and entering the details of read more..

  • Page - 17

    read more..

  • Page - 18

    1 Drawing Shapes in Canvas In this chapter we will cover: Graphics with 2D canvas Starting from basic shapes Creating shapes using paths Creating complex shapes Adding more vertices Overlapping shapes to create other shapes Introduction This chapter's main focus is to make a breakthrough into working in canvas. We will spend the majority of our time read more..

  • Page - 19

    Drawing Shapes in Canvas 8 Graphics with 2D canvas Canvas is the primary and most thrilling addition to HTML. It's the buzz of the industry, so let's start there. We will revisit canvas again in the later chapters. In this recipe, we will learn how to draw dynamically using canvas, and create an array of colorful circles that will update once every second. How read more..

  • Page - 20

    Chapter 1 9 3. 01.01.canvas.js into the HTML document (we will <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <script src="01.01.canvas.js"></script> <title>Canvas Example</title> </head> 4. Add an onLoad listener and trigger the function init when the document loads: <!DOCTYPE html> <html> read more..

  • Page - 21

    Drawing Shapes in Canvas 10 9. Access the canvas layer in the HTML document and change its width and height: var myCanvas = document.getElementById("myCanvas"); myCanvas.width = width; myCanvas.height = height; 10. Get the 2D context of the canvas: var context = myCanvas.getContext("2d"); 11. the full visible area of the canvas: context.fillStyle = read more..

  • Page - 22

    Chapter 1 11 Let's break down the JavaScript portion and understand the reason behind doing this. The init function: function init(){ updateCanvas(); } Our init function immediately calls the updateCanvas function. This is done so that later we can refresh and call updateCanvas again. In the updateCanvas function, we start by getting the current width of the browser read more..

  • Page - 23

    Drawing Shapes in Canvas 12 the centres of each circle we create, or in our case the diameter of our circle. By setting it up as two times the radius we space out our circles exactly one after the other. var widthCount = parseInt(width/gaps); var heightCount = parseInt(height/gaps); var aColors=["#43A9D1","#EFA63B","#EF7625","#5E4130"]; var aColorsLength read more..

  • Page - 24

    Chapter 1 13 The x and y for loops we need to add a buffer of an extra radius to push our content into the screen. We need and to the bottom by an extra radius. context.fill(); Last but not least, we need to call the fill() its color. There's more... Let's make our element refresh once a second; to do that all we need to do is add two read more..

  • Page - 25

    Drawing Shapes in Canvas 14 At this stage you know how to create a new canvas area and even create a few basic shapes. Getting ready If you followed the Graphics with 2D canvas recipe you already know how to do it. This one is dedicated to our Palauan readers and to the perfect arc (also known as circle). In this recipe we will ignore the HTML part, read more..

  • Page - 26

    Chapter 1 15 How to do it... Add the following code block: var cnvPalau = document.getElementById("palau"); var wid = cnvPalau.width; var hei = cnvPalau.height; var context = cnvPalau.getContext("2d"); context.fillStyle = "#4AADD6"; context.fillRect(0,0,wid,hei); context.fillStyle = "#FFDE00"; read more..

  • Page - 27

    Drawing Shapes in Canvas 16 Let's take a deeper look at how the arc circle with the x and y positions. The canvas tag follows the standard Cartesian coordinates: (0, 0) is at the top-left (x grows to the right and y grows towards the bottom). context.arc(x, y, radius, startingAngle, endingAngle, ccw); In our example, we decided to position the circle slightly read more..

  • Page - 28

    Chapter 1 17 Getting ready As in the previous recipe, we will be skipping the HTML part and will jump right into the JavaScript portion of drawing in the canvas. For a detailed explanation of the steps involved in closely and try to come up with an attack plan on the How to do it... this but the following is our attempt: 1. var canvas = read more..

  • Page - 29

    Drawing Shapes in Canvas 18 move on let's look deeper into how this works. How it works... Notice the addition of an offset. This is done because lineWidth grows in both directions from the actual point in the center of the line. In other words, a line with the width of 20 pixels that is drawn from (0, 0) to (0, height) would only have 10 pixels visible read more..

  • Page - 30

    Chapter 1 19 If you run the application now you will be really disappointed. We did exactly what we learned previously but it's not working as expected. that well because it got confused by all the lines we created earlier. To avoid this, we should tell the canvas when we are starting a new drawing and when we are ending it. To do so we can call read more..

  • Page - 31

    Drawing Shapes in Canvas 20 Getting ready Let's start from the simplest shape that isn't included in the basic shapes library: a triangle. So if you're ready let's get started... How to do it... context.fillStyle = color; context.beginPath(); context.moveTo(x1,y1); context.lineTo(x2,y2); context.lineTo(x3,y3); context.lineTo(x1,y1); context.closePath(); context.fill(); The code here with points x1,y1 read more..

  • Page - 32

    Chapter 1 21 OK, so you get the idea of the triangle. Let's see this in action. I've extracted this code and put var canvas = document.getElementById("guyana"); var wid = canvas.width; var hei = canvas.height; var context = canvas.getContext("2d"); context.fillStyle = "#009E49"; context.fillRect(0,0,wid,hei); fillTriangle(context, 0,0, read more..

  • Page - 33

    Drawing Shapes in Canvas 22 There's more... Don't let triangles be your most complex shape, as you can create any number of pointed of Bahrain. Try to locate the new logic before we break it down and explain it. var canvas = document.getElementById("bahrain"); var wid = canvas.width; var hei = canvas.height; var context = canvas.getContext("2d"); read more..

  • Page - 34

    Chapter 1 23 Let's break down this zigzag and understand what's going on here. After starting up with our normal setting up of a canvas element, we jump right into creating our shape. We start by drawing a red background, leaving us to create a shape that will have the white area. It's very much like a rectangle except that it has zigzags in it. In read more..

  • Page - 35

    Drawing Shapes in Canvas 24 We draw the zigzags in the for loop itself. To do so we need to use the following two lines of code in each round: context.lineTo(baseX +25 , (i+.5)*zagHeight); context.lineTo(baseX , (i+1)*zagHeight); step away from the current position and expand the line out half way through the height of the triangle, and to the extreme point read more..

  • Page - 36

    Chapter 1 25 easy and fun to work with. Let's break them down here in a more programming-for-drawing type of way. The most basic idea is that you have a triangle that has a 90 degree angle. You have some information about this triangle, and that's all you need to be able to start working with sine and cosine. Once you know that you have a 90 degree read more..

  • Page - 37

    Drawing Shapes in Canvas 26 How to do it... init function. 1. Create our basic canvas variables: var canvas = document.getElementById("israel"); var wid = canvas.width; var hei = canvas.height; var context = canvas.getContext("2d"); 2. Math.cos and Math.sin expect a radian value and not a degree value (radian is one degree measured in radians): var radian = read more..

  • Page - 38

    Chapter 1 27 baseX+ Math.sin(radian*240+tilt) * radius, baseY + Math.cos(radian*240+tilt) * radius, null,"#0040C0"); 9. : context.lineWidth=stripHeight; context.beginPath(); context.moveTo(0,stripHeight); context.lineTo(wid,stripHeight); context.moveTo(0,hei- stripHeight); context.lineTo(wid,hei- stripHeight); context.closePath(); context.stroke(); 10. Create the createTriangle function: function read more..

  • Page - 39

    Drawing Shapes in Canvas 28 context.beginPath(); context.strokeStyle = "#ff0000"; context.lineWidth=6; context.moveTo(Math.sin(0) * 30 + wid / 2, Math.cos(0) * 30 + hei/2); context.lineTo(Math.sin(rad*120) * 30 + wid / 2, Math.cos(rad*120) * 30 + hei/2); context.stroke(); The following is the output the code will generate: Although a circle, in our human-friendly head, is a read more..

  • Page - 40

    Chapter 1 29 Let's break down the most complex line: context.lineTo(Math.sin(rad*120) * 30 + wid / 2, Math.cos(rad*120) * 30 + hei/2); As Math.sin and Math.cos return a value for a radius of 1, we will multiply any value returned by the radius of our circle (in this case 30). In the parameters of Math.sin and Math.cos, we will provide the exact same read more..

  • Page - 41

    Drawing Shapes in Canvas 30 There's more... createTriangle function twice to create the full Star of David shape. Let's take a deeper look at the logic here by looking at the second triangle (the one that is turned upside down): createTriangle(context, baseX+ Math.sin(tilt) * radius, baseY + Math.cos(tilt) * radius, baseX+ Math.sin(radian*120+tilt) * radius, read more..

  • Page - 42

    Chapter 1 31 Adding more vertices this recipe, we will of points We will use the same key concept we discovered in the previous recipe by taking advantage of a virtual circle to calculate positions, this time with only two virtual circles. In this recipe, we enable us to create stars. Getting ready Please continue working on the sample from the previous read more..

  • Page - 43

    Drawing Shapes in Canvas 32 2. Fill the background color of canvas: context.fillStyle = "#4189DD"; context.fillRect(0,0,wid,hei); 3. Draw the star by calling the createStar function: createStar(context,wid/2,hei/2,7,20,5,"#ffffff",null,0); 4. Create the createStart function: function createStar(context,baseX,baseY, innerRadius,outerRadius, read more..

  • Page - 44

    Chapter 1 33 9. context.closePath(); if(fillColor){ context.fillStyle = fillColor; context.fill(); } if(strokeColor){ context.strokeStyle = strokeColor; context.stroke(); } } under your belt. How it works... Let's start by understanding what the function we are going to create expects. The idea is simple, to create a star we want read more..

  • Page - 45

    Drawing Shapes in Canvas 34 radianStepper. The goal of the radian stepper is to simplify calculations in our loop. We divided 360 degrees by the number of points our triangle will have. We divided the value by 2, as we will have two times the number of points as lines. Last but not least, we want to convert this value into radians so we are read more..

  • Page - 46

    Chapter 1 35 Overlapping shapes to create other shapes in general that can be created by combining the using subtraction to create more in-depth shapes. Getting ready The previous recipe is our starting point in this recipe. From here, we will continue working to create more advanced shapes that are built out of two shapes when combined. As such, we will be read more..

  • Page - 47

    Drawing Shapes in Canvas 36 2. Fill the rectangle canvas area: context.fillStyle = "#E30A17"; context.fillRect(0,0,wid,hei); 3. Create a full circle: context.fillStyle = "#ffffff"; context.beginPath(); context.arc(wid / 2 - 23, hei / 2, 23, 0, 2 * Math.PI, false); context.closePath(); context.fill(); 4. Change the color of canvas hides part of the last circle that was read more..

  • Page - 48

    Advanced Drawing in Canvas Drawing arcs Drawing curves with a control point Creating a Bezier curve Integrating images into our art Drawing with text Understanding pixel manipulation Introduction This is the last chapter where we will dig deep into canvas as the remaining chapters will focus on building charts and interactivity. In this chapter, we will read more..

  • Page - 49

    Advanced Drawing in Canvas 38 Getting ready If you recall in Chapter 1, Drawing Shapes in Canvas method to create perfect circles. The arc method is much more than just that. We can actually create any partial curve in a circular shape. If you don't recall drawing circles, I strongly encourage you to scan through Chapter 1, Drawing Shapes in Canvas again, and read more..

  • Page - 50

    Chapter 2 39 8. Close the shape by drawing a line back to the starting point of our shape: context.lineTo(wid/2,hei/2); 9. context.closePath(); context.fill(); You have just created a PacMan. How to do it... advantage and create a pie-type shape, known as PacMan (you can see how this can be very useful when we get into creating the pie graph). Very read more..

  • Page - 51

    Advanced Drawing in Canvas 40 Drawing curves with a control point If the world was just two points with a perfect arc this would be the end of the book, but alas or lucky for us, there are still many more complex shapes to learn and explore. There are many curves that are not perfectly aligned curves. Till now all the curves that we created were part of read more..

  • Page - 52

    Chapter 2 41 2. canvas with a solid color and after that begin a new shape by triggering the beginPath method: var context = canvas.getContext("2d"); context.fillStyle = "#dfdfdf"; context.fillRect(0,0,wid,hei); context.beginPath(); 3. context.lineWidth = 1; context.strokeStyle = "#000000"; // line color context.fillStyle = "#ffffff"; 4. Move read more..

  • Page - 53

    Advanced Drawing in Canvas 42 In our sample, we create a contained shape—the starting point to create an eye. Play with the controller to see how it affects the direction and size of the curve. The thumb rule is that the closer to the vertical line the less steep the curve will be, and the further away it is from the center point the more curved read more..

  • Page - 54

    Chapter 2 43 Getting ready This recipe is How it works... section. So if you are new to curves, I strongly encourage you to start learning from this How it works... section before implementing it. How to do it... 1. Create the canvas and context: var canvas = document.getElementById("canada"); var wid = canvas.width; var hei = canvas.height; var context = read more..

  • Page - 55

    Advanced Drawing in Canvas 44 5. context.closePath(); context.fill(); Now, you have created why it works or curves right away in the next section. How it works... and create a simpler example. In this short example, we will create an oval shape by using the bezierCurveTo method. context.moveTo(2,hei/2); context.bezierCurveTo(0, 0,wid,0, wid-2,hei/2); read more..

  • Page - 56

    Chapter 2 45 the effects of changing the values of the control points to get a better understanding and It's time to take our most complex drawing style—Bezier curves—and put them to action with something a bit more interesting than an oval. I have a confession: when I decided to create a shape this advanced, I opened up my graphics editor (in my read more..

  • Page - 57

    Advanced Drawing in Canvas 46 I got a shape that was far from what I was looking for. But now I knew that my shape was getting formed in the right direction. What were missing were the curves to connect between the dots. If you look at the preceding diagram again, you will notice that I've placed two blue they would be. I then moved back into canvas read more..

  • Page - 58

    Chapter 2 47 Getting ready img/haiti.png). By the way, when integrating art into canvas it's always best to avoid resizing the image whenever possible via code to preserve the image quality. How to do it... 1. Follow the basic steps that we need to access the canvas. Set the width, height, and the actual context: var canvas = read more..

  • Page - 59

    Advanced Drawing in Canvas 48 4. Create an onLoad function (that will be called when the image is loaded): oIMG.onload = function(){ context.drawImage(this, (wid-this.width)/2, (hei-this.height)/2); }; 5. Set the source of the image: oIMG.src = "img/haiti.png"; Yes, it's that easy to add images into canvas, but let's review more deeply what we have just done. How it read more..

  • Page - 60

    Chapter 2 49 Scaling images We can scale the image by adding two more parameters to the drawImage function, which sets the width and height of our image. Try the following: context.drawImage(this, (wid-this.width)/2, (hei-this.height)/2 , 100, 120); In the previous sample, we are loading the same image but we are forcing a resized image (note that the positions are not read more..

  • Page - 61

    Advanced Drawing in Canvas 50 createStar that we created in an earlier task—drawing a star in the center of the screen—by using the following pattern: createStar(context,wid/2,hei/2,20,50,20,pattern,"#ffffff",20); integrating images when it's just not fun to draw it yourself from scratch—such as detailed country logos. Drawing with text I agree, we've been working on some read more..

  • Page - 62

    Chapter 2 51 How to do it... In this example, we are going to 1. Gain access to the canvas 2D API: var canvas = document.getElementById("textCanvas"); var wid = canvas.width; var hei = canvas.height; var context = canvas.getContext("2d"); 2. var grd = context.createLinearGradient(wid/2, hei/2, wid, hei); grd.addColorStop(0, "#8ED6FF"); read more..

  • Page - 63

    Advanced Drawing in Canvas 52 How it works... Until now, we were stuck with the solid colors. We will now break out of that and move to a new world of gradient colors. Refer to the following code snippet: var grd = context.createLinearGradient(wid/2, hei/2, wid, hei); grd.addColorStop(0, "#8ED6FF"); grd.addColorStop(1, "#004CB3"); var grd = read more..

  • Page - 64

    Chapter 2 53 The only difference here is that our shape is a radial shape. We also want to add the starting radius and ending radius into it. You might be wondering why we need two or even more radii. second before reading the next paragraph. We have a separate control over the radius, mainly to enable us to separate the radius and to enable us read more..

  • Page - 65

    Advanced Drawing in Canvas 54 Notice that we are updating our gradient. Our last gradient was too big for such a small text area. As such, we are drawing a line from around the start of our text going horizontally for 110 pixels. Adding shadows and glows You can add a context.shadowOffsetX = 0; context.shadowOffsetY = 0; context.shadowBlur = 8; read more..

  • Page - 66

    Chapter 2 55 How to do it... Let's get our code working and then break it down to see how it works. Perform the following steps: 1. Create a few helper global variables: var context; var imageData; var pixelData; var pixelLen; var currentLocation=0; var fadeOutImageInterval; 2. Create an init function (for the rest of the steps, all code will be in this function): function read more..

  • Page - 67

    Advanced Drawing in Canvas 56 4. Create a new image: var oIMG = new Image(); 5. Add the onload listener logic: oIMG.onload = function(){ context.drawImage(this, 0,0,this.width,this.height,0,0,wid,hei); imageData = context.getImageData(0, 0, wid, hei); pixelData =; pixelLen = pixelData.length; fadeOutImageInterval = setInterval(fadeOutImage, 25); }; 6. oIMG.src read more..

  • Page - 68

    Chapter 2 57 Your outcome should look something like the following screenshot: How it works... We will skip explaining things that we have already covered in earlier samples such as how to load images and how to work with the drawImage method (covered in the Integrating images into our art recipe discussed earlier in this chapter). var context; var imageData; var read more..

  • Page - 69

    Advanced Drawing in Canvas 58 pixelLen = pixelData.length; fadeOutImageInterval = setInterval(fadeOutImage, 25); }; oIMG.src = "img/slide2.jpg"; We are now taking advantage of storing information in our canvas area and storing it globally. imageData. This variable contains all the information of our canvas. We get this variable by calling the read more..

  • Page - 70

    Chapter 2 59 When we are done with manipulating our data, it's time for us to update our canvas. To do that we just need to send our new data back into our context. The second and third parameters are for the x and y starting point. if(pixelsChanged==0){ clearInterval(fadeOutImageInterval); alert("we are done fading out"); } are less than 100 pixels read more..

  • Page - 71

    Advanced Drawing in Canvas 60 Making an image grayscale To make an image or our canvas grayscale, we need to take all of our colors (red, green, blue) into account and mix them together. After mixing them together, get to a brightness value, which we can then apply to all the pixels. Let's see it in action: function grayScaleImage(){ for (var i = 0; read more..

  • Page - 72

    3 Creating Cartesian- based Graphs In this chapter, we will cover the following topics: Building a bar chart from scratch Spreading data in a scatter chart Building line charts Building a candlestick chart (stock chart) Introduction We can classify them all roughly under Cartesian-based graphs. Altogether this graph style is relatively simple; it opens the door to read more..

  • Page - 73

    Creating Cartesian-based Graphs 62 The simplest chart around is the one that holds only one dimensional data (only one value per type). There are many ways to showcase this type of data but the most popular, logical, and simple way is by creating a simple bar chart. The steps involved in creating this bar chart will be very similar even in very complex charts. read more..

  • Page - 74

    Chapter 3 63 and then drawing in the data. How to do it... we will compare a group of friends and how many cats they each own. We will be performing the following steps: 1. : var data = [{label:"David", value:3, style:"rgba(241, 178, 225, 0.5)"}, {label:"Ben", value:2, read more..

  • Page - 75

    Creating Cartesian-based Graphs 64 3. our chart outlines: var CHART_PADDING = 20; context.font = "12pt Verdana, sans-serif"; context.fillStyle = "#999999"; context.moveTo(CHART_PADDING,CHART_PADDING); context.lineTo(CHART_PADDING,hei-CHART_PADDING); context.lineTo(wid-CHART_PADDING,hei-CHART_PADDING); var stepSize = (hei - CHART_PADDING*2)/10; for(var i=0; i<10; read more..

  • Page - 76

    Chapter 3 65 Let's delve deeper into the sample we created starting from our outline area: context.moveTo(CHART_PADDING,CHART_PADDING); context.lineTo(CHART_PADDING,hei-CHART_PADDING); context.lineTo(wid-CHART_PADDING,hei-CHART_PADDING); In these lines we are creating the L-shaped frame for our data; this is just to help and provide a visual aid. data visually. var stepSize = (hei – read more..

  • Page - 77

    Creating Cartesian-based Graphs 66 Notice that we are resetting the style twice each time the loop runs. If we didn't, we wouldn't get the colors we are hoping to get. We then place our text in the middle of the bar that was created. context.textAlign = "center"; There's more... will need to recreate them from scratch each time. Let's revisit our code read more..

  • Page - 78

    Chapter 3 67 Take a deep look into chartYData object as it enables us to put in as many steps as we maximum values of the overall graph. Before creating the new functions, let's add them into our init function (changes marked in bold). function init(){ var can = document.getElementById("bar"); wid = can.width; hei = can.height; var read more..

  • Page - 79

    Creating Cartesian-based Graphs 68 context.lineTo(CHART_PADDING*1.3,currentY); context.fillText(stepsData[i].label, CHART_PADDING*1.5, currentY+6); } context.stroke(); } Our changes were not many, but with them we turned our function to be much more dynamic than it was before. This time around we are basing the positions on the stepsData objects and the range read more..

  • Page - 80

    Chapter 3 69 This is ideal when the goal is to show a lot of details in a very visual way. Getting ready If you haven't had a chance I recommend you take a peek at it as we are going to base a lot of our work on that while expanding and making it a bit more complex to accommodate two data sets. The regular HTML start-up code can be found in read more..

  • Page - 81

    Creating Cartesian-based Graphs 70 style:"#B1DDF3"}, {label:"Oren", math:70, english:20, art:92, style:"#FFDE89"}, {label:"Barbera", math:90, english:55, art:81, style:"#E3675C"}, read more..

  • Page - 82

    Chapter 3 71 context.fillRect(0,0,wid,hei); context.font = "10pt Verdana, sans-serif"; context.fillStyle = "#999999"; context.moveTo(CHART_PADDING,CHART_PADDING); context.lineTo(CHART_PADDING,hei-CHART_PADDING); context.lineTo(wid-CHART_PADDING,hei-CHART_PADDING); fillChart(context,chartInfo); createDots(context,data); } Not much is new here. The major changes are highlighted. read more..

  • Page - 83

    Creating Cartesian-based Graphs 72 var xData = chartInfo.x; steps = xData.steps; var startX = CHART_PADDING; var endX = wid-CHART_PADDING; var chartWidth = endX-startX; var currentX; rangeLength = xData.max-xData.min; stepSize = rangeLength/steps; context.textAlign = "left"; for(var i=0; i<steps; i++){ currentX = startX + (i/steps) * read more..

  • Page - 84

    Chapter 3 73 for(var i=0; i<data.length;i++){ xPos = CHART_PADDING + (data[i][xDataLabel]-chartInfo.x.min)/ xDataRange * chartWidth; yPos = (hei - CHART_PADDING) -(data[i][yDataLabel]- chartInfo.y.min)/yDataRange * chartHeight; context.fillStyle = data[i].style; context.fillRect(xPos-4 ,yPos-4,8,8); } } y position and the x How it works... We read more..

  • Page - 85

    Creating Cartesian-based Graphs 74 As our focus right now is on the height, we are looking deeper into the y property and for the sake of comfort we will call it yData out what is the actual data range (rangeLength) of this value, which will be our converter number. In other words we want to take a visual space between the points startY and endY and read more..

  • Page - 86

    Chapter 3 75 This is one of my favorite parts of this recipe. We are grabbing the label from our chartInfo object and using that as our ID; this ID will be used to grab information from our data object. If you wish to change the values, all you need to do is switch the labels in the chartInfo object. fillChart function. This time around we want read more..

  • Page - 87

    Creating Cartesian-based Graphs 76 result will always be between 0 and 1. We can use the returned number and multiply it by the actual space in pixels to know exactly where to position our element on the screen. We do so by multiplying the value we got, that is between 0 and 1, by the total available space (in this case, width). Once we know where read more..

  • Page - 88

    Chapter 3 77 Getting ready As usual get your HTML wrapper ready. In this recipe we actually are going to base our changes on the previous recipe, Spreading data in a scatter chart. In our case study for this example, we will create a chart that shows how many new members joined my site,, in 2011 and 2010. I've gathered the information month by read more..

  • Page - 89

    Creating Cartesian-based Graphs 78 2. Update the init function: function init(){ var can = document.getElementById("bar"); wid = can.width; hei = can.height; var context = can.getContext("2d"); context.fillStyle = "#eeeeee"; context.strokeStyle = "#999999"; context.fillRect(0,0,wid,hei); context.font = "10pt Verdana, read more..

  • Page - 90

    Chapter 3 79 i ? context.lineTo(xPos,yPos):context.moveTo(xPos,yPos); } context.stroke(); } 4. Create the formatData function: function formatData(data , labelCopy , style){ newData = []; for(var i=0; i<data.length;i++){ newData.push({ label:(i+1)+labelCopy, users:data[i], months:i+1, read more..

  • Page - 91

    Creating Cartesian-based Graphs 80 A reminder from our previous recipe: this is what our data source looked like: var data = [{label:"David", math:50, english:80, art:92 style:"rgba(241, 178, 225, 0.5)"}, ... ]; x and y values: var chartInfo= { y:{min:0, max:300, read more..

  • Page - 92

    Chapter 3 81 This is one of the most powerful tricks in programing in the tool set. I've met many developers, who change their code instead of is always a way to modify data to make it more easily consumed by your application and it's much easier to dynamically modify data than it is to change your architecture. I didn't change anything in the core logic read more..

  • Page - 93

    Creating Cartesian-based Graphs 82 with the new code you can pick, per line added, how you wish to treat it. So let's jump right in. Enabling switching mode between dots and lines All the work we added into the function doesn't need to go through a big overhaul as nothing is visible until it's actually rendered. That is controlled in one line, where we create read more..

  • Page - 94

    Chapter 3 83 context.fillStyle = data[i].style; context.fillRect(xPos-4 ,yPos-4,8,8); i==0? context.moveTo(xPos,yPos):context.lineTo(xPos,yPos); } if(style)context.stroke(); }else{ context.fillStyle = style; context.globalAlpha = .6; context.moveTo(CHART_PADDING,hei - CHART_PADDING) for(var i=0; read more..

  • Page - 95

    Creating Cartesian-based Graphs 84 In each recipe in this chapter we've been advancing the complexity of our code and so we are After we the standard charts into more creative avenues. The waterfall chart is a very useful chart to outline trends, such as monthly total changes (positive and negative) while outlining the total value of the big picture. This type read more..

  • Page - 96

    Chapter 3 85 The following is the code before implementing changes: function createBars(context,data){ var elementWidth =(wid-CHART_PADDING*2)/ data.length; var startY = CHART_PADDING; var endY = hei-CHART_PADDING; var chartHeight = endY-startY; var rangeLength = range.max-range.min; var stepSize = chartHeight/rangeLength; context.textAlign = "center"; for(i=0; read more..

  • Page - 97

    Creating Cartesian-based Graphs 86 These changes are more than cosmetic; we are leveraging our external data feeds that have been used throughout a few of our previous samples. Now that our function is up-to-date and working in our latest logic developed in the previous two recipes, it's time to start building our waterfall chart. How to do it... waterfall chart is to read more..

  • Page - 98

    Chapter 3 87 4. In the for loop logic, draw a rectangle if the value is not 0: for(i=0; i<data.length; i++){ elementValue = data[i][chartInfo.y.label]; total +=elementValue; if(elementValue!=0){ context.fillStyle = elementValue>0? "#C2D985" :"#E3675C" ; currentY -=(elementValue*stepSize); context.fillRect(CHART_PADDING read more..

  • Page - 99

    Creating Cartesian-based Graphs 88 It's time to jump into the for tasks we might need to do within a waterfall chart. There are three types (value goes up, value cases, let's update our variables: for(i=0; i<data.length; i++){ elementValue = data[i][chartInfo.y.label]; total +=elementValue; The element value will give us the current numeric value (don't read more..

  • Page - 100

    Chapter 3 89 values. We are literally just changing a color based on whether we are in the positive or currentY position we create a rectangle in the current position (this current position is after the value was added, so this is our end point). The most important element to notice is the fourth parameter, elementValue*stepSize. The fourth parameter captures the read more..

  • Page - 101

    Creating Cartesian-based Graphs 90 visualization function calls from our init function (such as createBars or addLine) and instead replace them with our new function: createWaterfall(context,formatData(a2011)); Note that I am using the formatData object as I'm just reusing our array from an earlier sample. I just updated the values so they don't step out of a total of 300: read more..

  • Page - 102

    Chapter 3 91 //all the rest the same //do to all 3 functions Now that we have our fillChart function and everything is working, let's add some extra logic just before we call the fillChart function to help add the min max values dynamically: function createWaterfall(context,data){ if(!chartInfo.y.min || !chartInfo.y.max) updateCumulativeChartInfo(chartInfo,data); read more..

  • Page - 103

    Creating Cartesian-based Graphs 92 To solve the problem of our numeric values being very ugly, we can create a formatting the function: function formatNumber(num,lead){ for(var i=0;i<lead;i++) num*=10; num = parseInt(num); for(var i=0;i<lead;i++) num/=10; return num; } The function parameters are the values to be formatted (num) and the number of places we want read more..

  • Page - 104

    Chapter 3 93 The worst thing you can do is to assume that the only usage of four dimensions of data is in the stock market. This is where you can come up with the next big thing. Visualizing data in a clean and quick way and converting data into logic is one of the most fun things about charts. With that said let's start creating our stock chart. Getting read more..

  • Page - 105

    Creating Cartesian-based Graphs 94 How to do it... We are going to base our work starting from where we left in the previous recipe. We will start 1. Let's update our global variables: var chartInfo= { y:{min:11500, max:12900,steps:5,label:"close"}, x:{min:1, max:12, steps:11,label:"date"} }; var stockData; var CHART_PADDING = read more..

  • Page - 106

    Chapter 3 95 var dataDate; for(var i=startIndex; i<data.length;i++){ aCurrent = data[i].split(","); dataDate = aCurrent[0].charAt(0)=="a"?parseInt(aCurrent[0].sli ce(1)):parseInt(aCurrent[0]); newData.push({ date:dataDate, close:parseFloat(aCurrent[1]), high:parseFloat(aCurrent[2]), read more..

  • Page - 107

    Creating Cartesian-based Graphs 96 context.lineTo(currentX,endY-lowY); context.rect(CHART_PADDING +elementWidth*i ,endY-openY,element Width,closeYOffset); context.stroke(); context.fillStyle = closeYOffset<0? "#C2D985" :"#E3675C" ; context.fillRect(CHART_PADDING +elementWidth*i ,endY-openY,ele mentWidth,closeYOffset); } } All these steps are required to create read more..

  • Page - 108

    Chapter 3 97 \n does the might need to use \r or a combination \n\r or \n\r. Always length of your array and validating its right size (then test to see if its content is what you expect it to be). After our array is ready we want to format it to the user-friendly format followed by starting up the old init function that is now known as read more..

  • Page - 109

    Creating Cartesian-based Graphs 98 var startY = CHART_PADDING; var endY = hei-CHART_PADDING; var chartHeight = endY-startY; var stepSize = chartHeight/(chartInfo.y.max-chartInfo.y.min); We are gathering information that will make it easier to work in our loop when creating the bars from the width of elements (elementWidth to the ratio between our values and the read more..

  • Page - 110

    Chapter 3 99 context.fillStyle = closeYOffset<0? "#C2D985" :"#E3675C" ; context.fillRect(CHART_PADDING +elementWidth*i ,endY-openY,element Width,closeYOffset); } closeYOffset variable. At this stage we have a running application, although it can use a few more tweaks to make it work better. There's more... x coordinate values: var chartInfo= { read more..

  • Page - 111

    Creating Cartesian-based Graphs 100 What we are doing here is, before we call the fillChart function in our addStock function, we are checking to see if the max value is set; if it isn't set, we are going to reset all the values, setting the min to 0 and the max and steps to the length of our data array. We are doing this as we read more..

  • Page - 112

    Chapter 3 101 Only if we have an output from the formatter function formatter function does not exist we don't need to do anything. As such we need the if statement to capture both the scenarios, if we do not have the if statement, then our output will not conform to our earlier recipes. The only content we are changing within this block of read more..

  • Page - 113

    Creating Cartesian-based Graphs 102 While all other data lines contain only a number that represents how many days passed since that original date, we want to test and see if the current date is only one day after the last day. Only if the date change is greater than one day, we will create a new date format for it: }else if ( i>1 && read more..

  • Page - 114

    Chapter 3 103 context.stroke(); }else{ context.rect(CHART_PADDING +elementWidth*i ,endY-openY,elementWi dth,closeYOffset); context.stroke(); context.fillStyle = closeYOffset<0? "#C2D985" :"#E3675C" ; context.fillRect(CHART_PADDING +elementWidth*i ,endY-openY,eleme ntWidth,closeYOffset); } } There we go. We set read more..

  • Page - 115

    read more..

  • Page - 116

    Let's Curve Things Up In this chapter we will cover: Building a bubble chart Creating a pie chart Using a doughnut chart to show relationships Leveraging a radar Structuring a tree chart Introduction In the last chapter, we built a component for linear graphs ranging through dots, lines, and bars. Most of the data we worked with was two-dimensional, while we read more..

  • Page - 117

    Let’s Curve Things Up 106 A great demo of the powers of bubble charts can be seen in a TED presentation by Hans Rosling ( html). Getting ready We will start up our project with a canvas setup and skip the HTML end. If you have forgotten how to create it please refer to the Graphics with 2D Canvas recipe read more..

  • Page - 118

    Chapter 4 107 english:60, programing:40}, {name:"Danny", math:50, english:90, programing:50}, {name:"Mary", math:60, english:60, programing:60}, {name:"Jim", math:80, english:20, programing:80}]; 2. Create our chart information; contrary to previous charts, this chart has a third var chartInfo= { y:{min:0, read more..

  • Page - 119

    Let’s Curve Things Up 108 addDots(context,chartInfo,students2001, ["math","programing","english"],"name"); } 5. We start creating our outline when we create our style object. Now it's time to draw everything into our canvas. So we start by setting up our base canvas style: function createOutline(context,chartInfo){ var s = styling; read more..

  • Page - 120

    Chapter 4 109 context.strokeStyle = s.text; var fontStyle = s.font.split("pt"); var pointSize = fontStyle[0]/2; fontStyle[0]=pointSize; fontStyle = fontStyle.join("pt"); context.font = fontStyle; // making 1/2 original size of bars for(var i=1; i<=steps; i++){ ratio = i/steps; context.moveTo(0,ratio*styling.CHART_HEIGHT-1); read more..

  • Page - 121

    Let’s Curve Things Up 110 var _x; var _xoffset=0; var _yoffset=0; if(chartInfo.bubble){ var range = chartInfo.bubble.max- chartInfo.bubble.min; var radRange = chartInfo.bubble.maxRadius- chartInfo.bubble.minRadius; context.textAlign = "left"; } for(var i=0; i<data.length; i++){ _x = ((data[i][keys[0]] - read more..

  • Page - 122

    Chapter 4 111 context.restore(); } } } This block of code, although redone from scratch, bears a lot of resemblance to the Spreading data in a scatter chart recipe in Chapter 3, Creating Cartesian-based Graphs, That's it. You should have a running bubble chart. Now when you run the application, you will see that the x parameter is read more..

  • Page - 123

    Let’s Curve Things Up 112 0,0 coordinates of our canvas to be exactly at value. Note that from now on if we try to add text to the canvas, it will be upside down. Keep context.scale(1,-1); context.fillText(chartInfo.y.min + (scope/steps)*i,0,(ratio*styling. CHART_HEIGHT-3 -pointSize)*-1); context.scale(1,-1); Note that we are multiplying our y coordinate by *-1. We are read more..

  • Page - 124

    Chapter 4 113 It's time for us to look through our data object and propagate the data on the chart. for(var i=0; i<data.length; i++){ _x = ((data[i][keys[0]] - chartInfo.x.min )/ chartInfo.x.range) * styling.CHART_WIDTH; _y = ((data[i][keys[1]] - chartInfo.y.min )/ chartInfo.y.range) * styling.CHART_HEIGHT; context.fillStyle = "#44ff44"; For each loop, we read more..

  • Page - 125

    Let’s Curve Things Up 114 Then we add the preceding if statement. If our label is set, we position the style and create the text of the label. Creating a pie chart The steps to create a pie chart are relatively easy and short. Pie charts are ideal for showcasing example, dividing the number of people in the world into groups based on their region: read more..

  • Page - 126

    Chapter 4 115 539000000,style:"#C2D985"}, {label:"North America", value:320000000,style:"#eeeeee"}, {label:"Near East", value:179000000,style:"#aaaaaa"}, {label:"Oceania", value:32000000,style:"#444444"} ]; var wid; var hei; var radius = 100; 2. Prepare our canvas (from here on we are delving into the init function): function read more..

  • Page - 127

    Let’s Curve Things Up 116 How it works... Our pie chart, as its name indicates, uses pies and always showcases 100 percent of data. As our arc method works based on radians, we need to convert these data points from percentile to radians. 2*PI), we are ready to loop through and draw the slices. var currentTotal=0; for(i=0; i<data.length; i++){ read more..

  • Page - 128

    Chapter 4 117 There's more... A pie chart without any information on its content is probably not going to work as well as a revisit our old friends cos and sin to help us locate the dots on our circle, to enable us to add textual information on our newly created pie. We will start with adding a new global variable to store the color of our lines read more..

  • Page - 129

    Let’s Curve Things Up 118 the same arc point with a larger circle size: context.fillText(data[i].label,Math.cos(midRadian)*(radius+40),Math. sin(midRadian)*(radius+40)); the challenges involved with them. In a real-world example, we would probably want to use a rollover if this was a live application capable of containing all the information. We stopped in our preceding line of code read more..

  • Page - 130

    Chapter 4 119 Using a doughnut chart to show relationships The doughnut chart is a fancy pie chart. So if you haven't created a pie chart yet, I strongly encourage you to revisit the previous recipe, Creating a pie chart. A doughnut chart is a layered pie chart. This chart is ideal for condensing the comparable data between data types Getting ready read more..

  • Page - 131

    Let’s Curve Things Up 120 How to do it... Perform the following steps: 1. Let's update our data with some dummy data (we will create two data objects): var data1= [ {label:"Asia", value:3518000000,style:"#B1DDF3"}, {label:"Africa", value:839000000,style:"#FFDE89"}, {label:"Europe", value:803000000,style:"#E3675C"}, {label:"Latin America and read more..

  • Page - 132

    Chapter 4 121 var rad360 = Math.PI*2; var currentTotal=0; var midRadian; var offset=0; for(i=0; i<data.length; i++){ context.beginPath(); context.moveTo(0,0); context.fillStyle = data[i].style; context.arc( 0,0,radius,currentTotal/total*rad360, (currentTotal+data[i].value)/total*rad360,false); context.lineTo(0,0); context.closePath(); read more..

  • Page - 133

    Let’s Curve Things Up 122 How it works... The core logic of the doughnut chart is the same as that of the pie chart. Our main focus is really about reformatting and rewiring the content to be outlined at the visual level. As such, part of our work is to delete the things that are not relevant and to make the needed updates: read more..

  • Page - 134

    Chapter 4 123 The key here is that we are setting our offset on both the x and y values to be 0, and as such our shadow is being used as a glow. Every element that will be drawn from here on will have a shadow, and that works perfectly for us. Creating a legend Hey, since we have a huge hole in our doughnut, how about we put our legend read more..

  • Page - 135

    Let’s Curve Things Up 124 Warning You really need to be friendly with the Math.cos and Math.sin functions, as we are going to use them plenty of times in this chart type. With that said, if you don't feel comfortable with them yet, it would be a good idea to start from the start of the chapter to refresh your memory on this. Getting ready As always, read more..

  • Page - 136

    Chapter 4 125 How to do it... Let's see what are the steps involved in creating a radar chart: 1. var data=[{label:"Ben", style:"#E3675C", math:90,english:45,spanis h:25,programing:90,bible:20,art:90}, {label:"Sharon", style:"#C2D985", math:100,english:90,spanish:60 ,programing:27,bible:80,art:20}]; var chartInfo= {steps:10, max:100, types:["math","english","spanis read more..

  • Page - 137

    Let’s Curve Things Up 126 context.strokeStyle = "#000000"; for(var i=0; i<hSteps; i++){ context.moveTo(0,0); context.lineTo(Math.cos(hStepSize*i + radianOffset)*(radius+20),Math.sin(hStepSize*i + radianOffset)*(radius+20)); } var stepSize = radius/chartInfo.steps; var cRad; for(var i=1; read more..

  • Page - 138

    Chapter 4 127 context.lineTo(Math.cos(hStepSize*j + radianOffset)*cRad,Math.sin(hStepSize*j + radianOffset)*cRad); } cRad = radius*(data[i][chartInfo.types[0]]/chartInfo.max); context.lineTo(Math.cos(radianOffset)* cRad,Math.sin(radianOffset)*cRad); context.stroke(); } } How it works... The radar chart functions, but read more..

  • Page - 139

    Let’s Curve Things Up 128 for(var i=1; i<=chartInfo.steps; i++){ cRad = i*stepSize; context.moveTo(Math.cos(radianOffset)*cRad, Math.sin(radianOffset)*cRad); for(var j=0;j<hSteps; j++){ context.lineTo(Math.cos(hStepSize*j + radianOffset)*cRad,Math.sin(hStepSize*j + radianOffset)*cRad); } read more..

  • Page - 140

    Chapter 4 129 context.textAlign="center"; for(var i=0; i<hSteps; i++){ context.moveTo(0,0); context.lineTo(Math.cos( radianOffset)*(radius+20),Math.sin( radianOffset)*(radius+20)); context.fillText(chartInfo.types[i],Math.cos( radianOffset)*(radius+30),Math.sin( radianOffset)*(radius+30)); context.rotate(hStepSize); } The logic here is a bit simpler as we are just rotating our canvas read more..

  • Page - 141

    Let’s Curve Things Up 130 To help us space out our elements, we will make our canvas area much larger in this sample How to do it... Perform the following steps: 1. that this will only work on an up-to-date version of Firefox as at the time of this book being written): var xml = <node name ="Display Object"> <node name="AVM1Mobie" /> read more..

  • Page - 142

    Chapter 4 131 <node name="StaticText" /> <node name="Video" /> </node>; 2. Then create our standard helper and styling objects: var wid; var hei; var style = {boxWidth:90,boxHeight:30, boxColor:"black",boxCopy:"w hite", boxSpace:4, lines:"black",lineSpace:30 }; 3. We will implement our init function and then call the drawTree function: read more..

  • Page - 143

    Let’s Curve Things Up 132 context.moveTo(startXPoint,currentY); context.lineTo(startXPoint+totalWidthOfNewLayer- style.boxWidth,currentY); context.stroke(); for(var i=0; i<nodes.length();i++){ drawTree(context,startXPoint + i*(style.boxWidth + style.boxSpace) ,_y+50,nodes[i]); } } } How it works... For more information on read more..

  • Page - 144

    Chapter 4 133 totalWidthOfNewLayer += ( nodes.length()-1)* style.boxSpace; var startXPoint = _x-totalWidthOfNewLayer/2 + style.boxWidth/2; var currentY = _y+style.boxHeight/2; context.beginPath(); context.strokeStyle ="#000000"; context.lineWidth=3; context.moveTo(_x,currentY); currentY+=style.lineSpace/2; context.lineTo(_x,currentY); context.moveTo(startXPoint,currentY); read more..

  • Page - 145

    Let’s Curve Things Up 134 <node name="Sprite" > <node name="MovieClip"/> <node name="MovieClip2"/> </node> <node name="Stage" /> </node> <node name="SimpleButton" /> <node name="TextField" /> </node> <node name="MorphShape" /> <node name="Shape" /> read more..

  • Page - 146

    Chapter 4 135 if(nextChildX>startXPoint){ currentY+=style.lineSpace/4; context.lineTo(_x,currentY); context.lineTo(_x + (nextChildX-startXPoint),currentY); currentY+=style.lineSpace/4; context.lineTo(_x + (nextChildX-startXPoint),currentY); startXPoint = nextChildX; // offset correction value }else{ read more..

  • Page - 147

    read more..

  • Page - 148

    5 In this chapter we will cover: Going though a funnel (a pyramid chart) Revisiting lines: making the line chart interactive Tree mapping and recursiveness Adding user interaction into tree mapping Making an interactive click meter Introduction We have covered our bases with the majority of the standard charts. At this stage, it's time for us to become more read more..

  • Page - 149

    Getting Out of the Box 138 It's rare that you see a pyramid chart that is actually created dynamically. For the most part, .jpg and that's exactly why I wanted to start this chapter with this chart—it's not as complex as it might sound. A pyramid chart is in essence a way for us to visualize changes in data that are quantitative by nature. They have a read more..

  • Page - 150

    Chapter 5 139 How to do it... Beyond our standard HTML preparation, we need to come up with the data sources that we 1. var layers = [{label:"Completed Chapter 1", amount:23}, {label:"Completed Chapter 2", amount:15}, {label:"Completed Chapter 3", amount:11}, {label:"Completed Chapter 4", amount:7}, {label:"Completed Chapter 5", amount:3} ]; 2. Then, read more..

  • Page - 151

    Getting Out of the Box 140 4. It's time for us to create our init function. This function will be doing most of the heavy lifting with the help of another function. function init(){ var can = document.getElementById("bar"); wid = can.width; hei = can.height; totalPixels = (chartInfo.height * chartInfo.width) / 2; for(var i in layers) totalData read more..

  • Page - 152

    Chapter 5 141 its time to understand what we just did. How it works... After setting the code for lines in the init function, we are ready to start thinking about our totalPixels = (chartInfo.height * chartInfo.width) / 2; That is easy as we know our height and our width, so the formula is really simple. The next data point that is critical is the total read more..

  • Page - 153

    Getting Out of the Box 142 There's more... Let's start with introducing color into our pallet. var layers = [{label:"Completed Chapter 1", amount:23, style:"#B1DDF3"}, {label:"Completed Chapter 2", amount:15, style:"#FFDE89"}, {label:"Completed Chapter 3", amount:11, style:"#E3675C"}, {label:"Completed Chapter 4", amount:7, style:"#C2D985"}, read more..

  • Page - 154

    Chapter 5 143 Our next problem is that we don't want to change the actual triangle height as we will be calling this function more times than we did in the past. To come up with a plan for this problem, we need to extract some of the logic. We will return the new number of lines that were created, so that we can remove them externally from read more..

  • Page - 155

    Getting Out of the Box 144 currentTriangleHeight -= secHeight; context.fillStyle = layers[i].style; context.fill(); } context.beginPath(); findLine(context, 0,true); context.lineTo(0,0); context.fillStyle = layers[i].style; context.fill(); First, we draw all elements in our loop, minus the last one (as our last element is actually a triangle and read more..

  • Page - 156

    Chapter 5 145 Just see the difference between drawing our text in the loop and out of it. As we don't get new line data out of the loop, we need to change the point logic by using the total size of our leftover triangle. Revisiting lines: making the line chart interactive In this recipe, we will travel back in time to one of our earlier recipes, Building read more..

  • Page - 157

    Getting Out of the Box 146 Getting ready Chapter 3, Creating Cartesian-based Graphs. We will rename 03.05.line-revamp.html and 03.05.line- revamp.js to 05.02.line-revisit. three data sources (years 2009, 2010, and 2011). <hr/> 2009 : <input type="radio" name="i2009" value="-1" /> off <input type="radio" name="i2009" read more..

  • Page - 158

    Chapter 5 147 2. Time to move the logic of creating the chart into a separate function. Everything after the initalization of our canvas is going to be moved out. var context; function init(){ var can = document.getElementById("bar"); wid = can.width; hei = can.height; context = can.getContext("2d"); drawChart(); } 3. Update the radio boxes read more..

  • Page - 159

    Getting Out of the Box 148 context.font = "10pt Verdana, sans-serif"; context.fillStyle = "#999999"; context.moveTo(CHART_PADDING,CHART_PADDING); context.rect(CHART_PADDING,CHART_PADDING,wid- CHART_PADDING*2,hei-CHART_PADDING*2); context.stroke(); context.strokeStyle = "#cccccc"; fillChart(context,chartInfo); if(elementStatus.i2011>-1) read more..

  • Page - 160

    Chapter 5 149 We are using an object called elementStatus to store the current status of each line on our chart. The values it can store are as follows: -1: Do not draw 0 1 As such, we are adding the following logic into the end of our function: if(elementStatus.i2011>-1) addLine(context,formatData(a2011, "/2011"," read more..

  • Page - 161

    Getting Out of the Box 150 Let's take another peek at the logic in this function: elementStatus[] =; elementStatus controller. context.clearRect(0,0,wid,hei); We follow that by deleting everything from our canvas. context.beginPath(); Next, wipe the slate clean and start with a new path. drawChart(); And... you guessed it… Then start drawing everything all over, read more..

  • Page - 162

    Chapter 5 151 Getting ready We will start our application with the number of people in the world, in millions, divided by continent (based on public data from 2011). var chartData = [ {name: "Asia", value:4216}, {name: "Africa",value:1051}, {name: "The Americas and the Caribbean", value:942}, {name: "Europe", value:740}, {name: "Oceania", read more..

  • Page - 163

    Getting Out of the Box 152 3. Create the function drawTreeMap. function drawTreeMap(infoArray){ var percent=0; var cx=0; var rollingPercent = 0; for(var i=0; i<infoArray.length; i++){ percent = infoArray[i].value/total; rollingPercent +=percent context.fillStyle = formatColorObject(getRandomColor(255)); context.fillRect(cx,0 ,wid*percent,hei); read more..

  • Page - 164

    Chapter 5 153 How it works... Let's start with the initial idea. Our goal is to create a map that will showcase the bigger volume areas inside our rectangular area and leave a strip on the side for the smaller areas. So, let's start with our init calculate the actual total. We do that by looping through our data source, thus: for(var item in chartData) total read more..

  • Page - 165

    Getting Out of the Box 154 welcome to play with that value). When we reach it, we need to stop the loop, so that we can start drawing our rectangles by height instead of by width. if(rollingPercent > 0.7) break; } Before we start working on our boxes, which take the full leftover width and expand to the height, we need a few helper variables. var read more..

  • Page - 166

    Chapter 5 155 {name: "The Americas and the Caribbean", data:[ {name: "South America",total:396}, {name: "North America",total:346}, {name: "Central America",total:158}, {name: "Caribbean",total:42} ]}, {name: "Europe", total:740}, {name: "Oceania", total:37} ]; Now we have two regions of the world with a read more..

  • Page - 167

    Getting Out of the Box 156 Let's update our function to enable recursive operations. We start by adding an extra new parameter to capture the latest color. function drawTreeMap(infoArray,wid,hei,x,y,total,clr){ var percent=0; var cx=x ; var cy=y; var pad = 0; var pad2 = 0; var rollingPercent = 0; var keepColor = false; if(clr){ //keep color read more..

  • Page - 168

    Chapter 5 157 cx+=wid*percent; if(rollingPercent > 0.7) break; } The same logic is then implemented on the second loop as well (to see it check the Turning the data and total to recursive data Let's start by updating our tree data to be really recursive (for the full dataset please refer to the source code). … {name: "Asia", data:[ {name: read more..

  • Page - 169

    Getting Out of the Box 158 val = chartData[item]; if(! && = calculateTotal(; total +=; } return total; } The logic is really similar to what it was, with the exception that all the data entries are internal to the function, and each time there is a need to deal with another read more..

  • Page - 170

    Chapter 5 159 Consider the case when the user clicks on the chart (for example, the next picture is generated by clicking on the left-hand side rectangle—the tree map will update and zoom into that area). Getting ready To get this sample right, you will need to start from our last recipe, Tree maping and recursiveness, and adjust it to work for this read more..

  • Page - 171

    Getting Out of the Box 160 if(e.x>= box.x && e.y>= box.y && e.x<= box.x2 && e.y<= box.y2){ context.clearRect(0,0,wid,hei); drawTreeMap(currentDataset[item].data,wid, hei,0,0,currentDataset[item].total); currentDataset = currentDataset[item].data; break; } read more..

  • Page - 172

    Chapter 5 161 We loop through our data source (current one) and check to see whether the element we are currently in has a data source (that is, children); if it does, we continue, and if not, we will skip to the next element to test it as well. Now that we know our element has children, we are ready to see if our dot is in the range of our read more..

  • Page - 173

    Getting Out of the Box 162 break; } }else{ currentDataset = chartData; drawTreeMap(chartData,wid,hei,0,0,total); } } } and now it's in your hands to make this look a bit better. Add some rollover labels and all the visualization that will make your chart visually pleasing and will help understanding. read more..

  • Page - 174

    Chapter 5 163 How to do it... Most of the steps are going to be familiar, if you have worked on the bar chart from Chapter 3, Creating Cartesian-based Graphs. So, let's run through them and then focus on the new logic: 1. Let's create some helper variables. var currentObject = {label:1, value:0, style:"rgba(241, 178, 225, .5)"}; var colorOptions = read more..

  • Page - 175

    Getting Out of the Box 164 4. The next step is to create the onClick listener. function onClick(e){ currentObject.value++; refreshChart(); } 5. Now create the refreshChart function. function refreshChart(){ var newData = data.slice(0); newData.push(currentObject); drawChart(newData); } 6. Last but not least, let's create drawChart (most of its logic is the same as read more..

  • Page - 176

    Chapter 5 165 var elementWidth =(wid-CHART_PADDING*2)/ data.length; context.textAlign = "center"; for(i=0; i<data.length; i++){ context.fillStyle = data[i].style; context.fillRect(CHART_PADDING +elementWidth*i ,hei- CHART_PADDING - data[i].value*stepSize, elementWidth,data[i].value*stepSize); context.fillStyle = "rgba(255, 255, 225, 0.8)"; read more..

  • Page - 177

    Getting Out of the Box 166 Every time a second passes, the function checks whether the user had any clicks in that time interval, and if they did, it ensures that we push currentObject into the dataset. If the size of the dataset is greater than 25 matter what we create, a new empty object is labeled with a new label showing the current time in seconds. read more..

  • Page - 178

    6 In this chapter, we will cover the following topics: Stacking graphical layers Moving to an OOP perspective Animating independent layers Adding an interactive legend Creating a context-aware legend Introduction Until now, the importance of keeping things organized and clean wasn't as great as that of getting our projects done as we had relatively small projects. read more..

  • Page - 179

    Bringing Static Things to Life 168 Stacking graphical layers Before we can do any real animations on our canvas we really need to rethink the concept of building everything on one canvas layer. Once a canvas element is drawn, it's incredibly hard one of our famous charts, the bar chart, which we played around with and enhanced many times throughout the earlier read more..

  • Page - 180

    Chapter 6 169 2011 : <input type="radio" name="i2011" value="-1" /> off <input type="radio" name="i2011" value="0" /> line <input type="radio" name="i2011" value="1" select="1" /> full </div> </body> </html> 2. Add a CSS script so the layers will be read more..

  • Page - 181

    Bringing Static Things to Life 170 5. Consolidate all bar line information into one object for easier control (delete all the highlighted code snippets): var a2011 = [38,65,85,111,131,160,187,180,205,146,64,212]; var a2010 = [212,146,205,180,187,131,291,42,98,61,74,69]; var a2009 = [17,46,75,60,97,131,71,52,38,21,84,39]; var chartInfo= { y:{min:0, max:300, steps:5,label:"users"}, read more..

  • Page - 182

    Chapter 6 171 6. Remove all canvas logic from the init function and add it to the drawChart function: function init(){ var can = document.getElementById("bar"); wid = can.width; hei = can.height; context = can.getContext("2d"); drawChart(); var radios ; for(var id in elementStatus){ radios = document.getElementsByName(id); read more..

  • Page - 183

    Bringing Static Things to Life 172 8. In the drawChart function, extract the logic of line creation to an external function (delete the highlighted code snippets): if(elementStatus.i2011>-1) addLine(context,formatData(a2011, "/2 011","#B1DDF3"),"#B1DDF3",elementStatus.i2011==1); if(elementStatus.i2010>-1) addLine(context,formatData(a2010, "/2 read more..

  • Page - 184

    Chapter 6 173 How it works... The heart each other, and as our canvas is by default transparent, we can see through to the elements that are under it. After our canvas is layered with four layers, it's time for us to separate our background from our lines and as such we want to put all of our chart background information right into the base canvas: read more..

  • Page - 185

    Bringing Static Things to Life 174 We didn't change the core logic of our line but redirected the logic into the context of the current line: can = document.getElementById(id); This way we can extract any direct mention of a year or element without referring to element names directly. This way we can add or remove elements and we would only need to add read more..

  • Page - 186

    Chapter 6 175 to our <div> tag (delete the highlighted code snippet): <div id="chartContainer" class="graphicLayers" > <canvas id="base" class="canvasLayer" width="550" height="400"> </canvas> <canvas id="i2011" class="canvasLayer" width="550" height="400"> read more..

  • Page - 187

    Bringing Static Things to Life 176 Creating the radio buttons dynamically Yet another section that could be dynamic is our creation of radio buttons. So let's start with highlighted code snippet): <div id="chartContainer" class="controllers"> 2009 : <input type="radio" name="i2009" value="-1" /> off <input type="radio" read more..

  • Page - 188

    Chapter 6 177 appendRadioButton(radContainer,id,1," full "); hasLooped = true; } var radios ; for(id in barData){ radios = document.getElementsByName(id); for (var i=0; i<radios.length; i++){ radios[i].onchange = onChangedRadio; if(radios[i].value == barData[id].status ){ radios[i].checked = true; read more..

  • Page - 189

    Bringing Static Things to Life 178 How to do it... Let's jump right in and start converting our code to be more OOP friendly: 1. LineChart constructor method: function LineChart(chartInfo,barData){ this.chartInfo = chartInfo; this.barData = barData; this.HIDE_ELEMENT = -1; this.LINE_ELEMENT = 0; this.FILL_ELEMENT = 1; this.CHART_PADDING = 20; this.wid; read more..

  • Page - 190

    Chapter 6 179 2. Let's update all of our functions to be prototypes of the LineChart function (our pseudo class): LineChart.prototype.drawChart =function(){...} LineChart.prototype.appendRadioButton = function(container, id,value,text){...} LineChart.prototype.onChangedRadio = function (e){...} LineChart.prototype.changeLineView = function(id,value){...} LineChart.prototype.fillChart = function (context, chartInfo){...} read more..

  • Page - 191

    Bringing Static Things to Life 180 can.width=this.wid; can.height=this.hei; can.setAttribute("class","canvasLayer"); chartContainer.appendChild(can); this.changeLineView(id,this.barData[id].status); } } //continue and update all methods of our new object 4. In our application so far, to deal with radio buttons we created read more..

  • Page - 192

    Chapter 6 181 style: "#B1DDF3", label: "2011", data:[38,65,85,111,131,160,187,180,205,146,64,212] }, i2010:{ status: FILL_ELEMENT, style: "#FFDE89", label: "2010", read more..

  • Page - 193

    Bringing Static Things to Life 182 there, scope would not be an object scope but instead, the scope would be only within that function. As such whenever you want to create variables that are shared throughout an object you must create them and refer to them with a leading this reference. The next step is to rename all of our functions to be prototypes of read more..

  • Page - 194

    Chapter 6 183 Moving our base canvas element into our constructor Let's start by moving from the drawChart function. The following logic will fetch the base canvas and create a global variable within our new constructor: var can = document.getElementById("base"); this.wid = can.width; this.hei = can.height; this.baseCanvas = can.getContext("2d"); This read more..

  • Page - 195

    Bringing Static Things to Life 184 We are going to start inserting the controller class within our global <div> tag that will be used for our canvas. We need to update our CSS information for the controllers: .controllers { position: absolute; left:0; top:400px; } OK. We are now ready to do some code updates read more..

  • Page - 196

    Chapter 6 185 radContainer.innerHTML += (hasLooped ? " || ":"") + barData[id]. label +": " ; this.appendRadioButton(radContainer,id,-1," off "); this.appendRadioButton(radContainer,id,0," line "); this.appendRadioButton(radContainer,id,1," full "); hasLooped = true; } var radios ; for(id in barData){ radios read more..

  • Page - 197

    Bringing Static Things to Life 186 I've created two helper functions and their role is simple: to rename <div> buttons by adding the main <div> tag ID into their name. This way we won't have duplicate elements. All that is left is to locate all the areas where we are creating elements (we are creating canvas in the drawChart function and read more..

  • Page - 198

    Chapter 6 187 <div id="chartContainer2" class="graphicLayers2" > </div> </body> </html> In our init function let's set up both charts: new LineChart(chartInfo,barData,"chartContainer"); new LineChart(chartInfo,barData,"chartContainer2"); charts working at the same time based on the same code base. Animating independent layers After a read more..

  • Page - 199

    Bringing Static Things to Life 188 position: relative; left:100px } #chartContainer2{ position: relative; left:700px } .controllers { position: absolute; left:0; top:400px; } .canvasLayer{ position: absolute; read more..

  • Page - 200

    Chapter 6 189 this.animQue.push({obj:obj, p:property, crt:from, to:to, stepSize: (to-from)/(time*1000/this.refreshRate), delay:delay*1000 || 0}); if(!this.interval){ //only start interval if not running already this.interval = setInterval(this._animate,this. read more..

  • Page - 201

    Bringing Static Things to Life 190 5. Create a new Animate object within the LineChart constructor method and animate key components: function LineChart(chartInfo,barData,divID){ ... this.animator = new Animator(50); var chartContainer =this.mainDiv; var can = document.createElement("canvas"); can.width=chartInfo.width; can.height=chartInfo.height; read more..

  • Page - 202

    Chapter 6 191 How it works... Let's start by looking into our Animator constructor. We start with a few variables in our constructor: function Animator(refreshRate){ this.animQue = []; this.refreshRate = refreshRate || 50; //if nothing set 20 FPS this.interval = 0; } These variables are the key to everything else. The animQue array will store each new animation read more..

  • Page - 203

    Bringing Static Things to Life 192 Our add method takes in all the necessary information to animate a property: Animator.prototype.add = function(obj,property, from,to,time,delay){} Each element sent in to animate is then converted into a reference object that will be used when animations are running and pushed into our animQue array: this.animQue.push({obj:obj, read more..

  • Page - 204

    Chapter 6 193 This is the only strange logic, where we force the value of our loop variable down: }else{ obj[data.p] =; scope.animQue.splice(i,1); --i; } In this code we are removing our element. As soon as we remove our element our current value of i will be one value larger than it should be, as our object has shrunk. To solve this read more..

  • Page - 205

    Bringing Static Things to Life 194 How to do it... This time around we will create a method in the LineChart object that will create legends for us. Perform the following steps: 1. Create the createLegend method: LineChart.prototype.createLegend = function (){ var can = document.createElement("canvas"); can.width=70; can.height=100; read more..

  • Page - 206

    Chapter 6 195 3. The next step for us is to create a few methods that will be used as event listeners. Let's add a few listeners to control our animation: LineChart.prototype.onMouseMoveArea = function(e){ = (e.layerY) +"px"; } LineChart.prototype.fadeInLegend = function(){ this.animator.add(,"opacity", opacity,1,.5); } read more..

  • Page - 207

    Bringing Static Things to Life 196 repositioning based on our mouse moves. How it works... The logic this time around is simple as our application already is nicely set and optimized. Our createLegend method creates for us a new canvas area that we can use for our legend. I've added some hardcoded values into it, but it would be a good idea to extract them read more..

  • Page - 208

    Chapter 6 197 The only thing that requires explanation is the logic involved with the layout of the legend. We need to know how many items our chart contains to avoid looping through the data source time we loop through the user-generated data and thus update it to have our total items within it. We set up our method in a way that would make it read more..

  • Page - 209

    Bringing Static Things to Life 198 to:to, stepSize: (to-from)/(time*1000/this.refreshRate), delay:delay*1000 || 0}); if(!this.interval){ //only start interval if not running already this.interval = setInterval(this._animate,this.refreshRate,this); } } Although we have not addressed the dynamic legend read more..

  • Page - 210

    Chapter 6 199 2. Update the createLegend method: LineChart.prototype.createLegend = function (){ var can = document.createElement("canvas"); can.width=90; can.height=100; can.setAttribute("class","canvasLayer"); chartContainer.appendChild(can); this.legend = can; this.updateLegend(null,-1); = this.wid +"px"; } 3. read more..

  • Page - 211

    Bringing Static Things to Life 200 4. Change the event listener onMouseMoveArea: LineChart.prototype.onMouseMoveArea = function(e){ var pixelData; var barCanvas; var chartX = e.layerX-this.CHART_PADDING; var chartWid = this.wid -this.CHART_PADDING*2; var currentXIndex = -1; if(chartX>=0 && chartX<= chartWid){ currentXIndex = read more..

  • Page - 212

    Chapter 6 201 can.setAttribute("class","canvasLayer"); chartContainer.appendChild(can); this.barData[id].canvas =can.getContext("2d"); this.changeLineView(id,this.barData[id].status); this.animator.add(,"opacity",0,1,1,delay); delay+=.5; } We should be all set. When you run the page again, your mouse should be in control read more..

  • Page - 213

    Bringing Static Things to Life 202 if( pixelData[3]){ count++; renderList[id] = true; //there is content on this layer now } } that ID into the renderList object. The renderList object is going to be our hub; it will updateLegend method. If our mouse is above an element that is drawn then we will showcase the read more..

  • Page - 214

    Chapter 6 203 our chart. read more..

  • Page - 215

    read more..

  • Page - 216

    7 Depending on the Open Source Sphere In this chapter we will cover: Animating a gauge meter (jqPlot) Creating an animated 3D chart (canvas3DGraph) Building a clock with RaphaelJS Making a sunburst chart with InfoVis Introduction The open source data visualization community is extremely rich and detailed, with many options and some really amazing libraries. Each library read more..

  • Page - 217

    Depending on the Open Source Sphere 206 In this chapter we will explore working with some of these options. Instead of using the override the built-in libraries to provide us with better control over our applications, in case One more important thing to note is that all of these open source libraries have copyrights. It is advised that you check the legal read more..

  • Page - 218

    Chapter 7 207 <meta charset="utf-8" /> <link rel="stylesheet" href="./external/jqplot/jquery.jqplot.min.css"> <script src=" ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script src="./external/jqplot/ jquery.jqplot.js"></script> <script read more..

  • Page - 219

    Depending on the Open Source Sphere 208 5. Now it's time to animate our chart. Let's add in the last line of our ready listener interval (it will run from now on until the end of the recipe): $(document).ready(function(){ meter = $.jqplot('meter',[[meterValue]],{ seriesDefaults: { renderer: $.jqplot.MeterGaugeRenderer, rendererOptions:renderOptions read more..

  • Page - 220

    Chapter 7 209 How it works... This task was really easy as we didn't need to start everything from scratch. For the meter to run, we need to import the library meterGaugeRenderer. We do that by adding that into our is to prepare a few global variables; we are using global variables as we want to re-use these variables in two different functions read more..

  • Page - 221

    Depending on the Open Source Sphere 210 //ticks: [0, 40, 80, 120], intervals:[10,25, 90, 120], intervalColors:['#999999', '#E7E658','#66cc66', '#cc6666'] }; The ticks function controls where the copy outlines would be. The default would take our top range and divide it by 4 (that is 30, 60, 90, and 120). The intervals and intervalColors functions let the meter read more..

  • Page - 222

    Chapter 7 211 If we are already passed this state and want our meter to go up and down randomly, making it look like variations in driving speed, we'll use the following code snippet: }else{ meterValue += 1- Math.random()*2; meterValue = Math.max(0,Math.min(meterValue,120)); //keep our value in range no mater what } We are randomly adding a read more..

  • Page - 223

    Depending on the Open Source Sphere 212 Getting ready If you want to follow our updates, download the How to do it... Let's jump right in as we have a lot of work to do: 1. <!DOCTYPE html> <html> <head> <title>canvas3DGraph.js</title> <meta charset="utf-8" /> <link rel="stylesheet" read more..

  • Page - 224

    Chapter 7 213 top:0px; left:0px; z-index:10; } #x-label{ position:absolute; z-index:2; top:340px; left:580px; } #y-label{ position:absolute; z-index:2; top:10px; left:220px; } #z-label{ position:absolute; z-index:2; top:540px; read more..

  • Page - 225

    Depending on the Open Source Sphere 214 for(i=0;i<100;i++){ gData[i] = {x:(Math.cos((i/10)) * 400 + 400), y:(1000-(i*9.2)), z:(i*10)}; } plotBar(); setInterval(plotBar,40); } 6. Create the plotBar function: function plotBar(){ trailingArray.push(gData[curIndex]); if(trailingArray.length>=5) trailingArray.shift(); g.drawGraph(trailingArray);//trailingArray); curIndex++ read more..

  • Page - 226

    Chapter 7 215 The gData array will store all the possible points in the 3D space. A 3D bar will be created with these points (the points are the 3D points x, y, and z values that will be put into this array as objects). The trailingArray array will store the current bar elements in the view. The trailCount variable current index (curIndex) will keep track of read more..

  • Page - 227

    Depending on the Open Source Sphere 216 If our array length is 5 if(trailingArray.length>=5) trailingArray.shift(); We then draw our chart and push the value of curIndex up by one. If our curIndex is greater than our array elements, we reset it to 0. g.drawGraph(trailingArray);//trailingArray); curIndex++ if(curIndex>=gData.length) curIndex=0; The logic behind styleFormatter Our read more..

  • Page - 228

    Chapter 7 217 We have created a clear function to delete all the visuals from the graph so we can re-render the data each time we call it: canvasGraph.prototype.getBarStyle= function(baseStyle,index,total){ return this.barStyle.formatter? this.barStyle.formatter(baseStyle,index,total):baseStyle; } We moved the logic of drawing the chart to the drawGraph function, so I can read more..

  • Page - 229

    Depending on the Open Source Sphere 218 My second favorite feature is how easy it is to update the chart text info by using a tickFormater method: read more..

  • Page - 230

    Chapter 7 219 Getting ready To get the latest builds of the flotJS library, please visit our link hub at http://blog. for charting open source libraries or download our book's books/html5-graphics-and-data-visualization-cookbook.htm. How to do it... Let's create our 1. <!DOCTYPE html> <html> <head> read more..

  • Page - 231

    Depending on the Open Source Sphere 220 xaxis: { tickDecimals: 0, tickFormatter: function (v) { return v%12 + "/" + (2009+Math.floor(v/12)); } }, yaxis: { tickFormatter: function (v) { return v + " cm"; } } }; 3. Create a ready event and trigger updateChart: $(document).ready(updateChart); 4. Create updateChart: function updateChart() { plot = read more..

  • Page - 232

    Chapter 7 221 ]; index++; return dataset; } Now if you run the chart in your browser, you will see 6 months at a time, and at every half of a second, the chart will be updated by pushing the chart one month forward until the end of data source is reached. How it works... flotJS has a built-in logic to reset itself when its read more..

  • Page - 233

    Depending on the Open Source Sphere 222 There's more... There are still two more things to cover—the getData function and the updateChart function. In flotJS every data point has an ID. In our case, we want to showcase six related content types. Play around with the parameters to see how they change the way the view is rendered. Before we send the read more..

  • Page - 234

    Chapter 7 223 Getting ready As always in this chapter, you need the original library of Raphael. I've added it into our How to do it... Let's build up our application: 1. <!DOCTYPE html> <html> <head> <title>Raphael</title> <meta charset="utf-8" /> <script read more..

  • Page - 235

    Depending on the Open Source Sphere 224 body { background: #333; color: #fff; font: 300 100.1% "Helvetica Neue", Helvetica, "Arial Unicode MS", Arial, sans-serif; } #holder { height: 600px; margin: -300px 0 0 -300px; read more..

  • Page - 236

    Chapter 7 225 var degree = 360 *per; if(isClock) degree = 360-degree; var a = (90 - degree) * Math.PI / 180, x = baseX + R * Math.cos(a), y = baseY - R * Math.sin(a), path; if (per==1) { path = [["M", baseX, baseY - R], ["A", R, R, 0, 1, 1, baseX, baseY - R]]; } else { path = [["M", read more..

  • Page - 237

    Depending on the Open Source Sphere 226 var dDot = r.path("M0,0L0,0z").attr({fill: "#fff", stroke: "#fff", "fill-opacity": .3, "stroke-width": 1, "stroke-linecap": "round", translation: "100 100"}); transPath = Raphael.transformPath(helveticaForClock[':'], 'T280,90'); dDot.attr({path:transPath}); 7. Now it's time to create our art for our seconds read more..

  • Page - 238

    Chapter 7 227 9. Create the animateStrokeWidth function: function animateStrokeWidth(that,startWidth,endWidth,time){ that.attr({'stroke-width':startWidth}); that.animate({'stroke-width':endWidth},time,function(){ animateStrokeWidth(that,startWidth,endWidth,time); //repeat forever }); } If you run the application now, you will see the outcome of my day of play with Raphael's library. How it read more..

  • Page - 239

    Depending on the Open Source Sphere 228 There's more... critical steps. Animating paths One of the cooler things in this library is the capability to animate paths. If you have ever worked with Adobe Flash Shape Tweens, this will look very familiar—hands down, this is just really cool. The idea is very simple. We have an object with a lot of path points. read more..

  • Page - 240

    Chapter 7 229 Each time the animateSeconds digit has changed, and if it has then we are ready to update its information: var newDigits = [time.getMinutes()%10, parseInt(time.getMinutes()/10), time.getHours()%10, parseInt(time.getHours()/10)]; var path; var transPath; for(var i=0; i<aLast.length; i++){ if(aLast[i]!=newDigits[i]){ path = aDigits[i]; aLast[i] = read more..

  • Page - 241

    Depending on the Open Source Sphere 230 We will keep it relatively simple by having only four elements (Ben, Packt Publishing, 02geek, and Nicolas the creator of InfoVis). I have a one-way relationship with each of them: as the owner of, as a writer for Packt Publishing, and a user of InfoVis. While that is true about me, not all the others have a read more..

  • Page - 242

    Chapter 7 231 How to do it... Let's create some HTML and JavaScript magic: 1. <!DOCTYPE html> <html> <head> <title>Sunberst - InfoVis</title> <meta charset="utf-8" /> <style> #infovis { position:relative; width:600px; height:600px; margin:auto; read more..

  • Page - 243

    Depending on the Open Source Sphere 232 4. To connect the dots, we will need to create a function that will create the relationships between the elements: function relate(obj){ for(var i=1; i<arguments.length; i++){ obj.adjacencies.push({'nodeTo':arguments[i]}); } } 5. We want to be able to highlight the relationships. To do that we will need to have read more..

  • Page - 244

    Chapter 7 233 relate(node,'ben'); node = createNode('ben','Ben',100,40,"#E3675C"); relate(node,'geek','packt','nic'); node = createNode('nic','Nicolas',100,40,"#C2D985"); //no known relationships so far ;) ... 8. Create the actual sunburst and interact with the API (I've stripped it down to its bare bones; in the original samples it's much more detailed): read more..

  • Page - 245

    Depending on the Open Source Sphere 234 9. Last but not least, we want to render our chart by providing its dataSource and sb.loadJSON(dataSource); sb.refresh(); That's it. If you run scratches the capabilities of this really cool data networking library. How it works... I'll avoid getting into the details of the actual API as that is fairly intuitive and has a really read more..

  • Page - 246

    Chapter 7 235 "$lineWidth": 4 } } ] }, There are a few important really thrilling are between nodes that are at an equal level. As such the main parent has a relationship with all the nodes that are to follow. The children read more..

  • Page - 247

    Depending on the Open Source Sphere 236 Our last data-related function is our highlight function. The highlight function expects one parameter nodeID (that we created in createNode). The goal of the highlight function is to travel through all the data elements and de-highlight all the relationships limited to the one selected element and its relationships. function read more..

  • Page - 248

    Chapter 7 237 There's more... One more thing left is that we need to be able to refresh our content when the user clicks on an element. To accomplish this task, we will need to add an event parameter into the initializing parameter object of jit.Sunburst: var sb = new $jit.Sunburst({ injectInto: 'infovis', //id container ... Events: { read more..

  • Page - 249

    read more..

  • Page - 250

    8 Playing with Google Charts In this chapter we will cover: Getting started with a pie chart Creating charts using the ChartWrapper Changing data source to Google Spreadsheet Customizing chart properties with an options object Adding a dashboard to charts Introduction In this chapter, we will explore the Google visualization API task by task. We will look at read more..

  • Page - 251

    Playing with Google Charts 240 Getting ready 08.01.getting-started.html and 08.01.getting-started.js. How to do it... Let's list the steps 1. Let's start by creating a head and linking it to the Google jsapi and our local <!DOCTYPE html> <html> <head> <title>Google Charts Getting Started</title> <meta charset="utf-8" /> read more..

  • Page - 252

    Chapter 8 241 6. Create a new Google data object and provide data sources as shown in the following code snippet: data.addColumn('string', 'Type of Death'); data.addColumn('number', 'Deaths'); data.addRows([ ['Diseases of heart', 616828], ['Malignant neoplasms', 565469], ['Chronic lower respiratory diseases', 141090], read more..

  • Page - 253

    Playing with Google Charts 242 following screenshot: How it works... Let's explore the steps involved in working with Google Charts. <script src=""></script> Now that the Google API is loaded into our application, we can request the library we wish to work with. In our case, we want to work with the visualization API and read more..

  • Page - 254

    Chapter 8 243 We are asking the Google API to let us know when the package has loaded in a similar way to how we added a callback to our document. When the API is loaded, it is time for us to start interacting with the charting API. There are three components that you will probably want to explore in each Google Chart: Creating the data source read more..

  • Page - 255

    Playing with Google Charts 244 This covers our datasets. As long as we set our columns in the order of our data and send our information via arrays, we are set and don't need to dig any deeper into the data API. The options object enables us to create and modify the elements of our chart. The elements we control in our application are width, height, read more..

  • Page - 256

    Chapter 8 245 Changing the chart type Changing a chart type isn't something complicated. As long as the chart types share the same number of data entries the change is usually one word from the actual constructor object of the chart. For example, we can very quickly switch our chart type by changing the method in the visualization library that is called: var chart read more..

  • Page - 257

    Playing with Google Charts 246 Getting ready Getting started with pie charts). We will only modify How to do it... 1. Load Google API (you do not need to mention what you want to load any more) and add a callback: google.load('visualization', '1.0'); google.setOnLoadCallback(init); 2. Create the init function: function init(){ … } 3. Build a 2D array with the data source: read more..

  • Page - 258

    Chapter 8 247 4. Create the options object: var options = {'title':'Deaths, for the 15 leading causes of death: United States, 2008', 'width':800, 'height':600, "is3D": true}; 5. Build and render the chart: var chart = new read more..

  • Page - 259

    Playing with Google Charts 248 Changing data source to Google Spreadsheet One of the powerful features of working with the Google API is the deep relationship between the product lines. In this recipe, based on the last recipe, we will create a Google Spreadsheet and then integrate it into our application. Getting ready Creating charts using the ChartWrapper). How to do read more..

  • Page - 260

    Chapter 8 249 2. Create a new spreadsheet. 3. Add data to the spreadsheet. 4. Click on the Share button and set the view to public: 5. Create an API URL based on the document ID: Document link: DdFJfUTNVSVltTS1ZQWQ0bWNsX2xSbVE API link: UTNVSVltTS1ZQWQ0bWNsX2xSbVE read more..

  • Page - 261

    Playing with Google Charts 250 6. Now, it's time replace it with a URL feed: google.load('visualization', '1.0'); google.setOnLoadCallback(init); function init(){ var options = {'title':'Deaths, for the 15 leading causes of death: United States, 2008', 'width':800, 'height':600}; var read more..

  • Page - 262

    Chapter 8 251 How it works... This is really the amazing part about it. You just don't need to understand how it works, all you need to do is create your chart and use the steps provided in the preceding section, and you can convert any of your own spreadsheets into a Google Spreadsheet. The most important step in the preceding steps is step 4. Notice that read more..

  • Page - 263

    Playing with Google Charts 252 options:options, containerId:'chart' }); chart.draw(); Now go back to the public chart and change the data in it. You will see that it will automatically update the chart. Customizing the chart properties with an options object In this recipe, we will create a new chart with Google Charts API—a candlestick chart—and we Getting ready read more..

  • Page - 264

    Chapter 8 253 3. In the init function (from now until the end of this recipe we will remain in the init function), create a new DataTable object by using the google.visualization. arrayToDataTable method: var data = google.visualization.arrayToDataTable([ ['Mon', 10, 24, 18, 21], ['Tue', 31, 38, 55, 74], ['Wed', 50, 55, 20, 103], read more..

  • Page - 265

    Playing with Google Charts 254 How it works... we have used the method google.visualization. arrayToDataTable. This method takes in an array and returns a data table. When the second parameter of this method is set to true the data; and otherwise it will be treated as header data. There are many options and for a full list of them, review Google Charts documentation. read more..

  • Page - 266

    Chapter 8 255 How to do it... The following are the steps needed to create a basic dashboard controller: 1. 08.05.slider.js): <!DOCTYPE html> <html> <head> <title>Google Charts DASHBOARD</title> <meta charset="utf-8" /> <script src=""></script> <script read more..

  • Page - 267

    Playing with Google Charts 256 [52, 109125], [57,134708], [62,161474], [67,183450], [72,218129], [77,287370], [82,366190], [87,372552], [92,251381], [100,20892], ]); 5. Then create a new dashboard: var read more..

  • Page - 268

    Chapter 8 257 8. Last but not least, it's time to bind and draw our controller: dashboard.bind(slider, chart).draw(data); } select the age range that you want to dig deeper into. How it works... This is probably one of the smoothest parts of working with the Google Charting API. So let's for your chart. We will div layer with an ID associated for our dashboard read more..

  • Page - 269

    Playing with Google Charts 258 This dashboard is now going to be our hub where we connect all of our controllers (in our case, one controller). Then, we will create the next controller; in our case, we want to use a slider: var slider = new google.visualization.ControlWrapper({ containerId: 'filter', controlType: 'NumberRangeFilter', options: { read more..

  • Page - 270

    9 Using Google Maps In this chapter we will cover: Creating a geographic chart with the Google Visualization API Obtaining a Google API key Building a Google map Adding markers and events Customizing controls and overlapping maps Redesigning maps using styles Introduction This chapter will be dedicated to exploring some of the features available on Google Maps to get read more..

  • Page - 271

    Using Google Maps 260 Creating a geographic chart with Google Visualization API this chapter, we will start working with a vector-based map of the world. We will use it to highlight countries based on a data feed. In our case, we will use Wikipedia's list of countries as per the intentional homicide rate (latest numbers). To view this raw data go to read more..

  • Page - 272

    Chapter 9 261 How to do it... We will create a new 08.01.geo-chart.html and 08.01.geo-chart.js. Follow these steps: 1. <!DOCTYPE html> <html> <head> <title>Geo Charts</title> <meta charset="utf-8" /> <script src=""></script> <script src="./08.01.geo-chart.js"></script> read more..

  • Page - 273

    Using Google Maps 262 ['Panama',20],['Guyana',18],['Mexico',18], ['Ecuador',16], ['Nicaragua',13],['Grenada',12], ['Paraguay',12],['Russia',12], ['Barbados',11],['Costa Rica',10 ],['Bolivia',8.9], ['Estonia',7.5],['Moldova',7.4],['Haiti',6.9], ['Antigua and Barbuda',6.8],['Uruguay',6.1],['Thailand',5.3], ['Ukraine',5.2],['United States',4.7 ], read more..

  • Page - 274

    Chapter 9 263 Not all countries are alike. If you are having issues while working with a country that is outlined, search through the latest Google documents on the supported countries. For the full list, you can check the sheet available at svn/trunk/mapcoverage_filtered.html. There's more... Let's add some extra customization to our chart. As with read more..

  • Page - 275

    Using Google Maps 264 Making smaller areas more visible To solve the problem of really small invisible countries, we can switch our rendering to be marker based. Instead of highlighting the land itself, we can switch to a marker-based rendering mode: var options = {width:800,height:600, displayMode: 'markers', colorAxis: {colors: ['#22ff22', 'red']} read more..

  • Page - 276

    Chapter 9 265 Another option instead would be to zoom into the area (we can do both or just zoom in). To zoom into an area we will use this code: var options = {width:800,height:600, region:'MX', colorAxis: {colors: ['#22ff22', 'red']} }; possible values, refer back to the list of countries from earlier in this chapter. read more..

  • Page - 277

    Using Google Maps 266 Getting ready To get through this recipe you must have a Google ID; if you do not have one, you will need to create one. How to do it... Let's list the steps required to gain access to the Google API: 1. Log in to the API console at 2. Select the Services option from the left-hand side menu: 3. read more..

  • Page - 278

    Chapter 9 267 4. Again in the left-hand side menu select the API Access option. You will have to copy the API key and replace it in future Google API projects: This is the only time we will be talking about keys and permissions for working with the Google API platforms. Please validate that you have activated a key and also set the right libraries to read more..

  • Page - 279

    Using Google Maps 268 Getting ready To get through this recipe, you must have a Google ID. If you do not have one, you will need to create one. Beyond that you will need to activate the Google Maps API v3 service in the API Console. For more information on this, please review the recipe Obtaining a Google API key discussed earlier in this chapter. Our read more..

  • Page - 280

    Chapter 9 269 2. We will add to the HTML viewport information. This is the direction for mobile devices on how to render the page (this step can be skipped if you don't care about accessing the maps in mobile devices): <head> <title>Google Maps Hello world</title> <meta charset="utf-8" /> <meta name="viewport" read more..

  • Page - 281

    Using Google Maps 270 How it works... The most maps API. For Google to honor your request, you must have a valid API key. As such, don't forget to replace the bolded text with your key: <script src=" KEY &sensor=true"> The sensor parameter in the URL is mandatory and must be set to true or false. If your read more..

  • Page - 282

    Chapter 9 271 Working with latitude and longitude Latitude and longitude (lat/long) is a coordinate system that divides the Earth into a grid-like pattern, making it easy to locate points on the Earth. The lat represents the vertical space while the long represents the horizontal space. It's important to note that Google uses the World Geodetic System WGS84 standard. read more..

  • Page - 283

    Using Google Maps 272 Adding markers and events It's great that we have a map on our screen (assuming that you have followed the last recipe Building a Google map), but what about connecting data and integrating it into our map. I'm markers and events. In this sample, our goal is to place four markers in New York City. When the markers are clicked, we read more..

  • Page - 284

    Chapter 9 273 2. Create map constants in the base state and then zoom in on the state: function init() { var BASE_CENTER = new google.maps.LatLng(40.7142,- 74.0064 ); var BASE_ZOOM = 11; var BASE_MAP_TYPE = google.maps.MapTypeId.SATELLITE; var INNER_ZOOM = 14; var INNER_MAP_TYPE = google.maps.MapTypeId.ROADMAP; 3. Create the default map options: //40.7142° N, read more..

  • Page - 285

    Using Google Maps 274 map.setZoom(INNER_ZOOM); map.panTo(ev.latLng); map.setMapTypeId(INNER_MAP_TYPE); }); } 6. Last but not the least, make the map clickable. So when the user clicks on the map, it should reset to its original state: google.maps.event.addListener(map, 'click', function() { map.setZoom(BASE_ZOOM); map.panTo(BASE_CENTER); read more..

  • Page - 286

    Chapter 9 275 } function onMarkerClicked(ev){ map.setZoom(INNER_ZOOM); map.panTo(ev.latLng); map.setMapTypeId(INNER_MAP_TYPE); } The advantage is really big. Instead of creating a function for each loop, we are using the same function throughout (smarter and smaller memory footprint). In our code, we are not mentioning any hardcoded values. Instead we read more..

  • Page - 287

    Using Google Maps 276 Our main task in this recipe will be to take our work from the previous recipe, and instead of having the map zoom in and move around, create clean transitions between the zoomed in and zoomed out options; but as that isn't supported in a clean way through the interface, we will use external focuses. The idea is simple; we will stack read more..

  • Page - 288

    Chapter 9 277 2. Use CSS to stack the map's layers on top of each other: <style> html { height: 100% } body { height: 100%; margin: 0; padding: 0 } #mapIn, #mapOut { height: 100%; width:100%; position:absolute; top:0px; left:0px } </style> 3. Create the 09.05.controls.js init function in it (from this point onwards the rest read more..

  • Page - 289

    Using Google Maps 278 for(var i=0; i<aMarkers.length; i++){ marker = new google.maps.Marker({ position: aMarkers[i].local, map: mapOut, title: aMarkers[i].label }); google.maps.event.addListener(marker, 'click', onMarkerClicked); } function onMarkerClicked(ev){ mapIn.panTo(ev.latLng); $("#mapOut").fadeOut(1000); read more..

  • Page - 290

    Chapter 9 279 In our options for both the maps, we set the default controllers not to take effect by setting the property disableDefaultUI to be true, while in mapIn we set panControl to be true to showcase that the map can be panned through: var mapOut = new google.maps.Map(document.getElementById("mapOut"),{ center: BASE_CENTER, zoom: 11, read more..

  • Page - 291

    Using Google Maps 280 There's more... the map cannot move—it's not pannable. Google API v3 doesn't support the capability to disable the panning, but it does support the capability to get updated every time the map center point changes. As such we listen in to the following change: google.maps.event.addListener(mapOut, 'center_changed', function() { read more..

  • Page - 292

    Chapter 9 281 And here is a second style that we will create: Getting ready To complete this recipe, you will have to start from a copy of the previous recipe. We will only describe the new steps that differ from the last example in this recipe. To view and understand all the steps, please read the Customizing controls and overlapping maps recipe. As read more..

  • Page - 293

    Using Google Maps 282 featureType:'road', elementType: "geometry", stylers:[{color:'#C26580'}] }, { featureType:'road.arterial', elementType: "geometry", stylers:[{color:'#9B2559'}] }, { featureType:'road.highway', elementType: "geometry", stylers:[{color:'#75000D'}] }, { read more..

  • Page - 294

    Chapter 9 283 4. For the internal map, make the map-type controller visible and include in it the IDs for our new map styles: var mapIn = new google.maps.Map(document.getElementById("mapIn"),{ center: BASE_CENTER, zoom: 14, mapTypeId: google.maps.MapTypeId.ROADMAP, disableDefaultUI: true, panControl:true, mapTypeControl:true, mapTypeControlOptions: { read more..

  • Page - 295

    Using Google Maps 284 } ]; var busStyle = new google.maps.StyledMapType(aBusStyle,{name: "Buses"}); styles. Let's take a deeper look at one style rule: {stylers: [{saturation: -100}]} This example is the most basic. We have no rule, or in other words we want to apply this style to everything. As in this example we are setting the saturation to -100, we read more..

  • Page - 296

    Chapter 9 285 This is all the style information that is available, and with it we can control every style element within the map. Each style property's information needs to be sent as a separate object within the stylers array; for example, if we wanted to add a hue to our snippet, it would look like this: {stylers: [{saturation: -40},{hue:60}]} Now that we read more..

  • Page - 297

    Using Google Maps 286 This can be done by calling the setOptions function or by adding the style property when we create our map. Styles can only be added to road maps, and as such if you add this style to a map that isn't a road map, it would not be applied. As we want to add more than one style option, we have to list out the map read more..

  • Page - 298

    10 Maps in Action In this chapter we will cover the following topics: Connecting a Twitter feed to a Google map Building an advanced interactive marker Adding multiple tweets into an InfoWindow bubble Customizing the look and feel of markers Final project: building a live itinerary Introduction In this chapter on mapping, we will tie in more deeply to our read more..

  • Page - 299

    Maps in Action 288 This is the start of a very fun experiment with Google Maps. The goal of the task is to create goal. By the end of this recipe, we will have a Google map. This Google map will be clickable in any area of the screen. When the user clicks on the map, they will connect to the Twitter API and search for tweets in that area that read more..

  • Page - 300

    Chapter 10 289 <meta name="viewport" content="initial-scale=1.0, user- scalable=no" /> <style> html { height: 100% } body { height: 100%; margin: 0; padding: 0 } #map { height: 100%; width:100%; position:absolute; top:0px; left:0px } </style> <script src=" read more..

  • Page - 301

    Maps in Action 290 mapTypeId: google.maps.MapTypeId.ROADMAP, disableDefaultUI: true, }); 6. Set up the grayStyle styling object to be our default style. map.mapTypes.set('grayStyle', grayStyle); map.setMapTypeId('grayStyle'); 7. Our next step is going to use Google's API to create a new click event for the map. When the map is clicked we want to read more..

  • Page - 302

    Chapter 10 291 click will trigger a new Twitter search and will generate a new result based on the location you clicked on. To read the tweet, roll over the marker after it returns. How it works... We live in an age when data about almost anything increasingly overlaps with geolocation data and maps. It's almost impossible to write a book about data without read more..

  • Page - 303

    Maps in Action 292 We want to get our data in JSON format; to do that we will send our URL parameters to the following URL: Append to it our q values and geocode values. If you want to explore options and possibilities with the Twitter search API more deeply, visit the following page: The read more..

  • Page - 304

    Chapter 10 293 The next step in our social map project is to add more details for our Twitter search result. We would like to open up an information panel automatically when the Twitter result comes in. In the process, we will create a subclass of Google Marker and extend it and add a new InfoWindow to enable us to add live HTML data right into read more..

  • Page - 305

    Maps in Action 294 2. Now that we are not using the regular built-in marker, it's time for us to create our own marker. Let's start with the constructor. function TwitterMarker(opt){ var strTweet = this.buildTwitterHTML(opt.tweet); this.infoWindow = new google.maps.InfoWindow({ maxWidth:300, content:strTweet }); this.setValues(opt); read more..

  • Page - 306

    Chapter 10 295 str="The 50 Kilometer radius around this point did not message this value"; } return str; } If you reload your tweet, it will output it on the map within an InfoWindow. How it works... Although there are not many lines, a lot of logic is condensed into this code. Let's start by looking at our new Inheritance, as its name read more..

  • Page - 307

    Maps in Action 296 We wanted our marker to be a toggle button that controls the InfoWindow status. To do that we add a newly dynamically created property called isOpen. Even though we open up the InfoWindow earlier in the constructor, we don't set the value of isOpen TwitterMarker.prototype.onMarkerClick=function(evt){ this.isOpen=!this.isOpen; When the marker is clicked, read more..

  • Page - 308

    Chapter 10 297 features. It would be really nice if we could see more than one message in the InfoWindow result. In the next recipe we will try to solve that issue. Adding multiple tweets into an So far, in our interactive social map, we added markers in each location that we clicked on and opened up an InfoWindow with the tweet information. Our next step read more..

  • Page - 309

    Maps in Action 298 How to do it... multiple Twitter posts into our social map. 1. Let's start by changing our Twitter search to return up to 100 values per search. We are doing this because there is a limit on how many times we can call the Twitter API. So, we will try to grab as much as we can in one hit (this code should be around read more..

  • Page - 310

    Chapter 10 299 3. We want to update the TwitterMarker constructor to include our array and quick information on it, such as the total tweets and the current tweet we are in. We will need a way to identify our object, and as such, we will give it an ID as well (more on that in a few steps). function TwitterMarker(opt){ this.count = read more..

  • Page - 311

    Maps in Action 300 if(this.crnt!=0) str+="<a href='javascript:TwitterMarker. aMarkers["+("].prev();'>&lt;</a> "; str+= (this.crnt+1) + " of " + this.count; if(this.crnt<(this.count-1)) str+= "<a href='javascript:TwitterMarker.aMarkers["+("]. next();'>&gt;</a> "; str+= "</span>" read more..

  • Page - 312

    Chapter 10 301 Our goals are to create two buttons that will update our InfoWindow. This is an issue as we need a two-way connection between our marker and its InfoWindow. Until now, all our communication with the InfoWindow was one way. The easiest way for us to solve this problem and bypass the Google interface is to create a static array that will read more..

  • Page - 313

    Maps in Action 302 As this is rendered into a string to be parsed as HTML, the value that will be integrated into would be 0, and as such the prev button would look like this code statement: TwitterMarker.aMarkers[0].prev(); Now the logic is starting to reveal itself. By grabbing the marker from the array that is our current element, all that is left for us read more..

  • Page - 314

    Chapter 10 303 This will be our last recipe for social mapping. In this recipe, we will revisit our marker itself and give it a facelift. As our marker represents Twitter messages in a clicked area, we will update our marker to look like a Twitter bird (hand made). We will not stop there; after updating our graphic, we will add another graphical layer read more..

  • Page - 315

    Maps in Action 304 How to do it... previous recipe. 1. Update the showTweet function. function showTweet(a,latLng){ if(!a) a = [{text:'No tweet found in this area for this topic'}]; //console.log(obj); var marker = new TwitterMarker({ map: map, position: latLng, read more..

  • Page - 316

    Chapter 10 305 = "absolute"; this.canvas = document.createElement("CANVAS"); this.canvas.width = this.radius*2; this.canvas.height = this.radius*2; this.context = this.canvas.getContext("2d"); div.appendChild(this.canvas); this.div_ = div; var panes = this.getPanes(); panes.overlayLayer.appendChild(div); } 6. read more..

  • Page - 317

    Maps in Action 306 How it works... extending the regular marker, we have all of its default features and behaviors. One of these features is the ability to swap the icon. To do that, we pass in one of our object parameters as the icon and its path. var marker = new TwitterMarker({ map: map, position: latLng, read more..

  • Page - 318

    Chapter 10 307 The google.maps.OverlayView object has an onAdd method. It's just like a listener, but element is added into the map. MarkerCounter.prototype.onAdd = function() { var div = document.createElement('div'); = "none"; = "0px"; = "absolute"; this.canvas = read more..

  • Page - 319

    Maps in Action 308 the preceding code, we get the projection. The projection is the relative point of view of our overlay. Through this projection, we can extract the actual point in pixels. We call the projection.fromLatLngToDivPixel method and get back a point (x, y values). All that is left is to update the style of our div element and position it read more..

  • Page - 320

    Chapter 10 309 title:a.length? a[0].text : 'No tweet found in this area for this topic' , icon:"img/bird.png" }); } In case you are not familiar with the ternary operator, it's a very condensed way of creating an if...else statement within code. The core logic of it read more..

  • Page - 321

    Maps in Action 310 Final project: building a live itinerary Although the natural next step from our previous sample would be just to add an extra feature to our already growing social map (which we have built throughout this chapter), we are taking a direction shift. information of a close friend of mine in South America while I was working on this book. To read more..

  • Page - 322

    Chapter 10 311 How to do it... In this recipe we will be 1. <!DOCTYPE html> <html> <head> <title>Google Maps Markers and Events</title> <meta charset="utf-8" /> <meta name="viewport" content="initial-scale=1.0, user- scalable=no" /> <link href='' rel='stylesheet' read more..

  • Page - 323

    Maps in Action 312 position: absolute; top: 0; width: 100%; z-index: 50; } .overlayBox { left: -9999em; opacity: 0; position: absolute; z-index: 51; text-align:center; font-size:32px; read more..

  • Page - 324

    Chapter 10 313 var query = new google.visualization.Query( ' yWFJISFN3cjlqU1JnTGpOdHc'); query.send(onTripDataReady); } 4. When the document is loaded, it will trigger the onTripDataReady listener. When that happens, we will want to create a new GoogleMapTraveler object (a custom class for managing our experience). read more..

  • Page - 325

    Maps in Action 314 }], map: map }); this.traveler = new Traveler(,this.getPosition(0,1)); this.nextPathPoint(1); } 6. The getPosition method is a very smart, small method that enables us to create a new google.maps.LatLng object each time it's called and to create a point based on an average of points or read more..

  • Page - 326

    Chapter 10 315 8. In the heart of our application is the ability to automatically move from one step to the next. This logic is applied using our Animator object in combination with the nextPathPoint method: GoogleMapTraveler.prototype.nextPathPoint = function(index){ this.setPosition(index-1,2); this.pathPoints.push(this.getPosition(index-1,1)); //add last point again var read more..

  • Page - 327

    Maps in Action 316 12. Create the Traveler class. The Traveler class will be based on the work we did in the Customizing the look and feel of markers recipe in this chapter, only this time it will be an animating marker. function Traveler(map,ll) { this.ll = ll; this.radius = 15; this.innerRadius = 10; this.glowDirection = -1; read more..

  • Page - 328

    Chapter 10 317 var context = this.contextBG; context.fillStyle = "rgba(73,154,219,.4)"; context.beginPath(); context.arc(radius,radius, radius, 0, Math.PI*2, true); context.closePath(); context.fill(); context = this.contextFG; context.fillStyle = "rgb(73,154,219)"; context.beginPath(); context.arc(radius,radius, this.innerRadius, 0, Math.PI*2, true); read more..

  • Page - 329

    Maps in Action 318 13. We will grab the Animator class created in the Animating independent layers recipe in Chapter 6, Bringing Static Things to Life, and tweak it (changes are highlighted in the code snippet). function Animator(refreshRate){ this.onUpdate = function(){}; this.onComplete = function(){}; this.animQue = []; this.refreshRate = refreshRate || 35; //if read more..

  • Page - 330

    Chapter 10 319 }else{ obj[data.p] =; scope.animQue.splice(i,1); --i; } } } scope.onUpdate(); if( scope.animQue.length==0){ clearInterval(scope.interval); scope.interval = 0; //reset interval variable scope.onComplete(); } } spreadsheet. read more..

  • Page - 331

    Maps in Action 320 In the Changing data source to Google spreadsheet recipe in Chapter 8, Playing with Google Charts involved with preparing and adding a Google chart into the Google visualization. In our case, we created a chart that contains line by line all the areas through which my friend traveled. The exception in this case is that we don't want to feed read more..

  • Page - 332

    Chapter 10 321 Instead of having a very static line appearance, let's create a reveal effect for new lines that are added to the Google map. To achieve that, we need a way to update the polyline every few milliseconds to create an animation. From the get go, I know the start point and the destination point as I get that information from the Google read more..

  • Page - 333

    Maps in Action 322 Our next step will be to start and animate the values of our currentPoint until it reaches the values in the point it reaches its destination as well. We give a delay of 0.75 seconds to our second animation to keep things more interesting. this.animator.add(currentPoint,"Za",currentPoint.Za,point.Za,1); read more..

  • Page - 334

    Chapter 10 323 that will help create this application. Understanding the Traveler marker We will not dig deeply into this class, as for the most part, it's based on the work we did in the previous recipe, Customizing the look and feel of markers. The biggest difference is that we added internal animation to our element and an updatePosition method that enables read more..

  • Page - 335

    Maps in Action 324 Our second and last major update to the Animator object is that we added smarter, more detailed logic to enable our animator to animate both to positive and negative areas. Our tweaked the core animation logic. This covers the major new things we explored in this recipe. This recipe is jam-packed with many other small things we read more..

  • Page - 336

    Index Symbols A aColorsLength variable 12 addColorStop method 52 addColumn method 243 addDots function 109, 112 addLine function 79 addRows method 243 addStock function 97 advanced interactive marker building 293-296 working 295 creating 211-214 working 214, 215 animateStrokeWidth function 227 updating 323, 324 animQue array 191, 192 application OOP perspective, read more..

  • Page - 337

    326 canvas3DGraph about 211 creating 211-214 changeLineView function 172 chartInfo parameter 113 chart properties customizing, with options object 252-254 ChartWrapper used, for creating Google charts 245-247 clearRect method 13 clock building, with RaphaelJS 222-227 closePath method 12, 19 closeYOffset variable 98 complex shapes createTriangle function, creating 27 creating read more..

  • Page - 338

    327 about 217 URL 219 working 221 See also waterfall chart creating 84-87 working 87-89 formatData function 79 formatter function 101 G animating 206-208 working 209, 210 gData array 215 geographic chart creating, with Google visualization API 260-262 smaller areas, making visible 264, 265 getData function 222 getImageData function 58 getPanes method 307 read more..

  • Page - 339

    328 I array 58 image grayscale making 60 images control, adding 49 integrating, into art 46-48 scaling 49 independent layers add method, creating 188 animating 187-191 Animator constructor, creating 188 internal_animate method, creating 189 InfoVis about 229 used, for making sunburst chart 229-234 working 234-237 InfoWindow about 293-295 multiple tweets, read more..

  • Page - 340

    329 N nextPathPoint method 315 O onAdd method 307 onChangedRadio callback function 172 onChangedRadio function 148 breaking 150 onTripDataReady listener 313 OOP perspective base canvas element, moving into constructor 183 charts, creating for testing 186, 187 code, converting 178 functions, updating 179 helper function, creating 180 HTML components, creating 183-185 init read more..

  • Page - 341

    330 scatter chart about 68 data, spreading 68-75 working 73, 74 setInterval 13 setPosition method 314, 321 shadows and glows adding, in text 54 shapes creating, paths used 19-21 overlapping 35, 36 vertices, adding 31-33 showTweet function 292 spider chart 123 startIndex parameter 97 startingSpeed variable 209 stock chart about 92 creating 92-96 render options, read more..

  • Page - 342

    Thank you for buying HTML5 Graphing and Data Visualization Cookbook About Packt Publishing Mastering phpMyAdmin for Effective MySQL Management" in April 2004 and subsequently continued to specialize in publishing highly focused Our books and publications share the experiences of your fellow IT professionals in adapting and customizing today's systems, applications, and frameworks. Our read more..

  • Page - 343

    HTML5 Canvas Cookbook ISBN: 978-1-849691-36-9 Paperback: 348 pages Over 80 recipes to revolutionize the web experience with HTML5 Canvas 1. The quickest way to get up to speed with HTML5 Canvas application and game development 2. Create stunning 3D visualizations and games without Flash 3. Written in a modern, unobtrusive, and objected oriented read more..

  • Page - 344

    R Graphs Cookbook ISBN: 978-1-849513-06-7 Paperback: 272 pages Detailed hands-on recipes for creating the most useful types of graphs in R—starting from the simplest versions to more advanced applications 1. Learn to draw any type of graph or visual data representation in R 2. Filled with practical tips and techniques for creating any type of read more..

Write Your Review