Why Not Fabric.js or Konva?
"Just use Fabric.js."
We heard this a lot. And for most canvas apps, it's good advice. Fabric.js and Konva handle object management, selection, transforms, serialization. Months of work, free.
So why build from scratch?
What These Libraries Do Well
Object model. Shapes are objects with properties:
const rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 50,
height: 50
});
canvas.add(rect);
Selection and transforms. Built-in selection boxes, rotation handles, scaling. All the interaction work we'd have to build.
Events. Click, drag, hover—all wired up.
Serialization. canvas.toJSON() and back. Persistence solved.
For most apps, this is 80% of the work done for you.
The Vector Network Problem
Figma introduced vector networks. A vertex can connect to any number of segments. Lines branch, merge, form complex topologies.
●
/|\
/ | \
●──●──●
| | |
●──●──●
Fabric.js has fabric.Path. One stroke, one fill. No branching.
// Fabric can do this:
new fabric.Path('M 0 0 L 100 100 L 200 0');
// But not this: one vertex connected to 3 segments
// Paths are sequences, not networks
This isn't a bug. Fabric.js models SVG paths correctly. But SVG paths are linear sequences, not graphs.
Per-Segment Styling
In Figma, each segment can have different:
- Dash patterns
- Stroke width
- Start/end caps
●────●╌╌╌╌●━━━━●
(solid) (dashed) (thick)
Fabric.js applies stroke properties to the entire path. You can't dash one segment and solid another.
Workaround: Split into multiple paths. Now they're not connected. Move one vertex, the others don't follow.
Custom Render Pipeline
These libraries use Canvas2D internally. All the Canvas2D limitations apply.
Need Linear Burn blend mode? Not happening. Need efficient GPU caching? Not without rewriting the renderer. Need custom shader effects? Go build it yourself.
They abstract Canvas2D. They don't transcend it.
Performance at Scale
Fabric.js stores objects as JavaScript objects. Renders with Canvas2D. For hundreds of objects, fine.
Design tools have thousands of objects. Nested groups. Effects stacked on effects.
// Every frame
canvas.renderAll(); // Loops through all objects
// Calculates transforms
// Redraws everything
No spatial indexing. No GPU texture caching. No retained mode.
Konva improves on this with layers and caching, but it's still JavaScript loops calling Canvas2D.
Feature Gaps
What Figma has that these libraries don't:
| Feature | Fabric.js | Konva | Figma |
|---|---|---|---|
| Vector networks | ❌ | ❌ | ✅ |
| Per-segment styling | ❌ | ❌ | ✅ |
| All blend modes | ❌ | ❌ | ✅ |
| GPU acceleration | ❌ | Partial | ✅ |
| Layer effects | Basic | Basic | ✅ |
| Boolean operations | ❌ | ❌ | ✅ |
| Constraints | ❌ | ❌ | ✅ |
| Component system | ❌ | ❌ | ✅ |
This isn't criticism. These libraries solve different problems. They're not trying to be Figma.
When Fabric.js/Konva Make Sense
Image editors. Filter photos, add text overlays, crop and resize. Perfect fit.
Diagram tools. Flowcharts, organizational charts. Shapes with connectors.
Whiteboards. Freeform drawing, sticky notes, simple shapes.
Presentation builders. Slides with text, images, basic shapes.
Annotation tools. Mark up images or documents.
For these, building from scratch is wasted effort.
When to Build Custom
Vector editing. The core data model (vector networks) isn't supported.
Professional rendering. Need blend modes and effects Canvas2D can't provide.
Performance critical. Thousands of objects, 60fps, complex scenes.
Novel interaction patterns. If you're inventing new ways to manipulate graphics, libraries constrain you.
The Real Answer
Use them for prototyping. Seriously.
We prototyped in Fabric.js. Learned what worked, what didn't. Understood the object model, the transform math, the event handling.
Then we rebuilt with:
- Custom vector network data model
- Skia/CanvasKit renderer
- Custom selection and transform logic
The prototype taught us what to build. The custom implementation delivered what Fabric.js couldn't.
Summary
Fabric.js and Konva are excellent libraries. For their use cases.
Figma-level vector editing isn't their use case.
The gaps:
- No vector networks (core data model)
- No per-segment effects (key feature)
- Canvas2D renderer (performance ceiling)
If you need these, no library saves you. You build it.
Next: Why Not SVG? →