Functional JavaScript First Steps, v2

Recursion Art Exercise

Anjana Vakil
Software Engineer & Educator
Functional JavaScript First Steps, v2

Lesson Description

The "Recursion Art Exercise" Lesson is part of the full, Functional JavaScript First Steps, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Students are instructed to create an SVG design by recursively drawing a square with alternating colors and rotation. The SVG group element can be used to nest the recursive calls and apply the rotation using CSS transforms.

Preview
Close

Transcript from the "Recursion Art Exercise" Lesson

[00:00:00]
>> Anjana Vakil: Okay, now we're gonna get a little more fun with our recursion. So you're gonna see this little Functional Art Studio, and you have a blank canvas. And your mission is to implement some functions up here, which under the hood this little project is passing those to that impure render SVG and the pure get SVG art that we wrote before, and it's rendering them into the page.

[00:00:26]
So, as you update this function here in patterns.js, I'm gonna call it the diamondPattern, whatever you put here is going to get called in art.js. And in a non-function functional way is gonna get exported as a global there, but that is going to then be rendered on this little mini app here, which is just running in a little vite app.

[00:00:50]
Anyway, you can look at the source code later if you're so inclined, but it's basically exactly what we saw before. We're getting some data about an SVG and we're attaching that data to the DOM to visualize it. Anyway, your task, should you choose to accept it, is to draw something like this.

[00:01:13]
So this is a pattern that involves recursion. And I called it a diamondPattern, even though I guess it's squares and diamonds, whatever. But the idea is that we want to compute a string representing the inner contents of an SVG that will get rendered to the page. So for example, if I do return <rect, x is 0, and y is 0, and width is 50, and height is 50, and the fill is rebeccapurple.

[00:02:00]
>> Anjana Vakil: Then we get a purple rectangle. So this isn't a class about SVG art, although that is a super fascinating topic that there are some good courses on frontend masters about. I believe Shirley Wu has a course about data visualization with SVGs. Anyway, but you can, of course, use our good friend MDN to look up the SVG reference.

[00:02:21]
If you're not used to working with svg elements, just using this because instead of canvas or something, because svg is a declarative way of describing the pixels you wanna see on the screen. Not the pixels, but the elements you want to see on the screen, whereas, let's say, using the Canvas API, very imperative.

[00:02:38]
Anyway, svgs are great, I'm a fan, what have you. So you can check out MDN if you need any help with actually what do we do here? But spoiler alert, you're basically just gonna need [LAUGH] rect and maybe something else is going on here. I don't know. So this is a challenge.

[00:02:58]
Can we write a recursive function that takes in two colors and a given width and returns the string representing the pattern that I wanna see, which is these nested diamonds.
>> Anjana Vakil: Instead of hard coding a rect like this with a fixed width and a fixed height and a fixed fill, we're gonna start computing that on the fly.

[00:03:31]
This is how we would define a rectangle in CSS, in SVG, sorry. Why don't we start out with our base case where,
>> Anjana Vakil: Essentially,
>> Anjana Vakil: The width, we don't want it to go any smaller than 20, cuz that's just gonna look visually cluttered and we can't have it.

[00:03:57]
So I've just arbitrarily set this as the stopping point of our recursive patterning. So in the case where width this less than 20, let's just return one rectangle. But let's make sure we return it with the correct width and the correct color. And I'm just gonna say we're gonna with color1.

[00:04:22]
It can only be one color. We're gonna give it color1. So there are a few different ways that we could compute this string, but my favorite and the most declarative way to fill in a string with a bunch of other values that you don't know in advance is a template literal in JavaScript.

[00:04:46]
Have folks worked with this where instead of these regular little single quotes, we're gonna add backticks around this string, and then inside of the string, we can use the dollar sign and curly braces to inject a value. So in here, instead of hard coding the width as 50, I'm gonna pass in?

[00:05:11]
>> Speaker 2: Width.
>> Anjana Vakil: Width, thank you, [LAUGH]. And the thing is, it's a rectangle as far as SVG is concerned, but it's a square as far as what we are concerned. So we're also gonna do the same for the height, yeah. And then even though rebeccapurple is our new favorite CSS color, we are going to let the user decide what color they want to be, cuz they might not appreciate such aggressive color schemes as I do.

[00:05:42]
We only have one rectangle to draw, sorry, you don't get alternating colors, it's just gonna be one, and it's gonna be color1.
>> Speaker 3: Quotes?
>> Anjana Vakil: And quotes around that is a great idea. Okay, so if folks haven't worked with this dollar sign curly braces thing, I don't know what?

[00:06:04]
Because I'm calling it not width 20. Let's change that.
>> Anjana Vakil: Okay, so if I call it width 20, I get a little tiny green square, cool, face case. Now, all we need to do is the rest of the haul. Okay, so I'm going to return not only the color1 with square, but the rest of the stuff.

