[Bug]: Rotating shape while holding it with mouse translates it too
What happened?
When I rotate a shape while also holding it and translating it, I get weird behavior (see recording).
How can we reproduce the bug?
https://github.com/user-attachments/assets/797d9c84-0a1d-46ef-98ae-ee1fd477cc11
Notice when I rotate the shapes without holding them, they rotate as expected. Only when I pick them up and am still holding them and rotate do I get awkward additional translation behavior. Also, this happens consistently on Safari. In Firefox, it also happens, but if you keep the mouse still during rotation it's fine. Once you start translating again in Firefox, you see the jump.
Minimal reproduction at https://stackblitz.com/edit/vitejs-vite-ztlg36aq?file=src%2FApp.tsx
import { Tldraw, TLUiOverrides } from 'tldraw';
import { JustForSandbox } from './JustForSandbox';
import 'tldraw/tldraw.css';
import './styles.css';
const overrides: TLUiOverrides = {
actions: (editor, actions) => {
return {
...actions,
rotateCW: {
id: 'rotate-cw-hover',
label: 'Rotate clockwise',
kbd: 'w',
onSelect: () => {
editor.rotateShapesBy(editor.getSelectedShapeIds(), Math.PI / 4);
},
},
};
},
};
export default function App() {
return (
<div style={{ position: 'fixed', inset: 0 }}>
<Tldraw autoFocus={false} overrides={overrides}>
<JustForSandbox />
</Tldraw>
</div>
);
}
Also, for what it's worth, even if I implement the rotation manually and bypass rotateShapesBy by calculating the new top left corner position with vector math and apply the updateShape by setting x, y, and rotation I get the same behavior: works for a stationary shape, but translates while holding and rotating.
What browsers are you seeing the problem on?
Safari, Firefox
Where did this happen?
The developer package
Contact Details
Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Thanks for the report! I can see why this bug is happening.
Our translation interaction takes a 'snapshot' of the shape(s) it is moving at the start of the interaction, then on every frame it calculates the new position based on how far the mouse has moved since the start of the interaction and where the shapes were at the start of the interaction.
In order to support doing rotations during the interaction we'd need to do one of two things to the translation code:
- detect 'outside' changes to the translating shapes and recreate their snapshot if need be.
- apply deltas incrementally instead of from scratch on every frame.
probably the second one would be simpler to achieve but it might hurt performance a little when translating a lot of shapes because we'd need to do extra bookkeeping.
I'll add this issue to our backlog. Is it blocking your work or just something you noticed?
I'll add this issue to our backlog. Is it blocking your work or just something you noticed?
it's not blocking, but feels unexpected. specifically, I'm implementing a board game on the web: https://arcs.place. it's quite common to need to move cards and tokens around the area and rotate them and then this bug makes you think something is weird. you can always pre-rotate the shape or drop it then rotate it or just deal with the offset, but it feels disorienting every time. one example below, but comes up in cards and all other shapes too.
ideal flow (recorded from another implementation I have):
https://github.com/user-attachments/assets/421d4ef5-5637-4bac-95e2-d28ded06d17d
current buggy flow:
https://github.com/user-attachments/assets/60bc285c-9f18-4460-9897-3f4436f0a586