Building a Figma-like Transformation Layer for DeckGL: Harder Than It Looks
I was working on a feature called Image Alignment for SpatialX, we needed object transformation controls—those familiar resize handles and rotation grips you see in Figma or design tools. Simple, right? Just drag to resize, grab the corner to rotate. How hard could it be? Turns out, super challenging.

The DeckGL Constraint
Since we're already using DeckGL for our spatial visualization, switching to something like Fabric.js wasn't an option. Plus, Fabric's interaction patterns felt clunky compared to the smooth, intuitive feel of modern design tools. I wanted that Figma-like experience where everything just feels right.
The Invisible Complexity
Here's the thing about good UX—when it works perfectly, you don't notice it exists. You just drag a corner and expect the object to resize while keeping the opposite corner fixed. You rotate something and expect the cursor to show the right direction. These interactions are so natural we take them for granted.
But implementing them? That's where things get messy.
Problem 1: The Math Gets Wild
Resizing a rotated object isn't just about changing width and height. When you drag the top-right corner of a 45-degree rotated rectangle, which direction should it resize? The math involves coordinate transformations, rotation matrices, and ensuring the opposite edge stays perfectly fixed.
I found myself deep in trigonometry, calculating scale origins and transforming mouse coordinates between different coordinate spaces. There were moments where I stared at the screen wondering if I'd bitten off more than I could chew.
Problem 2: No Standard Rotation Cursors
This one caught me off guard. CSS (and operating systems) provide built-in cursors for resizing—nw-resize
, ne-resize
, etc. But there are no standard cursors for rotation handles.
Every design tool handles this differently. Figma, Sketch, Penpot, Framer—they all had to create custom cursors for rotation. Some use the same rotation icon for all corners, others create directional rotation cursors that show which way the corner will move when dragged.
I ended up building custom SVG rotation cursors that change based on which corner you're hovering over. It's one of those details where every design tool has to reinvent the wheel because there's no standard solution.

Learning from the Best
When I got stuck (which was often), I looked at how the pros do it. I dove into tldraw's source code to understand their rotation-aware resize logic. I studied Penpot's geometric transformations. Each reference helped piece together the puzzle.
The breakthrough came from tldraw's approach: calculate the distance from the drag point to the scale origin, rotate both points by the negative object rotation, then compute the scale ratio. Elegant once you see it, but took forever to figure out.
The Two-Zone Solution
I ended up with a two-zone interaction model:
- Resize zones: Thin areas along edges and corners for resizing
- Rotate zones: Outer zones around corners for rotation
This separation makes interactions predictable. You know exactly what will happen when you hover over different areas. It's inspired by Figma's interaction model but adapted for DeckGL's layer-based architecture.

The Magic of AI Pair Programming
I have to be honest, Claude Code was incredible throughout this process. When I got lost in coordinate transformations or couldn't figure out why the rotation center was off, Claude Code helped break down the math and spot the bugs. It's like having a patient math tutor who never judges you for making the same trigonometry mistake three times.
The Result
What started as a "quick feature" became a full transformation library. It handles move, resize, and rotate operations with pixel-perfect precision. The cursors change based on rotation. The resize behavior feels natural even on rotated objects. The UI is clean and modern.
But most importantly, it just works. Users can transform objects without thinking about the complexity underneath—which was the whole point.
Takeaways
- Simple UX often hides complex implementation. What looks trivial from the user's perspective can require deep technical work.
- Study the masters. Open source projects like tldraw and Penpot are goldmines for learning interaction patterns.
- AI pair programming is powerful. Having Claude as a coding partner made tackling the complex math much more manageable.
- Constraints breed creativity. Being locked into DeckGL forced me to build something custom that ended up being better than off-the-shelf solutions.
Give your reaction
Or wanna share your thoughts?
Suggestion