So now let's go ahead and actually enable the resizing functionality. So this is how we are going to do that. First things first, we are going to leave the On pointer down to be empty for now. So we are not going to immediately add this. Instead, let's just create this OnResizeHandlePointerDown in the canvas component.
So inside of canvas.csx right here, I'm going to go above this all pointer stuff. So let's see, we can do it here where we have insert layer so above on wheel let's write const on resize handle pointer down so when the user clicks on one of these little boxes here, it doesn't start to drag yet, just clicks on this, that's when this function is going to be fired. So that is going to be a callback function, so use callback like this. And in here, we're gonna go ahead and have the following props. So we're going to have corner, which is a type of side from our canvas types.
So make sure you import this from types canvas besides corner it's also gonna have the initial bounds which are gonna be our X, Y, width and height from types canvas as well so make sure you have side and this from canvas And now let's pause history and then let's do set canvas state and let's change the mode to be canvas mode dot resizing. And if we pass resizing we also need to pass the initial bounds and we also need to pass the initial bounds and we also need to pass the corner that is being resized. And now we can pass the history in the dependency array here. Now let's use this onResizeHandlePointerDown and let's actually pass it to our selection box here. So onResizeHandlePointerDown, we'll be calling the onResizeHandlePointerDown function right here.
And now let's go inside of the selection box and let's actually use that function now. So inside of the on pointer down here in the first handle, let me just find it. We have a to do add resize handler. Let's go ahead and write on resize handler pointer down. We're gonna call side.top plus side.left and bounds in the second argument like that.
So let's just see where we have the side from. We have the side from types canvas. So basically this is a corner bound, right? So you can see that when we resize we are resizing to the top and to the left, right? And we also pass in the bounds as the second argument.
So now we're going to copy this, go to the other handler right here. The other handler is simply going to be side top. Like that. So that's this one. It just goes to the top.
And then we go to the third one. This is again a corner one. So that one is going to be side top plus side dot right. Right? Because it's a this corner right here.
So now let's go ahead and go to the right one. Right here. So this one is very simply gonna go to side right. Like this. That's this one.
And then again we have a bottom corner here. So we're gonna use two of those. Let's go ahead and let's combine the side bottom and side Right. And passing the bounce as usual. And now let's go ahead to the lower one.
And this one is just side bottom, right? It's this one right here. So we don't have to pass in side right. Like that. Great.
And let's go ahead and do the next one which is this corner which is bottom and left. So lower one. This is gonna be side bottom plus side dot left like that and now let's go ahead and do the left one oh is this the last one? Oh yes, because yes, yes, yes, correct, correct. And this will just be side.left because all it does is goes inside of the left.
So let's go from bottom to top to confirm. So this one, the last rect is our side.left so that represents this one. Okay? The one above it is this corner right here which should be bottom and side left. Then the one above that one is simply side bottom because it just goes down right here.
The one above that is bottom and right because it is this corner right here. The one above that one is side right because it very simply just goes to the right so the opposite of our last one which is left. And then above that one we have a corner one so side top plus side right which is this one and then after that one we simply have side top So it simply goes to the top and the first one is simply a side top plus side left which is this right here. Perfect! So now we are ready to go back inside of our canvas.
And right now if you try, still nothing here is happening. But inside of your OnResizeHandlePointerDown you should be getting some console logs here. So let's go ahead and console log the corner and the initial bounds. So we can see this happening right here. So I'm going to go ahead and open my terminal here.
Let me try and selecting this one. If I click here, there we go, corner 9, corner 8, corner 10, corner 2, corner 6, corner 4, corner 5. Like that. So all of them are different, perfect and we also have the initial bounds of their width, height and their coordinates so we can calculate using those. Great.
And now what we have to do is the functionality to actually do something when we drag these items. So the way we are going to do that is by going inside of our... Let's go ahead and find on pointer up or on pointer move. I'm not sure which one would be the correct place to put this. Right, it should be on pointer move.
So let's go inside of on pointer move right here where right now all we do is simply set the presence of the cursor. So now what we're going to do is we're going to check if we have canvas state that mode to be canvas state dot resizing. CanvasState.mode to be canvasState.resizing We have to use a type canvasState My apologies, canvasMode.resizing If that is true, let's just console.log resizing. So now if we are correct, so let's find our onResizeHandle pointer down. What it does, it changes the canvas state to canvas mode resizing and it passes the initial bounds in the corner we are trying to resize.
So then inside of our on pointer move we should have this being logged once we are moving a corner icon. So let's try it out. So now if I go ahead and do this. Right now just by moving my cursor nothing is happening. If I randomly drag the element nothing is happening but if I drag this it should be happening but it seems like nothing is still happening so I think we are missing an additional event handler here.
It might be because I forgot to add a dependency array. Let's see if that is true. It could be. So we need canvas.state instead of the dependency array. Let's see if that will maybe help it.
There we go. So I was missing the dependency array. There we go. You can see how if I hold and drag anywhere, nothing is happening. But if I specifically grab a handle, then we have a bunch of resizing events happening.
So that's exactly what we want. Perfect. So just make sure that inside of your own pointer move you've added an if clause to check if we are in the resizing mode and then we are doing the resizing. Perfect. So what we have to do now is we have to create a method resizeSelectedLayer so that we can actually, well, resize it.
So I want to add this in here where we have our insert layer. So just below that, let's go ahead and let's add the function to resize the layer. So const resizeSelectedLayer is going to be useMutation again and in here let's go ahead and let's extract the storage and self and let me just write this function so we don't have any prop errors here so storage and self and point which is a type of point which we have from types canvas and now in here we're gonna go ahead and check if canvas state.mode is not canvas mode resizing so if we somehow fired this function and we are no longer resizing just break the function. And now what we have to do is we have to create a util to resize the bounds. Let's head inside of our utils file.
Then again you can always visit this in my GitHub. We have the entire utils file here if you don't feel like writing this line by line with me. If you do, then let's go and write expert function resize bounds, which is going to accept bounds as the first argument, which is a type of x, y, width and height, corner, which is a type of side, point, which is a type of point. And let me just collapse all of my props here. And it looks like I didn't import side from types canvas and point from types canvas.
So make sure you have the camera, the color, the point, side and XY width and height from types canvas. And it's going to return x, y, width, and height. So let's prepare the result to be x bounds.x, y bounds.y, width bounds.width, height bounds.height, and let me just fix my typos here so I don't break the entire app. All right, and what we're going to do is return that result. So this will resolve this type script error.
And in between returning the result and the initial result, we have to do some calculations to change the actual output, which is going to happen depending on what the user is dragging, how long they are dragging and what direction they are dragging it in. So if, let's open double parenthesis, if we have a corner and Psi.left is equal to Psi.left, in that case result.x is going to be math.min so the smaller value of this point.x or bounds.x plus bounds.width and result.width is going to be Math.absolute bounds.x plus bounds.width minus point.x Now let's go ahead and check if corner and side right is equal to side right. In that case, result.x is going to be math.min between point x and bounds.x and result.width is going to be math.absolute point x minus bounds.x. Now let's go ahead and write if corner and side top is equal to side top. In that case, result.y is going to be math min between point y, bounds.y plus bounds.height.
Between point y bounds dot y plus bounds dot height and result dot height is going to be math absolute bounds dot y plus bounds dot height minus point dot y and last thing we have to do is the bottom so if corner and side bottom is equal to side bottom like this result.y is math min between point y and bounds y and result.height is going to be math absolute point y and minus bounds.y coordinate like this So let's just confirm we have the necessary cases. So we have the side bottom case, we have the side top case handling here, We have the side right handling here and we have the side left handling here. Okay. And now what we can do is go back inside of our app folder, board, board ID components canvas. And now what we are going to do is we're going to actually get this function and get the bounds so let's write const bounds to be resize bounds from libutils so just make sure you import resize bounds from libutils the same place we have the connection ID caller and pointer event to canvas point.
And in here, we're gonna pass the canvas state dot initial bounds. We're gonna pass the canvas state corner, and we're gonna pass the point that we have from the event. And then what we're going to do is write const liveLayers to be storage.getLayers and then const layer individually is going to be liveLayers.get self.presence.selection first in the array. If we have that layer, we're going to do layer.update and pass in the new bounds for that layer. And very important, passing the canvas state in the dependency array, like that.
So let's try it out. And actually not just yet. So right now it's not going to work because we are not using this method anywhere. So let's go inside of our pointer move method. Where is it?
Pointer move. There we go. On pointer move use mutation where we have the console log resizing. Now let's actually use the resize selected layer here and pass in current. And let's go ahead and add some more values here so we need the canvas state but we also now need the resize selected layer.
So let's go ahead and try this out now. Let's also add the camera in here. I forgot that we need camera as well canvas state and this is okay for now. So let's try it out. If I click here and if I start resizing there we go.
I can resize in the corner, I can resize on the side here, I can resize up or down, I can resize left or right. Perfect. But it does seem kind of glitchy to me so it could be that I made some mistakes in one of the functions. So we're gonna go ahead, well I'm gonna go ahead and see exactly where I did wrong. Yeah, especially when I grab the complete opposite side.
This is not exactly how I would expect it to behave but yeah we are doing something that's good so now I'm just gonna go ahead throughout individually looking at looking through my well this method right called resize bounce and I'm also gonna go through is it rectangle? No, it's selectionBox I'm also gonna go look through this here so I'm gonna end the chapter like this for now. If you want to, you can go ahead and play around yourself and try to fix it. Just make a commit so you don't mess up your code. And in the next chapter, I'm gonna go ahead and see how we can improve this.
Great, great job!