 We're going to be talking about SVG charts and graphics in Ruby. So anyway, SVG. SVG is one of the big comeback stories in the tech world, I think. Because SVG started out back in around 1999, like a long time ago before the bubble burst, like the bubble that was before the big bubble that just burst a while ago. And XML had been invented a couple of years ago. And if you were to go into your local borders and buy a copy of XML magazine, you'd be forgiven for thinking that XML was just about the greatest thing that had ever been invented in the history of mankind ever. I mean, I know I was. And I got to say, guys, I'm kind of disappointed with how things have turned out. Because by now, I expected at least to be browsing the web in 3D using the power of VRML. And this is the creepiest image I could find, by the way. Yeah, it's Netscape. It's a VRML plugin for Netscape. I think I actually use that. I may have actually seen this rabbit guy. So yeah, I expect to be doing that. And for the boring text pages, those should definitely be rendered using XSLT, right? Because I mean, who needs Hamel when you got XSLT? And for the graphics, well, those are going to be SVG. And this is actually coming true a little bit. SVG is making a comeback, like I said. Now, why is that? And what is SVG anyway? It stands for Scalable Vector Graphics. And you all know this, but I'll go through it for the viewing audience at home. Raster graphics, your normal JPEGs, GIFs, pings, all that, are made up of pixels, right? And if you take a 10 pixel by 10 pixel image and enlarge it to 1,000 by 1,000, it looks like crap, unless you're on CSI Miami. And but vector images don't have that problem, because they're defined mathematically. You can scale them up and down as much as you want. That's fine. And the reason this is becoming more and more important is that, well, the people who make the screens for our devices, for our desktops and all that, they've been on a crazy terror lately. This shows the growth in pixels and screens. I don't know if there's actually an 8K UHD display out there, but I just got a 4K one. It's pretty cool. And they're not only adding more pixels there, they're cramming them into a smaller and smaller space. Penciled density is getting lower and lower, which on the one hand is kind of cool, because it makes everything look sharp and all that. But on the other hand, it's a real pain in the neck for us web developers, because we got to make the logo look good. You know, I used to, in the good old days, I used to be able to export a PNG from Photoshop and send it to my users through the web and be assured that it would look uniformly crappy on every monitor. And now I just don't have that assurance anymore, right? If I use the old sort of standard resolution for my logo, then it's gonna look crappy on retina monitors because they scale things up, or yeah, they scale things up and it looks sort of fuzzy around the edges. If I increase the image size by two times so that it gets scaled in retina to a nice size and looks good on retina, then who knows what it's gonna look like on HTC screen or whatever. And we're all just gonna be screwed whenever Apple comes out with retina 2.0. And so, anyway, I just wanna propose, I like proposing rules and talks, so this is Star's first rule of web design. You gotta make the logo look good. And SVG makes the logo look good. That's probably one of the nicest use cases for it. But as I'm sure you know, it's also great for cool things like illustrations. This is a really neat JavaScript library called SNAP, which you can use to make, there I say almost flashlight animations like if you wanted to do a cool intro page for your website, you could do it using this or, I don't know, I don't mean to make fun of them, but it's a really cool project. There's also graphs and the 800 pound gorilla in the graphing industry has gotta be D3. You can do amazing things with D3, right? You can map the outbreak of measles across the United States. You can make crazy charts showing interconnectedness between people who have the measles. I'm kinda worried about measles. No, I'm just trying to get a rise out of people. And anyway, you can use it for charts, right? And not only can you use D3 for charts, but actually D3 is a foundation for a lot of charting libraries that we use. Like a lot of charting libraries like Rickshaw will rely on D3 to do actual heavy lifting. And this posed a problem for me because, have you ever had this experience where you're looking through some code, you're trying to make some changes, make things better, maybe make things more efficient? And you're like, man, who is the idiot that wrote this? And then you go to get diff and it turns out it was you. So that's basically my life. So I didn't know anything about SVG at this point, but I knew that these charts were pretty simple. Like they can't be that complex. And so I opened up the web inspector in Chrome and actually inspected the SVG code. And just as an illustration, I put the code for one of those graphs on the left-hand window. And on the right is D3. And it keeps going for five minutes. I pressed the down button for five minutes and recorded it all. See, this is the point where I have you guys in the palm of my hand. I can make you suffer so badly. So anyway, it's about 100K minified. And it just really, really, really started to annoy me that we were using this 100K library to generate some about three lines of SVG code. You know, I wondered if maybe it wouldn't be more efficient if we rolled our own in Ruby. But like I said, I didn't know anything about SVG. So step one, what the heck does SVG even look like, right? It looks like this. It looks mostly like XML, HTML, whatever. You actually don't need a doc type or anything like that. This is valid. You can use it in your web apps or your web pages a number of ways. Easiest is probably to just treat it like an image. You can use it in an IMG tag. You can also use it as a background image. It's really handy for stuff like that. The second way to treat SVG as an external resource is to use the object tag, which gives you some nice fallback, a fallback mechanism, and it allows you to do some JavaScript manipulation, but not all the JavaScript manipulation that you might want to. And these approaches are nice for caching. You get browser caching for free just like with any type of image, but you can't style them with CSS really, and you can't, well, I mean, you can do some JavaScript, but it's kind of limited. So if you're looking for the most flexibility, the next approach is probably your best bet, which is just to embed the SVG directly into the HTML. And this works too. Obviously you have to use fragment caching or some other sort of text caching. You can't use browser caching for this. But you can manipulate this with your applications CSS and JavaScript, which is pretty cool, and I'll show you how to do that a little bit later. But first, let's take a tour. What does CSS look like? So just like in HTML, you have a bunch of tags like paragraph and h1 and all this. Basically, these are markup tags for describing documents, for describing text-based things. SVG is really similar, but you're describing shapes instead of text-based stuff. So we have shapes, right? You can draw a circle using the circle tag. You can have an ellipse. Ellipses have two radii. I actually distinctly remember nodding off in math class when they covered ellipses. And so, yeah, they intimidate me a little bit, but I'm not gonna show it. I'm gonna be brave. You can do rectangles. You have all sorts of crazy, amazing rounding options for the corners. You've got lines. You've got polylines, which are a bunch of lines strung together. You've got paths, which are a bunch of either lines or nonlinear segments that are strung together. You got text. And last but not least, you can actually embed and manipulate raster images inside of SVG. In this case, I'm loading an image from an external URL and on one copy of it, I'm running a filter that makes it black and white. You can do, basically you can do a lot of things that you might otherwise have to use Photoshop filters for or something like that, just with pure SVG, which gives you some interesting options around image manipulation that may have not been open to you before. And the cool thing is that if you're in the browser, SVG works a lot like HTML. Like you can use your same old bag of tricks. You can give SVG elements a ID. You can give them classes. And then you can use CSS selectors to style them. You can use document get element by ID or you can use even jQuery to get a reference to an SVG element and then you can change the text. You can change the font. You can really do a lot of stuff. And this may sound somewhat useful, but it opens up a world of possibility because it means that you can actually manipulate vector graphics in the browser. Say for example that you wanted to generate a bunch of custom, I don't know, postcards or something, a new postcard for every one of your user. And each of those postcards needed to have custom text, maybe a custom image on it, whatever. You could have your browser design or your browser, have your designer create the design in Illustrator, export that to SVG. You load that into your browser and then you can manipulate the SVG and swap out the text or do whatever you like with it. And then use something like something like phantom.js to print it to PDF. Which I'm not just making that up. I've actually done something like that. So, congratulations. You guys are now SVG experts. Everything there is to know. But that's the only half of the battle. The other half, I know this is the most overused chart ever, but I like it. Anyway, the other half is not red lasers or blue lasers. The other half is making some charts. So, we're gonna make three types of chart. We're gonna make a bar chart, we're gonna make a line chart, which is not shown here. And we're gonna make a donut chart. So, let's get started. Bar charts. Oh yeah, I just wanted to mention also, I'm just gonna be implementing these in SVG for now. Basically, putting these in and making these dynamic in Ruby is gonna be almost trivial. So, we're gonna focus on the SVG so we can see how things are actually put together and understand that a little bit better. So, what is a bar chart? A bar chart is just three rectangles that are next to one another, or however many rectangles, I chose three. I've given each of the rectangles a height corresponding to some value, some percentage, 50, 75, and 100. I'm imagining those are percentages. And so, now we have kind of a bar chart, but it's upside down, that's the problem, right? Because, well, most charts start at, the origin is at the bottom left, but SVG, like a lot of computer graphics, sets the origin at the top left of the screen. So, we actually have to position each of these bars so that they line up at the bottom. And you do that by setting the Y value to the maximum height of your graph minus the height of the bar. Am I getting feedback? Okay, I just stepped back a step and I thought I got some, so I'm just gonna stay right here. So, this is a really ugly chart, but we can use CSS to style it really easily. In this case, I'm using, I'm adding a stroke, a white stroke that separates out the bars. In SVG, you don't use CSS attributes like background and border. Instead, you use stroke, which is sort of like a border, and you use fill, which is kind of like the background. So, this is alright, I guess, but we want everything to be interactive, right? So, what if you wanted to show the value of the bar when you mouse over the bar? To do this, I'm gonna take an approach I would probably take even if I was implementing this using HTML on these bars where it just divs. First, I'm going to print out the value at the bottom of each bar, or wherever I want it. And I've only shown the code for one of these bars so that it's a little bit more clear. I'm grouping together using the G element, the rectangle and the text. And the G element is nice because it, not only does it allow you to structure your documents in a way that makes a little bit more sense than just having everything at a base level, it also lets you play tricks with the origin so you can do things like relative positioning. And then to add the interactivity, I'm just gonna use some CSS. I hide the numbers by default, and yeah, when you hover over it, I show them with a transition. It's not showing the animation on here, so that's why I'm leaning back. All right, so bar charts are conquered. Line charts are next. When we get done, you guys are gonna be able to make your own D3 and Ruby. And when you do, please tell me because I would like to use it. So for a line chart, I'm gonna introduce an element called a path. As I mentioned before, a path is made up of multiple segments, and they can be lines, they can be arcs, they can be bezier curves, whatever you like. But the main thing to know about the path is what this D attribute does. The D attribute is essentially a list of commands, and I've broken the commands out and separated them onto separate lines so you can see that a little bit easier. Basically, you can imagine this like you're giving commands to a person holding a pencil, or like you're writing a program for one of those old plotters that actually like holds a pen and a little device and moves it around. So first I'm telling it to move to 0.10, and then I'm telling it to draw a bunch of lines to the different points which are my data points. And that's pretty easy, right? So let's add a fill to that. To do that, I'm just gonna copy my original path, and instead of leaving it open and just having a line or a stroke, I'm gonna close it and add a fill of like gray. To add points, it's very easy to just, oh, okay, it's easy to just add circles each to your data points. And if you wanna make it pretty and use some CSS, you can use those same attributes. I'm just using fill, stroke, stroke, width to make this a little bit prettier. And the math for this is really simple. Like the math we've used so far, it almost doesn't even feel like math, it just feels like programming. But generally I found that when you're creating charts, it's easy to think about the math as sort of a three-stage process or a three-step process. And the first, you have your original raw data. This may be, I don't know, say I know how much RAM a server is using. And then I want to project that into a abstract sort of graph space. And as an example, say I wanna take that amount of RAM and I project that into zero to 100%. And then as the third and final step, I project that zero to 100% into a pixel space. I'm using scare quotes with pixels because with SVG pixels are kind of a nebulous thing. But still I convert the percentages to either heights or rotations or whatever. And I found generally that pretty much all the math I do boils down to a scale function where I say map my data into a space of one to 100% or something, and an invert function to just take care of the fact that SVG starts drawing at the top left of the screen. All right, so two charts down. We have one to go, the donut chart. The donut chart is the most complicated beast of a chart. Okay, it's not that complicated, but what this chart is actually made up of is made up of two paths. The one on the right, yeah, on your right, is the actual representation of the data. And the one on the left is a background, this is there to make it pretty. So let's get started. First we're gonna start by drawing the right path. So if you'll take a look at the D attribute, we start by moving to 10, zero. And then I tell it to draw a circular arc. That's what that A is right there. We tell it to draw a circular arc with a radius of 10. And the reason that says 10 twice is that you could actually add two radiuses and do a elliptical arc. We've got a couple bits that tell it which direction to draw in. And then we have the end point, which is calculated by the computer. Yeah, I didn't do that by hand. So the next step, we add a line into the inner radius, just using the same L command that we used for our bar chart. Then we draw the inner radius, which is another arc. This is a little bit smaller. Finally, we close the path by using the Z command. And I don't know if you guys have noticed this, but the graph is rotated 90 degrees from the direction that I want it. And I suppose I could go back and fix all my math, but I'm just gonna be lazy and add a transform and rotate the whole thing 90 degrees. So we'll add some CSS to change the background. And then we'll add that second path, which is a lot like the first path. So the math here is not quite as complicated as it may seem. I mean, you wind up with these values with a million decimal places and whatever, but it's actually really simple. If you first start thinking in terms of polar coordinates, because if we're trying to represent values from zero to 100, then those can be mapped onto a circle as zero to 360 degrees. And that combined with the radius gives you the ability to define every point that we use there. And so now all we need to do is convert those to Cartesian coordinates because SVT always uses Cartesian. And you just use a trig formula that you can look up online easily. And there you have it. So I'm not going to go into exactly how you would generate the XML with Ruby because that would be kind of boring. But if you're interested in a really sort of bare bones implementation of this, I have this on GitHub. We use this in our app, but I wouldn't recommend that you do it because I might change it at any point. All right, so this next slide, I think every talk should have this slide in it because it seems to me like putting together a talk is more about what you leave out than what you put in. It's all about stepping gingerly around all the dragons that you've discovered or lying there asleep just waiting to devour you. And the first major dragon that you'll face if you try and do something complicated with SVG is that it's not meant to deal with large amounts of text. It doesn't do what HTML does. There are a couple of ways around this. The first is that you can actually, in some browsers, you can embed HTML into your SVG. In other cases, since SVG doesn't support WordRap natively, you can use something like JavaScript to go in and create your own WordRap functions and create your own centering functions and stuff like that. And so if you see SVG that uses text and has text nicely centered and everything, chances are they're using JavaScript to do that. The coordinate systems, I dipped it a little bit into this with the G element and doing relative positioning and stuff like that. But coordinate systems can be a little bit hairy to figure out exactly what you're defining your elements relative to and all that. If you don't start down that road, if you don't ever do any tricks with the coordinate systems, everything is simple. But as soon as you start to get tricky with the coordinate systems, you can find yourself possibly writing things to a Cartesian coordinate system that actually when it's displayed on screen is rotated by a certain amount and it just gets weird. And the documentation is, it's there and it's okay, but people don't use SVG as widely as they do, say HTML. And so the documentation isn't quite as good as perhaps we're used to. So you kind of have to do a bit of trial and error. The standard hasn't changed, I don't think at all since around 2000, although I think there's supposed to be a new version in the works. But anyway, I have faith. I think you guys can do it if you're interested in that because I did it and I wasn't that big of a deal. If you're interested in learning more in this, I suggest that you buy this book, which I did not write, but it's really good even though it's published by Microsoft. And, well, they fought SVG for years, so maybe it would have been adopted a little bit sooner before that. But I guess, yeah, who among us isn't a hypocrite. So anyway, that's it. Thank you guys for listening to my talk on SVG.