[00:06:33]
So that means, to start out, it maybe looks very similar to what we did before, okay? This is gonna be the first part of our SVG, it's always gonna be this main big square. Now I'm gonna move this back to here. Okay, so,
>> Anjana Vakil: First we need to draw this layer of the pattern, if you will.

[00:07:02]
And then we need to draw the next smaller layer of the pattern, and the next smaller layer is gonna be a smaller width. That's just basically the hypotenuse of the half of the two, anyway, [LAUGH] so it fits perfectly in the square. I've already done that for you.

[00:07:20]
Thank you, built-in Math.SQRT2. And we're going to compute a new rectangle of the smaller width, but we want it to be a different color, and we want it to be diagonal. So here I'm going to continue using my declarative string template here, and I'm just going to add some space so we can do some other things.

[00:07:51]
Now here, if I wanted another rectangle that is,
>> Anjana Vakil: A very similar pattern to the one that I'm currently making, just with some different values, I'm gonna want to, and spoiler alert, we know this is the recursive case. I'm gonna want to call a function that's great at producing patterns like this, which is?

[00:08:22]
>> Speaker 3: DiamondPattern.
>> Speaker 4: DiamondPattern.
>> Anjana Vakil: Myself, diamondPattern, exactly. Okay, and now the values that I pass in are gonna be a little different. So can anybody help me guild this? At each layer if were thinking about them as layers of the pattern, we're gonna flip the colors. So instead of passing in color1, color2?

[00:08:39]
>> Speaker 3: Color2, color1.
>> Anjana Vakil: Color2, color1 [LAUGH] swapsies, and then instead of passing in width?
>> Speaker 5: Smaller widths.
>> Anjana Vakil: Smaller width. Bingo, okay, well, now something's happening, we've got recursion, we can see it. They keep getting smaller and smaller and they keep switching colors, so that feels good.
>> Speaker 6: Looks like infinite hall way.

[00:09:03]
>> Anjana Vakil: It is sort of giving us three dimensional vibes. So what we need to start doing now is rotating them. And in order to do that, we can wrap this rect that's gonna come back from diamondPattern. So what we'll do is we'll just go to the element reference, and you're just gonna have to trust me that there is this g element that's kind of the div that we want from our HTML.

[00:09:35]
Security net, I don't know, from how we're used to thinking about transforming elements on the page, by, let's say, having a div wrapper that then is transformed. We'll do the same with g in here. So whatever, if we wrap some elements, some SVG content, in a g, then whatever attributes we set on the g are gonna apply to the group.

[00:10:00]
So we can for example, set a bunch of properties for multiple things. Okay, so let's wrap this in a g, which, by itself, just like a div, doesn't do anything. In order to manipulate this g, we can pass a value to the transform attribute that uses some of these built-in transform functions similar to CSS.

[00:10:23]
So for example, I can rotate it 45 degrees and now, I mean, it doesn't look right, but at least we've got one little pointy thing that looks sort of similar, so that's cool. So what I'll also need to do is keep making sure that everything is centered essentially.

[00:10:44]
And because all these SVGs are gonna start at 0, 0, we're gonna kind of translate this whole system. It's gonna get rotated, but then we also wanna change the point of 0,0 and where it starts. So right now we translated it, sorry, we rotated it, but 0, 0 is still in the top left corner, same as it was before.

[00:11:14]
So instead what I wanna do is take this point, this top of the diamond thing, that's a little hard to see cuz it's on top of the other diamond, and we wanna move it here to the middle of the square. And so I can use a translate for that.

[00:11:33]
Can anybody help me fill in my translate operation here?
>> Anjana Vakil: And this is where I'm gonna need to maybe do a little math. So I'm gonna add a dollar curlies. And let's say, for example, if I translate it to the width, it pops all the way over to the other side.

[00:11:52]
That's also not what I want. You're halfway there? Halfway there, so if I divide the width by 2, now we're cooking with gas or pure functions. So what we've got is a purely recursive real-world object. Pixels on the page count as a real-world object in this sense, because remember, before we wrote that impure render SVG, we wrapped all of that impurity of actually taking this string that we're computing here and putting it into the page and making it pixels.

[00:12:32]
So what we're doing here is we're just computing that string, and we're doing it in a totally declarative way. We're saying I wanna a string that looks like this, and these are the values I wanna inject into it. And in order to get our repetition here, sure, I could have asked you to do this with a for loop, but where would be the fun in that?

[00:12:54]
So in order to do that repetition of keep going, keep going, keep going, keep going, we use recursion. So this is a simple and yet, I hope illustrative, example, [LAUGH], of kind of how we could use recursion to make recursive things work in a declarative way without having to write a for loop and keep going through each of the smaller squares.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Start a 7-Day Free Trial