Repository navigation
fix(studio): a resized corner stays on the pointer when the size rounds to whole pixels - #5213
Draft
miguel-heygen wants to merge 6 commits into
Draft
miguel-heygen wants to merge 6 commits into
miguel-heygen wants to merge 6 commits into
Conversation
…ds to whole pixels Resized sizes stay on whole CSS pixels (GSAP centres a -50% translate from the integer offset size), so the centre-anchored resize left the grabbed corner up to a third of a pixel times the element's scale off the pointer: 0.53 px on a 1.5x scaled layer. The centre pin now takes half the rounding remainder along the element's rendered edges, so the grabbed corner lands where the wanted size puts it while the written size stays whole.
Edit accuracy: accurate 2061 (base branch 2059), smooth 1652 of thoseThe gate passes. Newly passing (2)
Quarantined, measured but not gated (0) |
finalizeScaleResizeCommit skipped its position correction whenever the box sat within 0.5 px of the drop point on each axis, so a sub-pixel drop (now the norm, with the grabbed corner on the pointer) saved up to half a pixel off. It now skips only when the correction rounds to nothing at the precision the file is written in.
finalizeScaleResizeCommit lined the committed box up with the drop by its top-left corner. When one scale cannot reproduce the dragged width and height (the draft rounds each to whole pixels), that put the whole gap on the far edges, up to half a pixel. The resize is centre-anchored, so it now lines up centres and the gap splits evenly.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
During a corner resize, the grabbed corner now stays on the pointer when the element's size rounds to whole pixels. The written width and height stay whole, as before.
Why
Studio writes resized sizes in whole CSS pixels (#4766): GSAP works out a
-50%centring from the element's integer offset size, and a fractional size once saved a centred element 113 px off. A corner resize keeps the element's centre planted, so rounding the size moved the grabbed corner off the pointer by up to about 0.35 px times the element's rendered scale.On a layer that GSAP scales to 1.5x, that is up to 0.53 px. The edit accuracy bench's two remaining misses,
resize-scale-px-r30-root-z50-after(0.53) andresize-scale-px-r30-nested-z50-after(0.52), are exactly this, and the whole scale family's tracking climbs with the scale (about 0.27 / 0.36 / 0.45 px at 1x / 1.25x / 1.5x).Related work
Refs #4766 (whole-pixel sizes stay).
How
resizeRemainderShift(domEditResizeLocal.ts): the shift of the pinned centre that puts the grabbed corner where the wanted size would. It is half the rounding remainder, measured along the element's own rendered edges, so rotation and GSAP scale are included.resizeDraft.ts) pins the centre at its gesture-start point plus that shift. The release already commits the draft's anchor as the offset, so the saved file matches what the drag showed.applyStudioBoxSizeDraftreturns the size it wrote; the whole-pixel rule moved into one helper,roundToLayoutSize(utils/rounding.ts), used by every size write inmanualEditsDom.ts.finalizeScaleResizeCommitthen moves the box onto the drop point. It skipped that correction whenever the box was within 0.5 px of the drop point on each axis, so the first CI run of this PR showed the saved box up to 0.51 px off the drop (drop/reload). It now skips only when the correction rounds to nothing at the precision the file is written in (3 decimals). A scale resize can therefore save a sub-pixel position correction when the drop sits a fraction of a pixel off the committed scale's box.scalefor both axes, which cannot reproduce the draft's separately rounded width and height, so the second CI run put the whole gap on the far edges (drop0.46-0.55 on the-oncases). The resize is centre-anchored, so the correction now lines up centres and the gap splits evenly, as it did on main when the correction was skipped.Test plan
anchoredResizeCommitFeedsOffset.test.ts: a drag that asks for 300.6 x 150.3 writes 301 x 150 and commits the grabbed corner exactly where 300.6 x 150.3 puts it. Fails without the fix (corner off).domEditResizeLocal.test.ts: on a 30 deg, 1.5x box, each of the four corners lands on its wanted position.gsapResizeIntercept.test.ts: a scale resize leaves a static position alone when the drop is centred on the committed box, and moves it by exactly 0.3 / -0.2 px when the drop sits that far off. The second case fails on main (0.5 px skip); both fail with top-left alignment.resize-scale-*case's tracking fell from 0.25-0.53 px to 0.02-0.19 px;dropandreloadon four-aftercases were the remaining misses.-oncases missed ondrop(0.46-0.55), fixed by the centre alignment above.components/editor,hooksandutilssuites: 4339 passed.tsc --noEmit, oxlint, oxfmt, comment ratchet and Fallow clean.Size
9 files, about +125 / -20, about half of it tests.