Now let's go ahead and let's implement the last generic tool and that's going to be the opacity tool and we're also going to have the opacity sidebar. So let's go ahead and first implement the functionality inside of our use editor hook. So I'm going to go instead of source, features, editor, hooks, use editor. And in here I'm going to add two features. So first one will be change opacity.
And then we're going to add another one which will be similar to these ones which we have at the bottom. Which is getActiveStrokeWith getActiveStroke-array. So I want to create the equivalent but for the opacity. So we're gonna go ahead and create that as well. But let's just start with the Change opacity method.
So let's go inside of types here and let's add change opacity And let's just properly type it so the opacity itself will have a value here to accept and that will be a number like this so now let's go back inside of the use editor and we're gonna go ahead and use that here there we go So inside of here we're gonna go ahead and use canvas, get active objects for each, get the object and then we're gonna call object set opacity. Like this. And opacity will be a value. There we go. And then let's not forget to call canvas render all like this and then we can go ahead and do get active opacity.
Let's go ahead and go inside of types and add the getActiveOpacity which will return a number so getActiveOpacity will work similar to these ones, right? So let's copy one. Let's copy the get active stroke color. I think that's the simplest one. So I'm going to go ahead and call it like this.
Get active opacity. But we're not going to go and do this instead. We're going to return the default to be, well, one, right? As in, OK, it's visible. We assume, right, this should technically not happen.
But, you know, this is what we will fall back to 1 will basically mean a full opacity right then the other values will be like 0.5, 0.1, stuff like that. And then instead of looking at the stroke here we are going to be looking at the opacity. And in here we will be looking at the number one as well. There we go. So that will be the get active opacity.
And now I want to go inside of the toolbar component and we're going to go ahead and copy and paste our last one like this and let's go ahead and properly add this so the icon will be RX transparency grid so let's go ahead and add this icon import RX transparency grid from react icons RX. There we go. Let's just go ahead and confirm that we have it here. So size 4 will stay the same And now what this will do is on change active tool opacity. So you should have the opacity as one of the options in your active tools here in the types.
There we go, we have opacity. Perfect. Let me scroll here at the bottom. The label will be opacity and let's go ahead and take a look at what this looks like. So if I go ahead and add a circle, there we go.
We now have the opacity button and once clicked it should activate the opacity tool. Let's just go ahead and add the custom class name here. So CN. If active tool is opacity, in that case, we're going to go ahead and give it a background gray 100. So we know it's selected like this.
Now let's go ahead and let's create the opacity sidebar. So I think the easiest thing to do is to simply copy the existing stroke width sidebar. So inside of editor components we have the stroke width. So let's copy that and let's call this opacity sidebar. The reason I want to copy this one is because it uses the slider and that's what we're gonna use here as well.
So first things first, confirm that you're working inside of the opacity sidebar and then rename the props, the component and the props here to opacity sidebar. Like this. There we go. So we're going to go ahead and simply change this to be value editor and this will be get active opacity like this. We don't need the type of value at all and this will be the one will be the default value if we can't find it.
On close is fine and now we're gonna go ahead and change this to be a simple on change value will be number and this will be change opacity and passing the value like this. There we go. Let's go ahead and see what we have to do else. So the title here will be Opacity and this will be change the opacity of the selected object or any other description that you want. Inside of here, we don't need the label, right?
Because it's pretty self-explanatory and we're only gonna have one item inside of here so we can remove everything else inside of the scroll area like this. So just a very simple div here. Instead of width value, this will be the value and this will be on change. And what we have to add is this. A maximum of one.
A minimum of zero and a step of 0.01. So we want a granular control of our opacity. We also have to change the active tool check. So we only open this if opacity is the active tool. There we go.
I think this should work. Let's remove the label and the button imports. We don't need them. And let's remove stroke dash array and width from the types. Now let's go inside of the editor component itself.
So just confirm you're inside of features editor components editor. You can go ahead and copy the last one and change this to opacity sidebar from opacity sidebar. There we go. Now let's go ahead and add this. I'm going to go ahead and copy the stroke width sidebar.
Let's add the opacity sidebar and let's now check it out. So if I add a shape here and if I select the opacity, there we go. It just looks like it's not exactly working as intended. So it looks like the get active opacity is not exactly working reactively, right? So this get active opacity does not seem to re-render.
So let's go ahead and find a way to resolve this so this is what I'm going to do we're going to use the good old useState here and useEffect, so useEffect useState from React Let's go ahead and do it like this and we're gonna change this to be initial value. Let's expand this. And then what we're gonna do is add the state, so opacity, set opacity or yeah, let's call it opacity and set opacity. Use state initial value like this and then inside of here we're gonna go ahead and do the following we're gonna modify the on change to also modify the set opacity to value like this and then we're gonna be using the opacity in here instead of the value component so let's see if this is now working somewhat better so if I go ahead and select this there we go so now I can control it but I think we have an issue here so if I add a new element and click there we go you can see how it doesn't reset back right so it only remembers the last thing we changed but I don't want it to work like that I wanted to recognize that the element has been switched and that now we have a new one here so this is what I'm going to do I'm going to go ahead and I'm going to add a use effect here and I'm going to go ahead and create const selected object to be used memo because we're gonna add this dependency array and in here we're gonna call the editor selected objects and the first one in the array.
So let's see what we have to add here. Editor.selectedobjects. All right, let's add that. So this is how this is supposed to look like. Now that we have the selected object, we're gonna do the following.
If we have selected object, set opacity, selected object, get opacity, or We're just gonna fall back to one like this. And then let's just add the selected object inside. And let's see if this will perhaps improve this. So if I go ahead now, there we go. You can see now when I change, they each hold their own value.
Perfect! So it looks like this finally fixed our issue. Perfect! So yeah, some elements from Fabric are not exactly reactive so we have to make them reactive by using the useMemo and the useEffect. Just make sure that you memoize your stuff, otherwise you might create a bunch of the useEffect calls which you did not intend to do.
Great, so we've successfully added the last generic feature. And now we are ready to go ahead and implement the text so we can go ahead and add some more items to the toolbar here which will control the font, the text styles like bold, underline, italic, etc. And then we'll do the same for the images. Great, great job.