free transform: keep pointer capture during a rotate drag

startLayerRotate and startLayerSelectionRotate called render() on
every pointermove, which tore down the .freeLayer wrapper that owns
the rotation handle. That dropped pointerCapture mid-drag, so after
the first move event the gesture "let go" — the handle stopped
following the cursor and only a few degrees of rotation registered
before the user had to grab again.

Fixed both paths the same way the resize handler does: mutate the
layer's rotate (and centre, for multi-layer) and apply the change
directly to the affected .freeLayer's transform / position styles
inside move; only call render() on pointerup so the rest of the UI
catches up. The sidebar Rotation field updates live via
syncLayerInputs() as before.
This commit is contained in:
thePR0M3TH3AN committed 2026-06-02 10:20:16 -04:00
1 parent 31df555ae7
commit 1baa917c9a
1 file changed
+14 -3
+14 -3
View File
@@ -20255,16 +20255,21 @@
const ang = Math.atan2(e.clientY - cyPx, e.clientX - cxPx) * 180 / Math.PI;
let next = rot0 + (ang - ang0);
if (e.shiftKey) next = Math.round(next / 15) * 15;
// Normalize to (-180, 180] for cleaner numeric display.
next = ((next + 540) % 360) - 180;
layer.rotate = next;
render();
// Update the freeLayer's transform in place — calling render()
// here would tear down the handle the user is dragging and
// break pointer capture, so the drag would "let go" after one
// tick. The transform style is what renderLayers writes too.
el.style.transform = `rotate(${next}deg)`;
syncLayerInputs?.();
};
const up = () => {
document.body.classList.remove('dragging-layer');
handle.removeEventListener('pointermove', move);
handle.removeEventListener('pointerup', up);
handle.removeEventListener('pointercancel', up);
if (snapshotted) render();
};
handle.addEventListener('pointermove', move);
handle.addEventListener('pointerup', up);
@@ -20323,14 +20328,20 @@
s.layer.x = nx - w / 2;
s.layer.y = ny - h / 2;
s.layer.rotate = ((s.rot + delta + 540) % 360) - 180;
// Update each affected freeLayer in place — render() inside
// the drag tears down the handle and breaks pointer capture.
updateLayerElementBox(s.layer, isDesignerLayer);
const layerEl = document.querySelector(`.freeLayer[data-layer-id="${s.layer.id}"]`);
if (layerEl) layerEl.style.transform = `rotate(${s.layer.rotate}deg)`;
}
render();
syncLayerInputs?.();
};
const up = () => {
document.body.classList.remove('dragging-layer');
handle.removeEventListener('pointermove', move);
handle.removeEventListener('pointerup', up);
handle.removeEventListener('pointercancel', up);
if (snapshotted) render();
};
handle.addEventListener('pointermove', move);
handle.addEventListener('pointerup', up);