Now let's go ahead and let's add some image specific toolbar elements right here. So the same way we had some specific elements for the font, we now have some specific elements for images. So I want to go inside of the toolbar option. I meant the toolbar component. And let's go ahead and let me find my is text.
And let's go ahead and now write is image. And that's simply going to check if selected object type is image. So now we have is text and is image. So first things first, there are some things I immediately want to remove from the image. So let's see what happens if I change this.
So nothing happens if I work with this. How about the stroke? So it looks like images can have a stroke. So I should probably leave that. But it looks like changing the actual background doesn't do much.
So if you want to, you can use the newly created is image and use the negative of it to hide the fill color for example. You can go ahead and wrap this if it's not image then show this. So it's going to show for text and for shapes Like this. So let's go ahead and try it out. Let me refresh this.
So we have an image here. And there we go. You can see how now the fill color no longer appears so only the stroke color appears and we can go ahead and play around with stroke. Great! But now I want to add a tool which will only appear when an element is image and we're going to show that after our last one which was I believe the font size element So let's go ahead and simply find our font size input.
It's right here. So what I'm going to do is I'm just going to copy this one above font size because it has the icon format, which is the one we need. And let's paste that below the font size input. Let's change this to only show if is image and then what we are going to do is we are going to check this won't be properties align instead this will be if active tool is whoops filter like this. And instead of calling on change text align this will be on change active tool filter And the icon will be TB color filter.
Let's go ahead and let's import this. So import TB color filter from react icons TB. There we go. Let's change the label here to be filters. Let's try it out now.
So I'm going to refresh my page here. I'm going to add an image from Unsplash. And there we go. You can see how now we have filters here and when I click on them they stay selected because the active tool is now filter but we are missing the filter sidebar so that's the next thing that we have to implement. So let's go ahead and let's go inside of the use editor and what we are going to do is we're going to add change image filter.
It's going to accept the value which will be a string and let's immediately go inside of types in the editor interface and let's add change image filter it will return a void and let's not misspell the string Now inside of the change image filter, first of all, let's get all objects. So canvas.getActiveObjects. And then objects for each, we get the individual object. If object type is image, in that case, let's define the image object to be object as fabric dot image and then let's go ahead and let's create a util which depending on the value we sent will create a proper filter So we're gonna have to create a util for that. So I wanna go inside of my features editor, utils, right here.
And let's go at the bottom here and let's export const createFilter. Value will be a string and by default the effect will be undefined. And we are going to switch on the value and then in here we're gonna go ahead and actually create specific filters based on the keyword which we are going to pass inside of here. So let's go ahead and let's import fabric from fabric and let's go ahead and start with all the options so if case is Polaroid in that case effect will be new fabric image filters dot Polaroid And we also have some type errors in here so be careful not to misspell this. So this is Polaroid, like this.
And let's add csignore. Like this. Now let's go ahead and let's break this. And let's copy and paste this one. The other one will be Sepia.
And the filter here will be Sepia as well and you can remove the TS ignore for this one because Sepia is recognized as a filter. The next one is going to be Coda Chrome and it will call the Coda Chrome method but unfortunately the TS ignore is needed here. After Coda Chrome let's add the contrast filter. So this will not need the TS ignore and we'll simply call the contrast and inside of the options here we can change the contrast to 0.3 below the contrast we're gonna have brightness and we're gonna call the brightness and we're going to change the brightness value to 0.8 after that let's go ahead and copy and paste it and we're gonna change this to brownie and let's call brownie method. But we do need the TS ignore here.
Below the brownie we're gonna have vintage which will also need TS ignore and let's call vintage. Below that let's add Technicolor which will also need TS ignore and it's going to call Technicolor. So be careful not to misspell these because TS ignore will not warn you if these are misspelled. So for all of these which have TS ignore just be careful. You can always check my source code and simply copy from there and skip this part if that's easier.
Below the Technicolor we're gonna have Pixelate which we'll call Pixelate and good thing is that we don't need TSignore for that. After pixelate let's get invert which we'll simply call invert. After invert we're gonna have blur. After blur we're gonna have sharpen. For the sharpen, my apologies, it's not gonna be sharpen.
It's gonna be convolute. And we're gonna have some properties. So we are simply gonna create a matrix here of 0, minus 1, 0, minus 1 again, 5, minus 1, 0, minus 1 and 0. So these are simply the settings that look good for a filter. You can go ahead and of course play around with this or read more about Convolute in the official documentation.
After the Sharpen, we're going to have Emboss. So it's also going to be using convolute here, but it's going to be a little bit different. So in here the values are going to be 1111.7, minus one, minus one, minus one, and minus one. After emboss, we're gonna have remove color and this will simply call the method remove color And inside of here, we're gonna define the threshold to be 0.2 and distance to be 0.5. And unfortunately, we're gonna need TS ignore here.
So just make sure not to misspell these values inside of the options as well. Below remove color, we're going to have black and white, which we'll call the black white effect and black white effect has no options inside. Below that we're gonna have vibrance, which we'll call vibrance and open up the options and write vibrance 1 inside. Below that We're gonna have blend color and we don't need TS ignore here because we're gonna be using the blend color here and inside of here you can define any color you want to blend with so let's go ahead and use this neon green color and let's add mode multiply. And now there's just a couple of more left here.
After blend color we're gonna have hue rotate which we'll call the hue rotation And we are simply going to define rotation to be 0.5. After hue rotate, we're going to have resize, which we'll call the resize method. And resize will not have any options inside of it. And last one will be the gamma effect. So let's go ahead and simply call gamma.
And let's define this to be 1, 0.5 and 2.1 and we have to add tsignore here and now let's add the default case where effect will be null and return. And finally, return the effect. There we go. So a pretty big method, which we'll be able to handle all of these strings in order to create a proper effect or a filter using Fabric. So I want this to have a lot of effects so this can be a useful editor.
Great! Now let's head back inside of the Use Editor here And what we want to do now is define const effect to be create filter from features editor utils. So I added it here alongside is text type. And inside of here We're gonna pass in our value and then imageObject.filters will check if effect is present. Go ahead and add the effect in the array, otherwise switch to an empty array.
And yes, you can combine effects, but I'm not gonna do this because I found them to be more useful individually. And then let's call a method on the image object called applyFilters and canvasRenderAll. There we go. Now that we have the change image filter method, let's go ahead and let's create the sidebar. So for the sidebar, what we can use is inside of Features, Editor, Components and we should have the Font Sidebar.
So just copy and paste this and let's call it Filter Sidebar. Make sure you are inside of the Filter Sidebar and close everything else. Rename all instances of font sidebar to filter sidebar and go ahead and check that the active tool is filter. Then let's go ahead and give the title to be filters and let's go ahead and write apply a filter to your image or to selected image. There we go.
So what we want to do now is we want to iterate over all of our filters. So let's go ahead and let's create a list inside of types here. So I'm going to go to the top here and just as we've created the constant for fonts, we are now going to create a constant for all of our filters. So you can pause the screen and copy this. They're the exact same ones we've wrote in our method a moment ago, or you can copy this from the source code.
Great, so save the file, make sure you have the filters constant right here and now let's go ahead and let's iterate over them instead. So inside of here we're going to go ahead and call filters from features editor types right here and you can remove the fonts We are no longer going to need those. And we are going to keep this. Let's go ahead and just make the value none. My apologies, null for now.
And let's go ahead and remove the style. We're not going to need this and inside of here, we are not iterating over fonts. We are working with the individual filters. So this will be a filter, this will be a filter, and this will be a filter. And the editor will call change image filter and pass in the filter.
Like that. There we go. So we will have to do some slight modification in here to actually get the active value but we're going to do that in a second. Let's first go inside of the editor itself. Let's copy the image sidebar and add a filter sidebar.
And now let's copy and paste our rendering of the image sidebar with the filter sidebar this time. And now finally, if you go ahead and refresh your project here, add an image and click on filters. There we go. So I'm going to try and click on brightness and there we go. You can see how each of our filters is doing something.
Perfect. So it seems to me that like we might have some issues on some specific ones. So let's go ahead and try and debug all of them. So gamma is working, saturation, I'm not sure, saturation and resize. Saturation and resize don't seem to be doing much.
I'm not sure if it's maybe because of the image. But black and white seems to be working. Let's see if grayscale. So grayscale seems to not be working. Let's go ahead and let's slightly debug our filters until we see which ones are faulty.
So I'm going to go inside of the utils here, my apologies, inside of the utils of my editor where we wrote this method here to create the filters. So let's find the first faulty one. I assume most of the faulty ones are gonna be the ones where we added the TypeScript ignore. So can I find a grayscale here? Oh, it looks like we've added some which don't actually exist in here.
So this is what I'm going to do. I'm gonna go ahead and I'm gonna open them side by side. Here the editor and here the types. So the Polaroid exists, the Sepia exists, Kodachrome exists, the contrast exists, the brightness exists. And let me see, perhaps I missed the function to create the grayscale.
And I did, Yes, because grayscale actually exists. So anywhere, go ahead and add if case is grayscale. What we're gonna do is we're gonna define the effect to be new fabric.image.filters.grayscale. So I want to add this because it exists without any TypeScript issues. So write it like this in one line.
There we go. So that will resolve the grayscale. So now we have grayscale. Let's see what else did we miss perhaps. So we have browning, we have vintage, we have technicolor, we have pixelate, we have invert, we have blur, we have sharpen, we have emboss, we have remove color, we have black and white, we have vibrance, we have blend color, hue, rotate, we have resize, we have gamma and looks like we don't have saturation so let's go or do we have saturation?
We don't. Let's go ahead and let's create saturation as well. So I'm gonna go ahead and go ahead and copy this one and I'm gonna add the case saturation. Let me just confirm that we don't have this. Yes, we forgot to add that one.
So saturation here exists so we can remove the TypeScript ignore, but we have to add the saturation option to be 0.7. There we go. So it Looks like we missed two of these. Perfect. And if the other ones are still not working, you can simply remove them from the constant filters here.
So let's go ahead and try this again. I'm going to add an image here. I'm going to open my filters and There we go. So let's see if this grayscale... Is grayscale working or not?
Looks like grayscale is still not working for me. Why is it not working? I think that it should work. Grayscale. Did I misspell?
Yes. Grayscale with an A instead of an E. So let's go ahead and try this again on an image. And let's hope that finally we can have the grayscale. There we go.
We now have grayscale. Perfect. So what I want to do now is I want to create a method which will get the current active filter And then we can label it as active inside of here So let me close everything because we have way too much stuff open at the moment let me zoom back in a bit and let's go inside of the use editor here and I'm gonna go ahead and simply find for example get active opacity let's copy this one and let's go ahead and add it here get active image filter or just get active filter so this will get the selected object by default it will be the getActiveFilters actually so by default it's going to be an empty array and we are looking for filters here and let's go ahead and change this to an empty array as well and we are going to need psignore here let's go inside of types here at the bottom let's get get getActiveFilters which will return an array of strings and I think a better name would be getActiveImageFilters So let's go ahead and call it that. And now let's go inside of our filter sidebar.
And then for the value here, we can use that instead. So it's going to be editor, get active. Image filters like this or an empty array. And then inside of here we can check for the first in the array like this. So let's see if this will already work or perhaps we did something wrong with the naming.
Looks like we did something wrong with naming so perhaps this is not a proper way to get the active filters. So let's go ahead and see if they have any kind of filters inside of here. Perhaps it's not something that we can see at all. So I just tried, I paused the recording and I just tried a couple of times myself. Looks like there's no way, at least what I managed to find, there's no way to get the active image filter.
That's fine. We're just gonna remove this method. Whoops. So remove the method called get active image filters, remove it from the types here and remove the value as well and simply remove the dynamic part of the class name. So this can just be a good old class name.
There we go. This means that we don't need or we still use the CN. All right. Great! So that's it.
We've created filters for our images and we can now go ahead and play along with a bunch of filters. We can now start exploring some AI tools like AI background removal or AI image generation. Great, great job!