 So, in case you guys don't know me, my name is Starhorn. I work for Honey Badger. We do exception monitoring, uptime monitoring, stuff like that. And today, we're going to be talking about SVG charts and graphics in Ruby. And I wanted to do this talk, and I was excited about doing this talk because, well, when we use SVG, people tend to use it as via JavaScript, you know? SVG is actually quite simple. There's really no reason why we can't manipulate it ourselves in Ruby. Like, there's nothing magical about SVG. Whereas the way that a lot of developers that I've talked to sort of see SVG is this really complicated black box thing that you have to use all these tools in order to be able to work with. But that's just not the case. So SVG is really one of the, I think, one of the most amazing technological comebacks of all time. It's a rocky of web standards, I don't know. To really understand this, you gotta go back to 1999, which is the year it came around. XML had just been invented. People thought it was going to save the world. It was amazing. People were using KDE. And if you were to go down to your local borders and pick up a copy of XML magazine, as I did, you might be forgiven for being a little bit disappointed in how the web has turned out. Because I know I am, yeah, so you guys need to get to work. Because I thought by now, at least I would be browsing the web in 3D, using VRML, interacting with the birthday cake in a really creepy rabbit. This is the creepiest image I was able to find on Google, by the way, and you can't get away from text. But I at least thought we'd be using XSLT by now, for all that. And DHH didn't actually mention this, but there's some very exciting functionality being added to Rails 5. Because who needs Hamel when you have XSLT, right? But one of these standards, SVG, is actually making a comeback. It's actually ascendant. And in case you don't know offhand, SVG stands for Scalable Vector Graphics. The big difference here is that while raster graphics are made out of pixels. So if you have a 10 by 10 raster image, and you blow that up to 1,000 by 1,000. Unless you work for CSI Miami, it's gonna look like crap. But vector images are made out of math. And so they have no real pixel dimensions, so you can scale them up or down or whatever. And that's super important lately, because the guys who make computer monitors are just on a roll. I don't know what they have, what they've been drinking, but I want some of it, I want some of their coffee. Yeah, so I'm sure a lot of you have written a MacBook Pro. I just got one, it's awesome. I just got a big 4K monitor for my desk. And it's awesome, but all this stuff has made my life a little bit more difficult as a web developer. Because I used to be able to export an image like a logo from Photoshop. And be able to assume that it would look equally crappy on all screens. But now, if I take that logo and view it on a retina screen. I'm sure you've seen this, it looks blurry, it looks even crappier than it does on a standard screen. And so okay, so easy fix, right? You just blow everything up by twice the size. But then you have files that are twice the size. They're probably being sent over mobile networks. And then once retina 2 comes out, once you get your 8K Mac Pro, then you're just screwed because you have to make a whole another set of assets that are even bigger, it's not fun. So SVG fixes this, it makes the logo pretty. So the RailsConf logo, it's actually an SVG file. So you can go and download that from their website. But annoyingly for me, Keynote does not support SVG. So this is actually a ping as a screenshot. Yeah, so this thing isn't going to scale up or down. But in addition to logos, you can use SVG for animations, for games, for stuff that you might have used Flash for in the past. I know that's a bad word. You also have visualizations. And D3 is obviously the big boy of this group, right? You can do amazing things with D3. If you haven't looked at it, I suggest that you just go scroll through the demos and you'll be amazed by just the sheer variety of visualizations that you can make with D3. For example, you can plot the spread of the zombie virus, the virus that's turning us all into zombies throughout the US, if you want. That looks pretty bad for California. You can draw node graphs showing the connections between all the people who've turned into zombies. And I don't know, I just got to say I'm ready for this. The keynote really inspired me. So I've got a go pack in the mail from Amazon Prime. But it may not be that obvious, but D3 is actually the backbone for a lot of more prosaic graphing applications. Grapping frameworks like Rickshaw use D3 under the hood to do a lot of the heavy lifting, which is great. But I mean, these are a couple of little, almost sparkline graphs that we use at Honey Badger and our user interface. We use them to show memory usage, CPU load, stuff like that. They're really simple graphs. And I was going through our code, I was going through our front end code, and I was looking for places where I could cut JavaScript. Because one of my favorite games is to cut the number of kilobytes of JavaScript that people have to download before our site works. And I noticed something, which was that the code on the right, which is D3, it's 100 kilobytes minified. If I let this run, it'll go for five minutes. I held the down arrow down for five minutes and recorded it. And the code on the left is a code that is SVG that's being generated. So I started to suspect that there might be some efficiency gains that we could achieve. And I opened up the Chrome Web Inspector. I looked at the SVG that was being generated. It's super simple. It's just XML, so I'm like, why can't I do this in Ruby? Yeah, and it turns out, well, it turns out that you got to know some SVG, which I didn't. So the first thing about SVG, what does it look like? This is what it looks like. It's XML. You don't need a doc type or anything like that. This is perfectly valid. And to use SVG in your web applications, your web pages, you just, well, the easiest way is to refer to it as an image. And that's kind of cool because you get to use all your CDNs and all your caching and it works out great. But, and this is a big but, you can't use JavaScript or CSS to manipulate the graphics at that point because it's an external resource. And so it runs into the sandboxing, the security stuff that the browsers put into place. However, you can embed SVG directly into your HTML. And when you do this, when you just copy the SVG document into your HTML, it works great. And now you can suddenly use JavaScript and CSS to do amazing things. And we'll talk about some of that in a minute. First though, let's take a quick tour of SVG. In HTML, and this is one of the big points I want to get across. SVG is not that different from HTML. In HTML, you have paragraph tags, you have heading tags, you have all these tags to describe how a document is marked up. And in SVG, you have all these tags that describe shapes and other graphics primitives. So to draw a circle, it's kind of unintuitive, but you use the circle tag. And since this is XML, you just pass in your attributes to the circle, like how what the radius is, the center point, all that, as XML attributes. And I've given it also a stroke and a fill here, just to make it a little bit more pretty. So in addition to circles, you've got, wait for it, you've got ellipses. You've got squares with a variety of corner rounding options. If you're just used to CSS, you're gonna be blown away, guys, by the corner rounding features. You've got lines, you've got polylines, which are a bunch of lines strung in to end. You've got paths, which are a bunch of lines, arcs, curves, whatever strung in to end. You can make pretty much any shape with a path. You've got text, which is text. You've got, and perhaps surprisingly, you can actually embed raster images in your SVG. You can refer to them externally, like you might with an HTML image tag. You can embed them, base64 encoded, and once they're in there, you can apply filters to them. So pretty much anything you can imagine like Photoshop doing circa 1998, you can do an SVG. So here, I've desaturated damage. I made it black and white. You can also blur them. You can do clipping masks. You can, yeah, you can do a lot of things that, in the past, you may have just automatically turned to something like image magic to accomplish. A lot of these you can do client side with SVG. And so it's pretty cool. So now, in case you didn't hear me before, SVG elements work like HTML elements. I'm just gonna let that sink in for a second. So what does that mean? Well, you can give SVG elements, you can give them classes, you can give them IDs, and then once you have those attached to the elements, like your circle or square or whatever, then you can apply CSS to them. You can add fills, strokes, etc. The attributes in CSS are, they're different from HTML CSS attributes. But I mean, it's not really that complicated. Instead of border, you use outline, instead of color, you use fill. No, instead of border, you use stroke, instead of color, you use fill, and so on. There's about five of them. And moreover, you can use JavaScript then, either plain JavaScript or jQuery, it doesn't matter, to get handles on these SVG elements. And you can manipulate them. You can change the text. You can change the font. You can do whatever you can do with normal DOM elements. And this may seem like just a party trick, but you can do some really cool stuff with it. For example, back when I was freelancing, I had a client who wanted to do an online sort of flyer creator, where the designers come up with their templates in Illustrator. They're designers, they don't know anything about code. And then they want to export those and import them into the web app, which then users can go in and customize the templates. And so you can actually do this. You just load the exported SVG into the DOM and use JavaScript to insert the user's sort of custom data into the template. It works really well. And one other thing I just want to bring up is that you can use SVG for sprite sheets. This has a lot of advantage over something like a font icon because font icons are treated as fonts by the operating system. So they get anti-aliased, they also aren't very semantic. They use these high level character codes that don't have any relation to the thing that they're representing. Whereas in SVG, you can say, hey, here's a shape, it's a heart, it's called heart. So draw me a heart, give it a class of red heart, and you style that with CSS and it's red. So anyway, so now you guys know everything there is to know about SVG. But this chart's actually wrong. Like the other half of the battle, the part that's not knowing, it's not lasers, it's actually more charts. So let's talk about charts. Like I mentioned, we use these in our application. These were sort of the inspiration for this talk. And so let's go through and build these. First, let's do a bar chart because bar charts are super easy. I'm not gonna go over this in Ruby right now because I hope once you see that how the SVG works, it should be sort of painfully obvious how to implement this in Ruby because it's actually really simple. So a bar chart is just a bunch of rectangles next to one another. And so I've drawn three rectangles. The range is like 50, 75, and 100. Those are the heights. And there are just three black rectangles. This is a really crappy bar chart because, first of all, it's like butt ugly. But second of all, it's upside down. And that has to do with the fact that, well, SVG, like most computer graphics, has its origin at the top left of the screen. Whereas most of our simple charts that we'll be making have their origins at the bottom left. And so there are a couple ways around this, right? You can add some sort of mirror transform using SVG. They have very powerful tools for transforming shapes. But just to keep things simple for now, I'm gonna add Y coordinates to just line everything up at the bottom. And we'll add some styling. We'll just use a stroke, stroke width, and fill attributes. And suddenly we have a okay looking bar chart. But what about interactivity? Now, imagine I wanna add a, when the mouse hovers over each bar, I wanna show the value of that chart, of that bar. When faced with problems like this, I tend to find that the easiest way to approach them is to just treat the SVG as if it were HTML. Like, what would I do if these bars were made out of divs? And, yeah, and it was HTML. Well, the first thing I would do is I would just draw the text on the bars. And that's what I've done here. The code I have up there is just for one bar, just to keep things simple. I'm introducing a new tag to you. It's the G tag. It stands for group. And inside the group tag, I've got a rectangle and some text. Now, one of the reasons I'm introducing the group tag is because it allows me in my CSS to do a cool thing where I hide the text by default by setting the opacity to zero. But when you hover over the group, it sets the text inside of the group to an opacity of one with a nice little fade-in effect. So I'm not going to get up here and lie to you and pretend that this is pretty or that this is anything I would show to my customers. But I'm sure you can see how this is a very real start to something. You can make a decent-looking, a decent-behaving chart out of this. So moving on to line charts. Now line charts are going to introduce us to the scariest SVG element of all time. The path, it's pretty scary. So one of the things that makes path a little bit more difficult than tags like circle and square and all that is that while circle, you have these pretty obvious attributes like a radius and a center point. With path, you have this D attribute. And the D attribute contains a list of commands and they're drawing commands. So if you've ever seen like an old school plotter, like one that actually holds a pen in place and then moves it around, the path command works a lot like that. So let's step through the commands that we're passing it via the D attribute. Well, first we tell it to move to zero ten. Don't draw anything, just move the pen there. Next, we draw a line from the current position to ten-twelve. Draw another line, draw two more lines and that gives us a really basic crappy line chart, a little spark line. So what if I wanted to make this more of an area chart and I wanted to fill in the area underneath it? There's no real CSS that tricks that I can do to make this happen. So I just draw another path. I don't stroke it with anything and I fill it with gray. And the only real difference between this path and the last is that this path is closed and that's what that Z command at the bottom does. And path has a lot of different commands. So if you're interested in this stuff, I would recommend just going and finding a list of them and playing around with it, it's pretty powerful. So let's continue making this a little bit nicer. We'll add dots to where all the points are. And those are just circle tags. So preparing this presentation, I kind of felt like, this stuff is so dumb that I almost feel bad talking about it. It's like, yeah, it's dots, you use a circle tag. But yeah, I gave it another place and people had some good feedback, so let's style it now. I'm just using the same three attributes as before. Using fill, stroke, stroke, width. I'm applying those to the dots, to the line, to the fill. And you could make this as nice and as fancy as you wanted to. You could use gradients if you wanted to, you could, yeah. You could use the same CSS trick to show the values of each dot. Or you could use JavaScript for that. There's no reason you couldn't. You just add a event handler to the dot or whatever. Or add a mouse over handler to the graph. And yeah, and do your thing. So in case you haven't noticed, the math here is pretty simple. When I went into this thing, I was a little bit concerned about the math. But the math is quite simple as long as you're doing these sort of, as long as you're doing these simple charts. And this is, you know, for the charts, the type of charts that we typically use in web applications, like they're not, they don't have to be scientifically precise. So basic math is good enough. Generally there's only two steps. You take your raw data, you convert that into some sort of graph space data. For example, imagine I have a bunch of raw data points and I wanna convert those to a scale of zero to 100. Because I wanna display percentages. Well, to do that, I'd use something like a scale function. And then imagine that I need to position those so that the bottom lines up so that we don't have a upside down graph. You could use an invert function or something like that. I'm not saying these are particularly useful functions for you, I'm just showing you the level of complexity we're dealing with. So it's time to bump it up a match. Because I was told there would be donut charts. See, Aaron isn't the only one who can make puns around here. I don't even know if that counts as a pun. I don't know, I have to ask my way. So this donut chart is made up of two paths. The first path is on the right, it's orange and second path is on the left, it's gray. Can't get any simpler than that. These paths are a little bit more complicated than with our line chart. So first, if you look at the D attribute, we're moving to point 10, zero, and that's the right most point. Then we're telling the path element to draw an arc, to draw it with a radius of 10. It says 10 twice because it's a circular arc and you can actually do elliptical arcs and those would have two different radiuses. There's a bunch of zeros and ones and those are just flags that tell SVD which way to draw the arc and stuff like that. And then there are a bunch of unrealistically, there are two unrealistically precise numbers and those are in coordinates. As a second step, we just use the line command to draw another little line inward. Then we add another arc, swinging back the other way and finally we add the Z command to close the arc. So at this point, once I got this far I was pretty happy with myself except there's one problem, right? The chart is supposed to represent zero to 100%, like a pie chart, but zero starts at, I guess, zero, it's horizontal and as the number gets bigger it sweeps this way and I'd prefer it to be like a clock just because clocks kind of make sense to me. So I'd prefer it to be where zero is at the top and then as it gets bigger it goes around. And I guess if I weren't so lazy I could go back and do all the math differently and figure out the new points, but I am lazy so I just added a transform attribute. We're not really gonna talk about this that much in this talk, but SVG has a huge, it's super powerful when it comes to being able to apply transforms to shapes and elements that you've drawn and being able to control sort of the coordinate space. Like there's a ton of stuff you can do there. So now I'll make it orange and I'll add another path. This path works just like the last one so I'm not gonna step through it, but it's just gray. So how do you get these big numbers? It's really difficult just by thinking about it to come up with the Cartesian coordinates for points on a circle, that's almost impossible. But it becomes really simple when you express the problem in terms of polar coordinates. And because in polar coordinates, well we have four points to define our donut segment and those are super easily represented as a percentage of the circle complete or degrees and a radius. Now the percentage we know because that's our data we're trying to represent. And the radius is just arbitrary. It's something we set based on how big we like our donuts. Once you have that, once you realize that, then it's just a simple matter of plugging it into a radial to the Cartesian coordinate formula. And yeah, and so then you get your unrealistically precise long numbers. So all this is great, how do you implement it in Ruby though? Like what does this look like? I'm not really gonna spend a ton of time on this because, well just because it's so simple and there's a ton of ways you can do this, right? SVG is just XML and it works a lot like HTML in that respect, you can use a builder. I really wouldn't do it this way just because it's, I don't know, it's not my style but you know, you can use it, it works. You can construct SVG using Hamel. You can do it, you can construct it within your HTML document or you can actually create complete standalone SVG files as Hamel. There's no reason you can't. And if you wanna get really sort of quick and dirty, you can just use string concatenation which I wouldn't know anything about that. I'm just gonna take a drink of water and let you guys ponder my shame. But yeah, I mean string concatenation is ugly but it's quick and dirty and if you have, if you're using your own data, there's no danger of cross-site scripting or anything weird like that. So why not, it's all numbers. So I hope, I hope I've given you a decent case for at least going and playing around with SVG of learning what you can do with SVG because it's pretty fun and once you learn a couple of things, doors really start opening and it's something that can really, I don't know, take your front end web development to the next level I think because it's a whole complex set of tools that almost nobody uses for whatever reason. Well, there are a couple reasons because SVG sucks at a lot of things and most of them are text. So SVG, the most glaring problem with SVG is that there's no word wrapping, there's no support from multi-line text which kind of makes sense when you consider its origins as trying to replace the file format for Illustrator, Illustrator in that context is going to be laying out the text however Illustrator wants to. But for us as web developers, it's a real pain in the neck because you actually have to break up the text into spans and position each of those spans. So the lesson here is to avoid doing complicated textual stuff with SVG if you can and if you can't, then there are some JavaScript solutions for laying out text and wrapping it, they're not the prettiest thing that they work, I've used them. The second major problem with SVG is that nobody's really, until recently people haven't been using it and so the documentation is not the most user-friendly stuff in the world. If you Google around you can find recent tutorials that, I don't know, have to do a lot with interacting with SVG via JavaScript and stuff like that. But if it just comes down to learning basic SVG, like what do you need to know? A lot of times you find that Googling for the answer to some problem leads you to a specification page and while specification pages can be complete, they're not really that, you'll wind up with stuff about nested transformation matrices like when you're just trying to figure out how to make something blue. It doesn't work out that well. And the third major problem, well it's not really that major, but if your users have to be able to use IE8 or below, it's not gonna work for you. And IE9 supports SVG pretty well and more modern browsers are pretty standard in their implementation. But even IE9, you'll find some weirdness, like things will work, but you'll just have to do them in a completely different way than every other browser. And I know that that's weird thinking that IE would ever do that, but that's the case. In addition, there may be issues on older versions of Android, stuff like that. So just understand your use case before you get into it. And if you are interested in learning more about this, there's a really good book. I just got done trashing Microsoft in their Explorer, but they actually published a really good book about this. So they're hypocrites. I'm sorry, I'm from Seattle, so I gotta poke the people from Redmond whenever I can. So anyway, it's a really good book. I highly recommend it if you're interested. So yeah, so thank you. If you're interested in learning more about this stuff, I post blog posts occasionally and stuff, and I'll post them out on my Twitter. And yeah, and that's it. Does anybody have any questions? Okay, the question was, what is a good non-programmatic way to build SVG if you are just sort of getting started with it? Well, when I was just getting started with it, I found that the easiest thing to do, and the simplest thing, was just to use my normal text editor and load the file in Chrome, like Chrome can open SVG files, and just do it like you learned how to develop HTML, where you make a change, you see what happens, make another change, see what happens, beat your head against a wall for an hour, and then yeah, and so you can do that. Another interesting thing that you can do that I mentioned briefly, is you can actually export somewhat readable SVG from Illustrator. So if you're dealing with something like a logo and you wanna see how that's put together, you can export it as SVG from Illustrator, and yeah, and one of the cool things about that is that if you have an icon or a logo, and you wanna tweak the color of that just a little bit, you don't have to go back into Illustrator and do that, you just open it up as a text file and change the hex code. Okay, so the question was, what unit were all my numbers? And I thought you were my friend, Caleb, because that's the question I was glossing over. So SVG is kind of weird about units because it's a scalable format, it's a vector format, but a lot of times you'll see units expressed in pixels, which sort of seems a little bit weird. Essentially what happens is that SVG has a pretty sophisticated system for defining what are called view boxes, and you're drawing within those view boxes. So you can define a view box that's like 100 pixels by 100 pixels wide. And then if you draw something that say 10, it will assume that you mean 10 pixels, and then so it'll take up one tenth of the height or whatever. And once I get scaled, it'll get scaled up in proportion. But yeah, you can also make non-scalable SVG, which is kind of weird. You can actually set, fix dimensions and have everything be exact pixels if you want, but that kind of eliminates the point a lot of times. Okay, so the question is, if you have a bunch of large SVG files that some designer has given you, how do you reduce the file size? So it kind of depends. My first step would be to open up the SVG and a text editor and sort of see what it looks like. If you're exporting from say illustrator, which is how, that's how the most complex SVG files I've seen have come to me. If you're exporting from illustrator, you'll find that it may be doing weird things and may be embedding a 20 megabyte image in the middle of your SVG file. And in that case, you might want to open up and illustrator reduce the size of that image and resave it. If there's no obvious structural problems with the file, if there's no obvious place where you can get efficiency, then I would definitely look into, there is an SVG, I think it's SVGZ, it's a compressed SVG format, but you can also serve them as compressed files. If you're loading an SVG file as a separate asset, you can serve it as a compressed, a Jesus compressed file, so. I mean, I'm not sure there's any magic bullets there, but there are a few things you can do. I haven't, the question was, what happens when the SVG files become large or do they become unperformantly slow? And my answer to that is, I mean, it probably depends on your device. If you're viewing it with an older Android tablet or something, then it's probably gonna get a lot slower than if you're viewing it on a MacBook. I personally have dealt with, in addition to these little graphs and stuff, but I personally dealt with some fairly complex SVG files and they seem to load and perform reasonably well. I haven't done a lot of these crazy visualizations where you have 20,000 points in mind and stuff. So I don't really have any experience there, but yeah, for smaller and medium scale files, I've experienced no performance problems. And one benefit that SVG does have over Canvas is that, well, with Canvas, once you've drawn something to the screen, it's there as pixels, but with SVG, you at least have the ability to, in theory, sort of save it as a separate file to export it and then use it in other contexts at different sizes and so forth. Okay, so the question was, would a complex SVG file be slower to load than a raster file? And I wanna say it depends, but I know that's not a helpful answer at all. Let's take, for example, the logo, like the RailsConf logo. At a really small resolution, at 100 pixels by 100 pixels, the ping version of that is going to be, it's gonna be smaller than the SVG version probably. But once you start serving larger versions of that file, the SVG file, or the SVG starts winning in terms of file size by a lot. So if you needed to serve like a 500 pixel or 1,000 pixel by 1,000 pixel version of that same logo, then the SVG version is gonna be a lot smaller probably. In terms of, yeah, in terms of complexity, it really just depends. But I've generally found that when I've replaced image assets with SVG assets, the SVG is smaller. Yeah, so the question is, is SVG capable of being dynamically sort of scaled, changed on the fly based on your user data? And yeah, absolutely yes. There are, you can animate SVG using CSS3 transformations, there are a lot of JavaScript libraries that let you do this, like a snap, which I showed in a screenshot. And there's also, I forget the name of it, there's actually a kind of clunky SVG native animation way of doing things. But yeah, you can definitely do this. And it's like, if you go to, if you look at the snap website, I think it's snap.js, then you'll see a lot of cool examples of SVG being dynamically generated on the fly. I think D3 does that too, like for charts that are updated automatically and stuff. Okay, I don't see anybody. So if I'm missing you, yell. You have five seconds. Four, three, two, one. All right, you're free. Thank you.