Updating App's Version of Fabric.JS and New Tree Architecture (Bounty + $50)
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

I'd like someone to refactor the following code so that it takes advantage of Fabric.JS 2.4.2 (currently 1.7.22) as well as a new architecture (below). Here's my detailed criteria:

  1. The solution should take advantage of the latest v. of Fabric.JS so that I can better understand the new features/changes to the framework
  2. The solution should take advantage of another answer I received on the site recently: https://bountify.co/looking-for-some-serious-feedback. I'd like it to take advantage of this new architecture so that I may more easily expand the app in my learning. Here are the files that I'd like updated (kudos to CyteBode for answering that question):

I understand that this isn't a small task so I've decided to post this with $10 and tip whoever provides the most complete solution with $50 more dollars.

Please let me know if I can provide more info that will lead to a solution. As always I will probably be interested in tinkering this further, for more tips, if you are too.

Thank you kindly!


As it currently is, the code only keeps one image (as the canvas's pic property) and removes any old one when adding a new one. It's also ingrained with the frame functionality. How do you want it to be changed so it works with multiple images?
CyteBode 1 month ago
Hey CyteBode, that somehow slipped my mind, good catch! That functionality was there originally so that only 1 image would be added to the frame space at a time. Would it be possible to have that functionality only work if a frame is selected? If it's too tricky, for now, we can cut that functionality (so long as images can still be added behind the selected frame). This is because multiple images being added to the canvas are as-important as the frame switching/adding an image behind functionality. I hope this helps/makes sense, but let me know if not! Cheers
sharper 30 days ago
Okay so currently I changed the pic to be an array (as pics) which works similarly as with the accents array. Adding multiple images works, but when a frame is enabled, they all get constrained by that frame. I also noticed that scaling the image(s) in that case is completely broken. Is that what you want?
CyteBode 30 days ago
If I have to choose between the frame functionality and adding images to either canvas + being able to scale them (unconstrained to the frame), I’d prefer to go with the latter. I am interested in better standardizing how the frame functionality works so that I may add an image (1 at a time) behind/cropped to a frame, change the frame AND still be able to add images outside of the frame. With that, the frame functionality I thought this JSFiddle looked interesting. Basically, I envision being able to have 1) an oval crop, and 2) a rectangular crop (with new frames to match, which I'd create). I mention this for context, hopefully that helps explain where my mind’s at and answers your last question! Edit: Sorry for the wall of text 😅
sharper 29 days ago
awarded to CyteBode

Crowdsource coding tasks.

1 Solution

The changes I had to make:

  • The selection isn't implemented as an implicit group anymore so canvas.getActiveGroup() doesn't work. It needs to be canvas.getActiveObjects() instead, which simplifies things a bit.
  • Some (but not all) properties were replaced with actual getters and setters so, for example, object.setLeft(object.getLeft + 1) becomes object.left = object.left + 1.
  • getWidth() and getHeight() became getScaledWidth() and getScaledHeight().
  • canvas.deactivateAll() doesn't exist anymore, so it has to be replaced with a loop through all the objects to deactivate them all and a call to canvas.discardActiveObject() to discard the active object(s).
  • The underline style is set through a boolean property instead of through thetextDecoration selection style. I also changed the bold and italic styles to use fontStyle and fontWeight directly instead of going through the selection style.
  • Removing an object is now done through canvas.remove(object) instead of object.remove().

There's a weird bug with fabric where TypeError: pointBR is undefined or TypeError: r is undefined gets thrown some of the time at initialization. I don't know what that's about, but it doesn't seem to be breaking anything.

Updated files:

Note: I noticed that the loadJsonIntoCanvas function was broken (even in the old version, so it's not due to the migration to the new fabric version) as only one accent would get loaded. I don't understand what the purpose of the code in the if condition is, but if it's bypassed with false &&, the loading works properly.

I also made it so that the center line would be removed before saving (and added back after), so it doesn't get re-added when loading.

Edit 1: Added fix for canvas.deactivateAll() and underline.

Edit 2: Fixed object.remove() -> canvas.remove(object). Started fixing the load from JSON functionality.

Edit 3: Added frame clipping and removed frame constraint. Added multi-image support. Fixed the bleed on only exterior canvas bug. Added borderify() and made shadowify() work with multiple objects at once. Added dropdown menu closing (it was annoying me to no end). Disabled deletion when editing text so that backspace and delete work properly. Made the nudge by arrow keys repeat and made it work with multiple objects at once.

Edit 4: Fixed image dragging inside the frame.

Edit 5: Fixed image clipping on frame removal and added frame clipping of selected images. Integrated undo/redo functionality, but it's still buggy.

Edit 6: Fixed serialization/deserialization and undo/redo functionality.

Thanks for awarding me the bounty and tipping me! And last time, too - I'm sorry I forgot to thank you then.
CyteBode 30 days ago
Hey, not a problem—you are most welcome. I appreciate your help.
sharper 29 days ago
2 issues that've cropped up: 1) why might adding text to the Interior canvas not obey the Bleed Area functionality (233 in script.js)? and 2) Toggling frames doesn't seem to work, for me? Is it for you? I can select any one frame okay, but changing it doesn't do anything.
sharper 29 days ago
The bleed bug was already in the old version (but I can look into it). Line 233 is actually empty so you might not have the latest version. Toggling frames works for me in my version. I've got the frame clipping working, but I still need to iron out some kinks. Edit: I've fixed the bleed bug. It was just that the bleed function was only applied to the main canvas instead of both.
CyteBode 29 days ago
That's right, you mentioned that, my bad. Would you care to, for a tip? And my mistake, I didn't have the latest version—toggling works now, thank you. Standing by—look forward to seeing what you come up with! Cheers.
sharper 29 days ago
CyteBode, this looks incredible. Thank you. The only issue I see yet after updating all of the files is that the image added to the frame isn't movable inside of the frame. I can rotate it, but not drag it. Is this the case for you?
sharper 29 days ago
Yeah, that's because the drag of the frame takes over, even though it's set to be non-selectable. I don't really know how to fix this. The image can still be moved, so long as it's being dragged from a point outside the frame.
CyteBode 29 days ago
Oh, that makes sense! Do you think it might be possible, for only what image might be in the frame, to have some sort of "padded border / drag" so that I can click the image from outside the frame to more easily move? Let me know if that doesn't make sense, and thanks again!
sharper 29 days ago
Thanks for the additional tip! What you described would be a possible workaround, and it could accomplished by wrapping the image in a group alongside an invisible object that's bigger than the image. However, there's nothing to keep that embiggened image from becoming smaller than the frame and going back to being unmovable. I've actually had a few occasions while testing where I could freely move the image inside the frame, perhaps depending on the order of operation. It might have something to do with z-ordering. I'll have to investigate further.
CyteBode 29 days ago
Aha! I found the solution after a quick trip through the docs. There's a evented property that can be set to false so that events (such as a drag) can pass right through the object. There's also a hoverCursor property that can be set to "default" to keep the cursor from turning into the all-scroll cursor when hovering over the object. I've updated script.js and moving images inside the frame is now completely seamless.
CyteBode 29 days ago
Hey hey, great work! I appreciate you digging into that for me. This is excellent. 🙌
sharper 29 days ago
CyteBode, would it be tough to have it so that selecting No Frame after having selected a frame and adding an image would disable the clipping/binding of the single image? Please let me know if that doesn't make sense. Here's an image of what happens when I select No Frame after already having selected a frame and adding an image. Cheers. https://imgur.com/a/CcmkD8C
sharper 29 days ago
Yeah, that makes sense. I can also make it so adding a frame while having some images selected will clip them. I think that should be user-friendly enough.
CyteBode 29 days ago
That would be awesome! Also, would you be interested in incorporating ONLY the undo/redo functionality from this snippet? https://jsfiddle.net/gableroux/tv29xfkg/10/ If so, what would be a fair tip for you to incorporate that? Thank you
sharper 29 days ago
Yeah, I can do that as well. Where do you want the undo/redo buttons to be?
CyteBode 29 days ago
Sweet! 👍How about to the left of the Save dropdown menu
sharper 28 days ago
I did what I could to integrate the undo/redo functionality, but it's still not working right. The whole thing is turning into a pile of spaghetti code and it's getting hard to maintain. I also fixed loadJsonIntoCanvas() in the process so loading from JSON works properly now.
CyteBode 28 days ago
Understandable, I've thrown a lot at you! Thank you, again—I'm going to play with this for a while! If you have any ideas for how you might better organize it so it's less spaghetti code, I'd love to learn more! Maybe we could open a private repo or something, to make working on it a little easier. Cheers!
sharper 28 days ago
Thanks for the last two tips. The problem right now with the undo/redo feature lies in how the serialization/deserialization is done (the memento code per se is impeccable). It's because it's using fabric's serialization logic as-is, but there's this data structure that's maintained inside the canvases that isn't expressed in the JSON. Then during loading, it all needs to be re-linked through those id's that had to be tacked on the objects. It's all very messy. I thought I had fixed loadJsonIntoCanvas(), but it's still broken. The frameClip just doesn't get re-loaded properly.
CyteBode 28 days ago
Instead, there really should be a custom serialization/deserialization logic that naturally follows the data structure so none of that manual re-linking needs to be done, and that only uses fabric's logic on a per-object basis. Plus, I wouldn't have to fight against it just to treat the center line and the frame clip separately. Speaking of the data structure, tacking on properties (i.e. frame, pics, mementoConfig, etc.) to the canvas objects is just bad practice. It should all be inside a FaceCard class instead, with the respective canvas as a member. All the face-specific stuff such as serialization/deserialization and state management should be in there too. A private repo would be nice. Bitbucket has free private repos for <= 5 users.
CyteBode 28 days ago
You're welcome. That sounds much cleaner. I’d love to continue working with you on this if you’re into it. I can create a private repo and invite you (I think I’ll need an email?). It may be a week or 2 before I get back to this more seriously again but I would like to fix the frame clip bug/what (as soon as you're able/willing) other bugs you may be able to fix in the current "spaghetti-state", haha. Let me know what you think, thanks again!
sharper 28 days ago
As long as you don't have any more new feature to add in the near future, I could take a homestretch and fix the code despite the spaghetti.
CyteBode 28 days ago
Okay. That's correct, I think we got everything I wanted!
sharper 28 days ago
I finally managed to get things working mostly right (and much better than before). There's just one thing I've found to break sporadically while testing and it's that the texts can sometimes end up in the upper-left corner when undoing/redoing. I'm not too sure what that's about. Everything else is working great otherwise.
CyteBode 27 days ago
Woo! I'm happy to hear it. Great work, thanks! I've created a private repo, too, to hopefully make future work together a little easier. Let me know your Bitbucket username or email and I'll invite you to it. :) I'll be paid again in a few days and have set a reminder to tip you again for these recent changes. Cheers!
sharper 26 days ago
You can send me a personal message on Bountify (by clicking on my name and going into the "Contact" tab) and I'll be able to reply with my email. Note this will tell me what your email is, so if you don't want that, you can enable personal messages yourself, by ticking "Contact Me" in your account settings and I'll be able to send you a message directly. I've looked further into the upper-left corner bug I mentioned and it's actually occurring every time a modification is applied to multiple objects at once (when more than one is selected). I think it's due to how the object:modified event gets fired and how the new Fabric version handles selections.
CyteBode 26 days ago
Thank you for explaining that, I had no idea we could do this on the site. I enabled it out of curiosity—please shoot me a message at your convenience and we'll get you in the repo! :) Also, thanks for looking more into that bug. Looks like that'll be next! Haha. I look forward to hearing from you. Cheers 🍻
sharper 26 days ago