Code Your Own Generative Art
Writing code to expand your creative capabilities is a fun way to stretch your knowledge of what code can do. One of the best creative technologists in the game, Nat Alison, will teach us how it’s done.
Links & Resources
Click to expand the full transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON LENGSTORF: Hello, everyone. And, welcome to another episode of Learn With Jason. Today, on the show, we're bringing in Nat Alison. I'm so excited. I feel like I've been looking forward to this episode for so long because we scheduled, a while back, to do an episode and life happened and it didn't work out. Here we are, we got it rescheduled.
So, before I talk about what we're going to today, let's talk a little bit about you. For folks who aren't familiar?
NAT ALISON: I am a freelance� mostlyfreelance software engineer, mostly focused on frontend work, mostly focusing on weird visualization and, like, a lot of mathy stuff. And, a lot of generative art, which is what we're going to be doing today. So, yeah.
JASON LENGSTORF: Yeah, I first think� I think the first thing I saw from you that kind of really blew my mind, you did the Polyhedra site. Every single shade.
NAT ALISON: Every shape you can make that can transform into each other and rotate and squish into each other and stuff.
JASON LENGSTORF: I remember seeing that and I just thought to myself, that's a thing� I don't even know how to begin to wrap my mind around how to build something like that. I've always seen you work on projects that make me laugh or may me scratch my head and figure out how it works. [Laughter]. And those are my two, favorite qualities in a creator. [Laughter]. So, today, we're going to work a little bit on some generative art and for folks who aren't familiar, do you maybe want to do a highlevel of what generative art is?
NAT ALISON: Yeah. Generative art is art that you generate with a computer, using some sort of algorithm or code or a random seed that you can� that you can, like, specify how it's generated. It's� yeah. It's really pretty broad and people have stuff from very, like, basic, simple shapes to completely wild stuff with, like, shaders that I don't really know how to do. Yeah.
JASON LENGSTORF: Yeah, and it's a very cool field because one of the things that I think is a trap that I've fallen into� and I think a lot of us fall into� is we look at code as being� it's the thing we do for work. And, sometimes you can� you can look at the thing that you do for work and, like, work on a hobby project and that feels like, hey, I'm playing, it's a hobby. But we don't really look at code� at least I tend to forget that code is a creative medium, as well, where you can build things that are an actual expression of something that doesn't need to be built with an explicit purpose, other than seeing if you can make something that looks cool or gives you that sense of, wow, that's really interesting. Or, wow, that's incredible.
So I'm always really excited to talk to folks who have remembered that, who have steered into the creative aspect of coding and using it as a medium of expression as opposed to solely leaning on it as a way to accomplish work, very specificallydefined work.
So, a couple ways that I've seen generative art happen, that you know, that really blow my mind is, like, we had Shar Styles on the show who uses shaders and she helped me put together� we plugged into the Web Audio API and she was showing me how to make the shader move based on what the sound levels do. I was like, oh, my god, this is really cool. There are also really practical applications where you can use it for work. For example, when I was at Netlify, I worked with George Francis who does generative art with CSS and CSS Houdini and he had made a thing that you could put in, like, a random number and it would generate a similar, but different placeholder image for the Netlify blog so that you had something that was always unique, but that felt like it was part of a Netlify brand.
So, even if you want to use generative art for a practical work purpose, you can, as demonstrated by folks like George. So, at its core, what� I guess, like, what is the� the baseline thing that you're doing with a piece of generative art? Because I think for a lot of us, we're looking at it and what I see is you say, look at this thing. And I go to it and magic is happening. What's Step Zero here? What are the component parts of generative art?
NAT ALISON: The component parts? I honestly don't know. I just take a blank canvas and I start, like, messing around with it until it leads to something. Usually, you start with, like, an idea or a core concept that you want to get through. Like, what do you want it to look like? You sketch out a couple examples or start with something databased, where you have to start with data and you start molding it and see if you can come up with a way to turn it into something, like, pretty.
I know you've done stuff with data visualization. I only watched the first episode of that, where you didn't actually do any code so I don't know if it ended up working, I'm sure it did. [Laughter].
JASON LENGSTORF: Shirley and I have done three projects and we have yet it to finish one, but she's really fun to talk to. [Laughter].
NAT ALISON: You start with a scaffold to start running stuff and then you iterate on it and you can add this thing, can I add this other thing, until it start looks like what you want. You can start off with something very simple. Maybe, just, like, doesn't need a generator at all and it just generates a very, like, a fixed thing and you put in a seed in it and then watch the thing change. And then you put in another one and watch how that changes and you keep adding more parameters and add more variation until it becomes extremely, uh, until it becomes extreme� something that you like.
JASON LENGSTORF: Yeah.
NAT ALISON: And then you put it away because you have to do something else and you come back and add more functionality to it.
JASON LENGSTORF: Yeah, for sure. And I think that, you know, the thing that I've always found really interesting about this is you can make these very� what's the computer word? Deterministic. If you put in a random seed, if you put in the same seed, you get the same output or you can check the clock and, like, do stuff based on time moving forward.
NAT ALISON: Use a thousand lava lamps to generate a seed. [Laughter].
JASON LENGSTORF: Wait, is that a real project?
NAT ALISON: Yeah. Cloud First office has a wall of lava lamps. They're sufficiently random enough. [Laughter].
JASON LENGSTORF: That's incredible.
Think about this from a practical standpoint, let's talk about what we're going to do today. We wanted to source some ideas from the chat. So, y'all, start warming up your thinking machines because we're going to be asking you for ideas. So, let's set some parameters. What should we think as our guardrails for what we want to build today?
NAT ALISON: I think just generally something that would be relatively simple to do with SVG because that's what I have the most experience in. If we're feeling pretty spicy, we could do Canvas. Any one of those two.
JASON LENGSTORF: Let's see if we can do SVG and so what I'm thinking is that we're open up CodePen and we'll just start throwing things in and seeing what we can come up with. And, I have� let's see...SVGwise, I have a few things we could grab, like images or things I've been in Figma. I think we could do straightup SVGs. What do you think, chat? Infinite cat fractal.
Um...let's see, so, here's what I'm going to do. I'm going to get us moved over into the pair programming view. So, let me switch this one over here. And then, I'm going to get...a new tab open and pull that out here. And for some reason, that's teenytiny, so we'll make that bigger. All right. So, this episode, like every episode, is being livecaptioned. We've got Vanessa here from White Coat Captioning. We've got Netlify, Nx, New Relic and Pluralsight.
We are talking to Nat today, so let me pull up the Twitter. I'll throw this into the Discord chat for folks. Okay. All right. And, we're going to play CodePen today. So I'm going to come in here. I guess I need to log in again...and, I'll create a new pen. And now I don't know what to do next.
NAT ALISON: Well, did you want to send me the link to the SVG, to the Code Pen, are we going to pair program?
JASON LENGSTORF: Sure, if you want. Let me�
NAT ALISON: First of all�
JASON LENGSTORF: Let me see. I've done this before and I always forget how to do it. I'm going to save it. I'm going to give it a name...and then, I think� is it� where's the button? Nope, that's not it. What have I done? I'm looking right at this. Where's the button to do the shared one? Oh, here we go. Here we go. So, Collab Mode. I'll send this to you. And then...[coughing]. Got to get this� there you go. Turn this back on. Editor View...there we go. Okay. So, we have a blank canvas and anything that we do in here is going to show up live. There we go. So, now we can start just...putting stuff in here.
NAT ALISON: So, the first thing that's probably a good idea is to have an idea of what we want to do, so, chat has� does chat have any ideas? Are going to do the infinite cat fractal spiral, whatever?
JASON LENGSTORF: We can� we can definitely play with something like that. Maybe the first thing we can do is just start with the very basics. Like, can we get something on the screen, where we're generating something with code and it can just be, like, circles or something to get the basic ideas and then we'll kind of refine it from there.
NAT ALISON: Yeah. We could, um� first, we should have an SVG on the screen.
JASON LENGSTORF: Get an SVG onscreen. Okay, so I have, um...if I get to my...Figma, I have a couple goofy things that I've been working on. Which one of these? Here, I think.
NAT ALISON: Oh, oh, Jason, we're not going to put an existing SVG on the screen. We're going to make an SVG.
JASON LENGSTORF: I understand. [Laughter]. All right. So, I have� I have an SVG.
NAT ALISON: Uhhuh. I think you need to set the width and the height to a normal amount of width and height.
JASON LENGSTORF: Let's go with a 400x400.
NAT ALISON: Maybe you can, like, set a border on it to figure out where our boundaries are, while it's a blank canvas like this.
JASON LENGSTORF: I think the most popular debugging tool in CSS, the onepixel red border.
NAT ALISON: Uhhuh. And now, we are going to add a bunch of circles here. Um, so, in our JS, probably give an ID to the SVG.
JASON LENGSTORF: Okay. We'll call it "art."
NAT ALISON: High expectations. Setting up ourselves for success. [Laughter].
JASON LENGSTORF: So then I'm going to grab this document.getelement by ID. And we'll go with "art." And now we have it to work with.
NAT ALISON: Yep. So, if we want to draw in a bunch of circles, all we have to do is append a bunch of circle elements. So, it's� make a four loop, iterate from one to how many circles you want.
JASON LENGSTORF: Let's see if I can remember how to do a four loop. I is zero. I is less than?
NAT ALISON: 400, same as our width and height. Actually, that might not be a good idea. Maybe let's just do 20 circles. [Laughter]. I++...
JASON LENGSTORF: Okay.
NAT ALISON: Um, yeah, so we want to append a circle.
JASON LENGSTORF: So, do we� do I need to create it first and then append it, right?
NAT ALISON: Honestly, I'm so used to React� to, like, using React and other componentbased libraries so I don't remember how to append an element.
JASON LENGSTORF: I think what we do is if we set up a circle and that would be a "document create element." Once we get into SVG, I don't know if we have to use something other than Create Element.
NAT ALISON: I think it's actually HTML. And then you just need to set the attributes to it.
JASON LENGSTORF: And is it...straightup like that. Let's play it safe and set attribute and the attribute is going to be width�
NAT ALISON: They have a radius.
JASON LENGSTORF: Is it spelled out or is it "r"?
NAT ALISON: It's "r."
JASON LENGSTORF: And how big do we want these to be, do you think?
NAT ALISON: Let's say, five pixels for now.
JASON LENGSTORF: Do I need units?
JASON LENGSTORF: Math.round and math.random and the random needs to be multiplied against�
NAT ALISON: The width. I think it's svg.width.
JASON LENGSTORF: SVG...okay. And then should I do the same thing�
NAT ALISON: Yes. For y and height.
JASON LENGSTORF: Okay. And then, I think down here, we do svg.append...and child� oh, is this going to work? Let's find out...then, we probably need to set a color on these, right?
NAT ALISON: Yes. For circle, it's going to be�
JASON LENGSTORF: Fill, not color?
NAT ALISON: Uhhuh.
JASON LENGSTORF: Let's go here and see if we can make it work...I think I broke it...expected token...okay. So, I did the math.round, the math.random.
NAT ALISON: Did I break it? No.
JASON LENGSTORF: This is all valid, isn't it?
NAT ALISON: I think so.
JASON LENGSTORF: Let's try it again. Could also be that this is doing it, but not actually working and that is entirely possible because I just wrote all of that from memory, so, inside of our SVG, we have a bunch of circles but my x and y are not a number and that is okay because that means probably this didn't work? Let's consolelog the width and height and make sure that that's correct.
NAT ALISON: Yeah.
JASON LENGSTORF: Width and height...so, I think maybe it needs to be, like "attribute"? Whoa!
NAT ALISON: It's Canvas to automatically access the width and height. I think an attribute should work.
JASON LENGSTORF: Get Attribute looks like it's working for us, which is great. We can set these up as w and...keep the math a little bit...our code will be a little bit less.
NAT ALISON: Make an h?
JASON LENGSTORF: H and w. Okay. So, we're closer, now. No errors. But...something still didn't work and that "something" is...
NAT ALISON: Let's see. The circles are there.
JASON LENGSTORF: The circles are here, but they're not actually visible.
NAT ALISON: Oh, I think it's rx and not x and y? Is that? No...
JASON LENGSTORF: Should we, like, forcecode one.
NAT ALISON: Oh, I'm sorry. It's cx for Center X. SVG is very consistent and logical. [Laughter].
JASON LENGSTORF: What gives? Where you at? This is the hardest part, getting through the initial...okay. So, they still aren't rendering. Do they need anything that we haven't provided to make them render? Because they don't look like they're showing up onscreen at all.
NAT ALISON: I tried a stroke, that doesn't seem to be working.
JASON LENGSTORF: So, we're going to set our radius to 5. We'll set the cx to 100 is fine. Cy...
NAT ALISON: Okay. That seems to be working.
JASON LENGSTORF: Okay. So that one's working. So why wouldn't these ones want to work?
NAT ALISON: They're just very shy circles.
JASON LENGSTORF: I swear, I did this and found the issue. Like, there was something I was doing...I wonder if it needs to be...if it's something to do with us, like, adding it after the fact and we have to�
NAT ALISON: Uh. Uhhuh.
JASON LENGSTORF: Hmm. Do you think, if we try to...create the SVG onthefly, as well. We do a container and actually create our SVG in here. Let's try this and see if it'll do it. So, I'm going to copy this...and we're going to get our container. And then, inside of our container, we want to create this. So, I'm going to copy this one and then we'll comment it out and then we'll just...equals document create element. We'll make that an SVG and then "svg.setattribute" and do the same thing for height. And we'll continue to add these pieces, here, but then what we need to do is we've appended to the SVG and then once we're here, we'll container.appendchildsvg. What do we got? Nothing.
Okay. What have I done? Chat, do you see it?
NAT ALISON: I wonder if it's something CodePenspecific?
JASON LENGSTORF: Oh, that would be interesting. Did I typo somewhere? SVG. SVG...okay. So, we're not getting any errors anymore. And we're also not getting...there's our container, there's our SVG. Somebody's suggesting a view box?
NAT ALISON: Uhhh...we can try it, but also, I think that would have made the other thing not work, as well.
JASON LENGSTORF: So strangely enough, it is appending now. But it's set to� like, it doesn't have a width. So, it's coming out as 2 and 20 for reasons unbeknownst to me. Maybe we need to set it to� this can't be right.
NAT ALISON: It might just be a CodePen thing. I don't know.
JASON LENGSTORF: Oh, interesting. Jacob Bolda, there is a namespace thing so I'm going to do this one and then...ahhah! Okay, so we're closer. We're much closer.
NAT ALISON: Create Element Namespace for everything?
JASON LENGSTORF: Don't be like that!
NAT ALISON: I shouldn't be like that or they shouldn't be like that?
SVG shouldn't be like that. Ahhah! Thank you, Jacob, for the save. We have randomlygenerated art and every time we save, it should replot differently.
NAT ALISON: Uhhuh.
JASON LENGSTORF: Look at it go! Okay. So, this is� I mean, obviously, we're not going to be submitting this for, like, a gallery, but we created actual generative art here, where we're making something on a canvas that didn't exist through code exclusively.
NAT ALISON: And who says we can't submit this to a gallery. You can say this is a piece representing the human condition and the indictment of� an indictment of the blood shed during� I don't know� [Laughter]. I don't want to get too morbid with it. But, yeah. We have circles.
JASON LENGSTORF: The separation we all felt during the pandemic. That is� yes, yes.
NAT ALISON: I don't know. Some of the circles are properly sociallydistanced.
JASON LENGSTORF: These ones were pods. [Laughter].
NAT ALISON: I see.
JASON LENGSTORF: This is supercool because this basically means, like, what we've done here is what I feel like is the, sort of the root of how the rest of this is going to work because now that we've got the ability to create a space and then place things within that space, the rest of it sort of becomes identifying what we want to accomplish it, which is very, very fun. So, let me close this down. What do you think we should do next?
NAT ALISON: So, where I usually play around with it is I see what things can be randomized, in a sense. And, so right now, we're only randomizing the position, but there's so many attributes about the circle we can randomize. We can randomize the radius. It is 5. We can change that. I made a handydandy Rand Range function so maybe we can try setting the radius to something� pick a minimum and maximum radius you would like.
JASON LENGSTORF: Minimum is going to be 3; maximum is going to be 10. And it's already significantly more interesting.
NAT ALISON: Maybe you can change how many circles generate. Instead of fixing it to 20, maybe you want to go from 10 to 100.
JASON LENGSTORF: Okay. So we'll do another one of these, somewhere between 10 and 100...now, on every save, we will get a slightlydifferent setup with a different number� oh, that's so cool.
NAT ALISON: And, another thing we could do is change the color of the circles. And, randomize, make it a rainbow.
JASON LENGSTORF: Oh, yeah, because colors are just numbers.
NAT ALISON: Colors are numbers, man. Everything is numbers. [Laughter].
JASON LENGSTORF: Okay. Then, so we can set up� let's see, we should do this with, what? HSL, maybe?
NAT ALISON: HSL is great.
JASON LENGSTORF: So maybe what we can do is just set the� we'll� will HSL work as a fill on these if I do, like�
NAT ALISON: Fill is just a CSS color property, which accepts RGB, Heck, HSL.
JASON LENGSTORF: We'll set the first one will be a random range between zero and 360, because we get 360 degrees. And then for these, maybe we just go...[Away from mic] make them all that and then I guess we don't really need the� didn't really need that extra fill piece, but we can drop it in anyways. Why not? And then we'll set the fill to be...fill. And then this should give us, like, random colors. I screwed it up. Oh, I'm probably overwriting it.
NAT ALISON: There you go.
JASON LENGSTORF: Yeahhhh! Look at that, y'all! We need brighter colors. We need brighter colors on this stream. That's too bright. How about this? Nice, bright colors, lots of fun and now we want bigger circles because we have...
Oh, this is� this is wonderful. So� and, like, we could, if we wanted to, restrict this to, you know, selecting from a set of colors. Like, if we wanted to do it on a color theme, we could 15 colors that were allowed and generate a math.random to choose one of the� you know, the 15 colors by index. And then we'd be able to grab those out, as well.
So, yeah, oh, man, this is so much fun. All right. What else? What else do you got? Is this considered the Canvas API? No. You could do something similar to this with the Canvas API, but it would not be� like, it would work differently.
NAT ALISON: Uhhuh. It would work differently. It wouldn't be scalable. This is infinitelyscalable right now.
JASON LENGSTORF: That's a good point. We'll go "display block." We'll make it margin...set the width to be [audio cutting out]. Height should be auto and that should keep it square.
NAT ALISON: I'm trying to do...okay. Who cares about semantic HTML, I just wanted to make a joke.
[Laughter]. I don't� J Lengstorf. [Laughter].
JASON LENGSTORF: Yes. [Laughter]. Okay. But I do think� is it randomizing� [Laughter]. Weirder now, because we did the auto?
NAT ALISON: Uhhhh...oh, right. Um...yeah, because we�
JASON LENGSTORF: It should be�
NAT ALISON: We did auto. The width and the height are changed. So, we need to get...I think�
JASON LENGSTORF: Because we can't� yeah, because it's an SVG.
NAT ALISON: Hold on. We can go back to, um...
JASON LENGSTORF: Oh, right. Because we fixed that thing. So we can take this, here. What is it XML NS, right?
NAT ALISON: Yeah.
JASON LENGSTORF: And then we'll take this piece, here, and then we can take that out and this out. And...this out.
NAT ALISON: And undo setting the attribute.
JASON LENGSTORF: Yes. Okay.
NAT ALISON: Ohhhhh, wait. We're setting the attributes by width and height instead of...
JASON LENGSTORF: I have a theory. I'm going to see how correct this is.
NAT ALISON: Oohhhh.
JASON LENGSTORF: Nooooo! So, maybe what we can do is maybe hardcode these because�
NAT ALISON: Yeah. Let's not bother. We're going to keep the view box the same.
JASON LENGSTORF: Yeah. We'll keep the view box the same and that way, it should scale with us. Yes, there we go. What just changed here, for anyone who's never seen this before, is we just set the coordinates for how big the SVG is instead of hardcoding the width and height so everything within it is plotted on a scale of 0 to 400, both left to right and top to bottom. And the width, it'll scale now. So everything here is consistent of 0 do 400, regardless of the actual width and height of the SVG which is very, very useful and one of the reasons why SVG is so cool and powerful.
NAT ALISON: I just messed it up. I tried to be fancy and get the view box attribute. There we go.
JASON LENGSTORF: There we go! Nice. I love it. [Laughter]. And now, it's bulletproof. [Laughter]. So, no matter how we switch that up, it'll continue to work and...look at that! That's supercool! Okay. Now we have adaptive, responsive generative art.
NAT ALISON: Uhhuh.
JASON LENGSTORF: Yes! Is everybody else feeling like a genius right now? Because I'm feeling like a genius right now.
[Laughter]. Can I print this out and put it on my fridge? Yes, you absolutely can. Nice. Yes. I'm having fun. Okay. This is great. [Laughter]. So, now we have...you know, we can continue to mess around with this. Let's say we want a minimum number here� we'll say 50, because they're dippin' dots. Where do you start to see� when you are building out something like this, what are numbers are you start to get into the danger zone of crashing the browser?
NAT ALISON: Crashing the browsers? Browsers are pretty good nowadays. I found projects with 2,000SVG elements. Once you get to that point, you have to, like, do tricks. You have to be like, maybe I'll have to, like, put some of these in the CSS instead of� instead of attributes or maybe I need to be really careful about how I handle opacities and stuff. SVG's pretty powerful nowadays. If you use a framework like React or Vue, there are ways to help you make it more efficient.
If it gets too much, Canvas can handle a lot more.
JASON LENGSTORF: So we're probably safe with a few hundred, probably don't want to get into a few thousand. Let's throw in 500 and see...and now that there's so many, we'll make them smaller. Yeah. This is soup� just with these little tweaks, you get something that feels very different, right. And I think that is such a fun way to approach this stuff. And so, from here, we could theoretically, um, we could do something like circles sometimes and then maybe we throw something else in every once in a while.
NAT ALISON: Uhhhhm.
JASON LENGSTORF: Um, let's see. What should we throw in? Is there a good way to check� like, what's a good way to grab a small number of� I guess we could just check if it's� what's the percentage sign is a� if we could check modulo17, something that's not going to have a ton of matches and then change them to squares or something like that.
NAT ALISON: Yeah. We could do that. I noticed that our shirt says square bois, round bois, curly bois and pointy bois. Maybe your squares could have that.
JASON LENGSTORF: Yes, let's absolutely do that. To do that, is there a text element in SVG?
NAT ALISON: Yes, there is a text element in SVG. Did you want squares or do you want brackets?
JASON LENGSTORF: Let's do brackets.
NAT ALISON: Everyone's done circles. But brackets, that's new territory. That's high art right there. [Laughter].
JASON LENGSTORF: And that is what I live for. So I'm just going to put all of the different bracket types into...into a thing. And then we'll just randomlyselect them, right? If I can type? Please let me type...please� oh, my god. This is going to take so long. And we can do these... oh, my goodness. Nobody look at me. I got to ortholinear keyboard and I'm still a little bit shaky on some of these options. We need, what, parenthesis and then we'll done?
So, now we've got all the different options. We got curly bois and curly bois and round bois. We can start throwing these on our canvas here. So, to do that, we need a text� right. So I'm just going to comment this out for now. And, we need text and that'll be document.� I'm just going to copypaste this piece. Text. And then, we need...a lot of this is going to be sort of similar, but not exactly the same. So, we need the text dot� is it going to be x and y for this?
NAT ALISON: Yes, it's going to be x and y.
JASON LENGSTORF: Okay. So, take this one and set this to height. Okay. And then, the� is it� is it an attribute for the text or is it, like, the inner text?
NAT ALISON: Uhhhh...it is the inner text, so�.text.
JASON LENGSTORF: We're going to take bracket options and a math.round times math.random... oh, no. We need to do not math.round, but a math.floor and bracket options length and that gives us one of...our different bracket options. And then we need to actually append this...does it need color? Does it need a fill?
NAT ALISON: Um, let's see, it needs a fill.
JASON LENGSTORF: Okay. So let's just take this fill�
NAT ALISON: I think that should be fine.
JASON LENGSTORF: And text.
NAT ALISON: So let's see where the text is going wrong. Fill� does it need a font, I wonder?
JASON LENGSTORF: Um, it's also not� I think I'm wrong on what the� inner text is not doing anything, so there's probably something for how you do that in SVG.
NAT ALISON: Uh, is it� okay, so you did Create Element NS.
JASON LENGSTORF: It's rendering the text, but there's not a� there's no, like, text inside of it. So, if I come in here and I can actually just, like, probably manually edit one of these... let's edit as HTML and then we'll throw in one of these and then�
NAT ALISON: It's�.node.text.context or� or is it Node�
JASON LENGSTORF: Content or text?
NAT ALISON: Context.
JASON LENGSTORF: There we go! This is a little more chaotic than I want it to be. I would like to play with the fonts on this. So, let's make it� you said that there's a font property?
NAT ALISON: Um, let me check...
JASON LENGSTORF: I don't know that we need that one to be random. So, here, we can� text...that works. And then, we can do a text stroke of, like, 2pick solid. Oh, I forget what the� do you remember� off the top of your head� what the stroke for a text element is?
NAT ALISON: I think it's Paint Order Stroke is just what I found from Googling. So, you want a stroke outside of the text?
JASON LENGSTORF: That was the plan, yeah. And then do, like, a� stroke color?
NAT ALISON: Yeah, I think it needs to be a property.
JASON LENGSTORF: It needs to be set in here?
NAT ALISON: Yes, as an attribute.
JASON LENGSTORF: Okay�
NAT ALISON: Goes behind the text. And then, you can specify the stroke of the text. Stroke�
JASON LENGSTORF: Stroke.
NAT ALISON: There we go! Oh, that's so good!
JASON LENGSTORF: So that� that works. And then, let's make this even a little bit more chaotic and let's play with the rotation a little bit. [Laughter]. So, we can kind of have�
NAT ALISON: That is exactly what I was thinking of. [Laughter].
JASON LENGSTORF: So, to do that, I need, like, a transform or is there a rotation property?
NAT ALISON: Transform.
JASON LENGSTORF: That'll turn it sideways, if it's working...
NAT ALISON: It's going to be the style, not an attribute.
JASON LENGSTORF: Oh! Oh, oh, oh [audio cutting out] okay. Is it just a straightup, like a string?
NAT ALISON: Um...set style program [Away from mic]. �.style� no, wait...yeah, it's�.style, dot the property and it's "rotate," not "rotation." Does that work?
JASON LENGSTORF: Oh, oh. Why did that die?
NAT ALISON: I think it rotated everything from, like, the baseline.
JASON LENGSTORF: Ooohhh. Weird, yeah. Because, look, it's over here now.
NAT ALISON: I don't know�
JASON LENGSTORF: That's not the right thing.
NAT ALISON: Just try doing transform then.
JASON LENGSTORF: Text style transform and we'll say, rotate 80�.
NAT ALISON: No, same thing.
JASON LENGSTORF: Same thing. Why don't you�
NAT ALISON: So I think you need to set the [Away from mic].
JASON LENGSTORF: If I set the transform order in the center, it won't do that? Hey! There we go! That keeps the CSS from rebelling, by setting the transform point to the center of the text. I think it must have been up here. All right. So, then, we can swap this out to be random. So, now we'll set this to be a random range between, probably, like...like, 15 and 15, maybe?
NAT ALISON: Uhhh.
JASON LENGSTORF: That way, it'll kind of wiggle a little bit. Yeah, we've got some confetti. And then we want to set the size. Because these ones, you can't set the radius so we need to jiggle the size. And to do that...is that just, like, font size?
NAT ALISON: I think so.
JASON LENGSTORF: Okay. So we'll do a random range of, um...let's say 18 to 30.
NAT ALISON: Is that� is there a difference? I can barely see. I guess there's a little bit of difference.
JASON LENGSTORF: Yeah, let's make it more extreme and see if it's actually working...yes, okay. Actually, I kind of like it with that more extreme difference anyways. [Laughter]. This is chaos and I love it.
NAT ALISON: I want this on a shirt. [Laughter].
JASON LENGSTORF: I mean, this is legitimately, I would have a lot of fun putting this on, like, a poster or something.
NAT ALISON: Uhhuh.
JASON LENGSTORF: I guess that's the whole point, right. You're making something you want to see and if you make something you like well enough, you can move it somewhere else, put it out into the world.
Let's make this one a nice color that can sit in the back and probably make it� saturation can be pretty low. Lightness should be pretty high. And...
NAT ALISON: Ooohhh.
JASON LENGSTORF: Look at it go!
NAT ALISON: So nice. So pleasant to look at.
JASON LENGSTORF: This is really fun. Try just rotate as an attribute...so, yeah, I do think that now that we've� now that we've set this, I think it'll work. We just need to do this...yeah. So, now that we've set the transform origin, so that was the� that was the trick, not necessarily using the rotate.
Man, this is� this is fun! All right. So, we got about 30 minutes left, if we want to try anything else in here.
NAT ALISON: One thing we could do is make it reproducible from just the content. So, like, not having it so that you have to refresh every time. So, we can, like, is share the CodePen to people and regenerate it every time.
JASON LENGSTORF: And give the seed and it becomes deterministic?
NAT ALISON: Or have a button to rerun the algorithm.
JASON LENGSTORF: Oh, yeah, I gotcha. Let's do that.
NAT ALISON: I think the CodePen is not loading on my end.
JASON LENGSTORF: Let me save and now� [Laughter]. I didn't realize� [Laughter].
NAT ALISON: What happened?
JASON LENGSTORF: I just realized that you updated all of the descriptions.
Okay. Um, so to do that, we would want a� like, a button, right. And in our button...we would have...a regenerate... have a button and we can give this the most basic of styles. A display� no, we won't even do that. We'll do, um� I'm going to put it inside of a paragraph so that we don't have to figure out how to center it. And that might be good enough for now, actually, we won't fall down the CSS rabbit hole.
We have a button.
NAT ALISON: We have a button. I think we can just wrap it into a function and call that function from the button. So, wrap all generative text in a function.
JASON LENGSTORF: Okay. We can take all of this part...and, we'll move it inside here. Okay. And then, we'll start with a call to generate art TM. And that gives us our first call and then we'll do a document.queryselector. Grab the button. And then we'll do "add event listener." Click. And, we can run "generate art TM." And, because I think this is a good habit to get into, it'll� doing it that way will pass in the event to generate art and, like, it won't matter in this function but it's a bad habit because sometimes it does matter and it will trip you up in and ways so doing a little closure here, instead.
NAT ALISON: It started generating. [Laughter].
JASON LENGSTORF: Oh!
[Laughter]. Okay. So, that's going to end up causing some issues. So, we need to clear this thing.
NAT ALISON: Yeah. Clear all the children.
JASON LENGSTORF: To clear children, we need to� do we SVG set inner HTML as nothing? Can I just clear it like that? Will that work? Nope. Um, okay. So, to delete all of these...do I have to, like, loop through and delete all of these children? Inner HTML is all capitalized.
NAT ALISON: I'm just wondering if it's going to break.
JASON LENGSTORF: Yes!
NAT ALISON: Does it work?
JASON LENGSTORF: It does work. I'm really glad that worked because I did not want to have to write a loop. [Laughter]. So...now, we have...generative art and we can click the heck out of this and come up with new patterns to our heart's content.
NAT ALISON: Another aspect of generative art that would be fun to touch into is adding parameters. So, not just being able to make a random thing [audio cutting out] what is being generated. So, this can be everything from, like, defining the color scale to adjusting the ratios of the square bois and the round bois and all the different kinds of bois.
JASON LENGSTORF: Okay. So, maybe what we can do is, let's make this into a form, because we'll just be able to use inform data API here to grab all this. And what we can do is set up a label and we can say� let's go with some easy stuff, probably. We can do, like, a range. Right. Like�
NAT ALISON: Yeah.
JASON LENGSTORF: Like, number of bois. [Laughter]. And then we can do an input put range and set a min and we'll default it to our current values of 100 and max of 100. And the name will be...boi count?
NAT ALISON: That is a very good name for it. [Laughter].
JASON LENGSTORF: Um...oh, but that doesn't actually do what I want because the range isn't what I'm after. I'm looking for an actual min/max. So we need, like, a number.
NAT ALISON: Yeah, but it's also� it's also okay to not specify a range and just have the number of bois be determined by, um, just the value on the slider. So�
JASON LENGSTORF: Oh, like, let it be fixed.
NAT ALISON: Yeah. And then you can regenerate every time you change the number, and the slider, as well.
JASON LENGSTORF: Oh. Okay. I was going to let them click the "regenerate "button but you are saying to listen for changes?
NAT ALISON: Yeah.
JASON LENGSTORF: Let's do that. Let's grab an ID so we can do that. And then in here, we'll set up a listener and that'll be� let's say� date on change, the event and then we can say...the new value is going to be...the event.target.value should be what we're after, I think. And then, um...we would call "regenerate." We have to figure out what the field to update is.
NAT ALISON: You can just add a parameter to, um, to generate art for the number of bois. The boi count. And generate with that boi count.
JASON LENGSTORF: So, we'll default to, let's say, 200. And then, we'll...delete that bit. And, we're going to use "boi count," instead. 200. And that means I should probably set this to 200 by default.
NAT ALISON: Uhhuh.
JASON LENGSTORF: Okay. And then, we can� the new value will be "generate art with the new value." And then we can do a document.queryselector and we'll grab...boi count.
[Laughter]. Listener. Just change and we can update on change. Okay. So, this should remain� oooooh, boy!
NAT ALISON: Oh, no.
JASON LENGSTORF: What did I do? What is happening? It was� did you see that kind of work, and then not?
NAT ALISON: Uhhhh, yeah.
JASON LENGSTORF: So� what is that?
NAT ALISON: Just bricked.
JASON LENGSTORF: So, you should be...did I use a circle count anywhere else? No. Is it just you that causes this problem?
NAT ALISON: Seems to be working for me.
JASON LENGSTORF: Okay. I'm going to save. I'm going to hardrefresh...click the button...what on earth is happening? Ooh! I know why. It is because now that form submits, because I made it a form!
[Laughter]. Oohhhh. Silly. Silly. Silly. Okay. Better now. All right. That's fine. That's fine. That's just me not being good at code and we've come to learn that here, at Learn With Jason. Look at it go! Look at it go! Hahahaha! Dammit, that's fun. That's great. What we're getting here, we could get more clever where we could do something to the effect of, let's say...here, we have the ID, right. And so we could get the, like, value to change is going to be, um� we'll say "event.target.id." And then what we could do here is we could actually send in, like, value to change...and the new value. And, up here, we would update this to be...the boi count...so, we'd get� we'd have to� let's see, would that work? That should still work, I think.
And...why it's got to be like this? So, then, if we update this, it still works. But we could set another one for, let's say, the� uhhhhhm, font size� well, let's see. What would we do? Let's do...
NAT ALISON: Oh, rotation. Upgrade rotation degree.
JASON LENGSTORF: Okay. Yeah.
NAT ALISON: You could have the things be slightly bendy or go every which way, based on what you want.
JASON LENGSTORF: Rotation variants. We'll go with variants and that way, we can do plus or minus, you know, up to 90� or something. And we'll say, a minimum of zero. So, no rotation and a maximum of 180. We'll set the value to 15 and we'll call it "rotation." Okay. And then we're going to add one of these, down in here...I'm going to have to do a default object, I think. And, like, extend it because I think this is going to break. Um...so, then...we're going to use� whoops� the rotation variants here and here.
So, if I...take this one...we'll do rotation very� whoops, whoops, whoops. Rotation variants. Then, theoretically, if I flip this upside down...it's going to break and it broke because that means we're missing...I think, the number of bois. Yeah, so I think we need to change this one, down here, to be� how about this, we will take this piece out and we'll set this to "values." Then we'd be "structure." Now, if one isn't set, it'll fall back for us and we don't have to figure out how to do all the rest of that. So, let's� don't you lie to me, that works. Oh, no, it won't, because these need to be equals. Now it works. You going to� you going to work? Crap, what have I done? Okay. We reload...cannot read properties of undefined. Reading boi count. Maybe this needs to default to an empty object. Yeah, there we go. Okay. So, now...let's see...lots and lots...let them flip around...rotation variants...rotation variants...why isn't that working?
NAT ALISON: Oh.
JASON LENGSTORF: Oh, there we go. There we go.
NAT ALISON: Nice.
JASON LENGSTORF: And so now we have�
NAT ALISON: Extremelyrotated bois.
JASON LENGSTORF: Oh, you have to unfocus to get that� so, the change doesn't trigger if you just edit. You have to defocus. Okay. So that's a problem that we could solve, but probably won't.
NAT ALISON: Yeah, that's form stuff and not cool, generative stuff. That's boilerplate. Okay. So we got� we got rotatey bois. We have number of bois. Is there anything else you want to add? We have about 15 minutes left.
JASON LENGSTORF: We do, indeed, have 15 minutes left. If we don't have anything� people were in the chat, like, hey, you're formsubmitting. I have this very helpful chat and I don't read it.
Oh, here's a question. We're getting asked if we can rightclick and save the downloaded� the generated SVG? I think the answer right now is, no. So there would be a way to do that, we probably don't have time to do it right now. And to do that, you would need to, like, grab� grab the SVG content and then set it to� there's a� you can send the contents as a� like, a hinted download and then your browser would download as an SVG. So, it is possible. If you want to do that and submit it as� like, an exercise for the reader... that would be super, super fun.
Okay. Chat, you got anymore ideas or should we just call this a resounding success and give ourselves 15 minutes back?
Nat, while the chat is thinking, do you have a place where we can look at some of your other art? Because I just realized, we didn't show any of when we first got on the stream?
NAT ALISON: Most of the generative art I did was when I was working with Components.ai. If you go to components.ai/svggrid.
JASON LENGSTORF: This is what a finished version of what we started working on would be.
NAT ALISON: You can adjust the width, height. If you get rid of a lot of those symbols, so, there's a bunch of symbols. The founder of component.ai did that. You can also adjust the color palette. If you do "add palette" on one of the shapes. If you switch from shallow to scale...and then try and randomize it a couple of times, using the "refresh" button.
JASON LENGSTORF: This stuff is so cool. And like, each of these is...I love it.
NAT ALISON: Uhhuh.
JASON LENGSTORF: It's very cool and we're increasing the odds of how likely that this shows up in that section and if I'm� if I'm attempting to reverseengineer this, what I think is happening is you're kind of scanning across the SVG and then deciding if each session should have� like, what shape should it choose and grabs from these settings here to pick something from the parameters. Is that the gist, at least?
NAT ALISON: Yeah. And the cool thing about generative stuff is they can build on top of each other. A lot of the random functions can be used. This component was another component I did for them. You can enhance the capabilities of this thing. There's another aspect, if you click on "scale" on the checkbox, it will scale it. And, this isn't completely random, it's made using Simplex Noise, which is a thing� a Gaussian Blur. The scale is smaller in some sections and larger in other sections.
JASON LENGSTORF: It gives, like, a real pattern.
NAT ALISON: Yeah. Yeah. And I think you can�
JASON LENGSTORF: Wow, that's dope!
NAT ALISON: You have the ability to adjust the scale, you can have a granular or very large pattern with it. You can use� you don't have to just do a linear random distribution, you can do normal distributions. And...yeah. So, this is another thing that I did...recently, which isn't quite, like, generative art, but uses, like, a lot of the same� a lot of the same...let me send the link to you.
JASON LENGSTORF: Okay.
NAT ALISON: Ummmmm...so, this is a project I did. The idea was to make a game based on the� oh, hoping it works. You should turn the music on. It's just the music� click the "music" button.
This is a simulator. [Laughter]. So, if you click�
JASON LENGSTORF: What is sloop?
NAT ALISON: It's sloop. If you click inside of it, you can place food. It's not very good at finding the food, so you have to place it on top of it, basically. If you click on it a bunch of times, it'll grow faster in that direction. Yeah, see?
JASON LENGSTORF: Oh, neat!
NAT ALISON: So�
JASON LENGSTORF: It's sinking. This is� the schloop is also, like, hilarious. Wow, this is so cool. And so, we have one request from the chat, which is to� where is it? Here. Which is to put some emojis in this. So, let's� because we're using text, that's actually going to be really simple and I'm very happy about that. So, we can� which ones are we doing? I'm adding pizza. What else? Everybody, name your favorite emoji and I swear to god, if you do anything gross, you're banned.
I can't do any Twitch emoji, it has to be a standard emoji. Let's see, I'm going to add� let's add a spicy pepper...
NAT ALISON: Because we're going for a food theme. Can we do Ramen?
JASON LENGSTORF: Yes, absolutely.
And so now, we should start seeing these immediately showing up. We've got food and code all mixed in together. And, like, I think this is� this is so cool, how fast you can put together ideas like this. And how quickly [audio cutting out] this, you know. If you wanted to build� you know, an allover print or something for a Tshirt and you had a series of images that were brand images, you can just throw them in here and put them on the screen and regenerate until you find one you like. Let's bump in the rotation a little bit. Let's increase the number, that's too many. Let's decrease the number. You start to find things that look the way you want and you can drop things in and out until you get something you're happy with.
I think this is so much fun, food and bois. [Laughter]. But, yeah, this is� I mean, this is just wonderful. So...Bubble tea, you're right.
NAT ALISON: Is that a good idea? This is all savor foods. Maybe you can pick your palette? This is homework. We can share the CodePen and be like, pick a palette and pick food that fits the palette.
JASON LENGSTORF: You could even set this as different types, so you could do code theme, savory theme, sweet theme and have a theme switcher here and you'd be able to change that down here...where we're grabbing our pieces. You'd be able to switch this up to a little function that would look for which theme you're using and grab from the subset, right. Lots and lots of remixing it. Chat, I hope you have a lot of fun playing with this and remixing it yourself. The possibilities here are endless. I think another thing that would be a fun exercise for someone to do on their own time would be to change this from being completely random with math.random, to make using a random number generator so if you put the same seed in, you would always get the same output, which would make it shareable. If you get one you really like, you could get a link that� I don't know, here's the art with a query parameter of seed 1234 and everyone who looks at that link will see the same generative art, which is a great way to make this generative and also shareable, which I think is really, really fun.
Okay. So, with that, I don't think we've got time to add anything else. Chat, thank you for all the ideas today. And Nat, thank you so much for taking time out of your day today to teach us.
NAT ALISON: It was a blast.
JASON LENGSTORF: For anybody who wants to do more with this, do you have any more resources, any inspiration?
NAT ALISON: You can check out my website, tesseralis.site. It is� I just revamped it. It is what I call Math Professor Core. It's a link to all the stuff I've done. Yeah. Do you want to show people my Polyhedra Reviewer?
JASON LENGSTORF: Yes. It's so good. So, this� what do you think is the best thing to demo here?
NAT ALISON: Just pick any of them. They're all great.
JASON LENGSTORF: I'm jumping in. So, this is like, rotated 3D Polyhedra and then you can start doing wild stuff. Oh, I love this so much. Look at it, y'all. Look at freakin' cool this is. I just� and all of this is done� actually, how did you build this one?
NAT ALISON: How did I build it? This is React and I was using this thing called X3DOM. 3D SVG, but it's also, like, very weird and, like, very, like, outdated and restrictive so I actually have a new version of this, that's built using 3JS.
JASON LENGSTORF: Oh, cool. Very cool. We've done a little bit with 3JS on the show. For more on this, here's the episode we did if you want to see how to do this with a shader. 3JS, we have an intro with Sarah Drasner if you want to start playing with more powerful stuff, like building something like this. And that, I think, is all the time we have.
Nat, thank you so much, again, for hanging out with us. Any final words for the chat before I wrap us up?
NAT ALISON: Thank you so much. It's been a blast. You can find me on the website, but also on my Twitter, which I usually just post random thoughts and complain about the modern frontend web development stack. [Laughter].
JASON LENGSTORF: Let me throw a link into there. All right, chat, we are going to go find somebody to raid. Thank you, all, again, for hanging out� I just screwed up that link. That's the right one. We will see you all next time.
NAT ALISON: Did you share the� did you share the link yet so people can remix it?
JASON LENGSTORF: Oh, oh, no, I didn't. That's a good call. Let me do that right now. Um, so now people can get in and remix that and I need to find somebody to raid because nobody is live right now.
Closed captioning and more are made possible by our sponsors: