[tiny] Slightly more efficient selection rotated page bounds / page bounds (#3178)
This PR makes a few tiny improvements to the way that selection page bounds and rotated page bounds are calculated. For bounds, we bail once we find a different rotation among the selected shapes. Previously, we grabbed all of the rotations first before comparing them; we only need to grab rotations until we find a rotation that's different from the first one. For rotating page bounds, we only look at the corners of the calculated bounds, and we mutate the resulting points after we transform them. Previously, we looked at all vertices and make a copy of the points when rotating them. The transform already creates the copy, so we can mutate it; and while the bounds are usually calculated from the vertices, using the corners gives us fewer points to transform. ### Change Type <!-- ❗ Please select a 'Scope' label ❗️ --> - [x] `sdk` — Changes the tldraw SDK - [ ] `dotcom` — Changes the tldraw.com web app - [ ] `docs` — Changes to the documentation, examples, or templates. - [ ] `vs code` — Changes to the vscode plugin - [ ] `internal` — Does not affect user-facing stuff <!-- ❗ Please select a 'Type' label ❗️ --> - [ ] `bugfix` — Bug fix - [ ] `feature` — New feature - [x] `improvement` — Improving existing features - [ ] `chore` — Updating dependencies, other boring stuff - [ ] `galaxy brain` — Architectural changes - [ ] `tests` — Changes to any test code - [ ] `tools` — Changes to infrastructure, CI, internal scripts, debugging tools, etc. - [ ] `dunno` — I don't know ### Release Notes - SDK, slightly more performant selection bounds calculations.
This commit is contained in:
parent
a9bc79b1c2
commit
e764e59cda
1 changed files with 18 additions and 13 deletions
|
@ -1647,19 +1647,24 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
*/
|
*/
|
||||||
@computed getSelectionRotation(): number {
|
@computed getSelectionRotation(): number {
|
||||||
const selectedShapeIds = this.getSelectedShapeIds()
|
const selectedShapeIds = this.getSelectedShapeIds()
|
||||||
if (selectedShapeIds.length === 0) {
|
let foundFirst = false // annoying but we can't use an i===0 check because we need to skip over undefineds
|
||||||
return 0
|
let rotation = 0
|
||||||
}
|
for (let i = 0, n = selectedShapeIds.length; i < n; i++) {
|
||||||
if (selectedShapeIds.length === 1) {
|
const pageTransform = this.getShapePageTransform(selectedShapeIds[i])
|
||||||
return this.getShapePageTransform(this.getSelectedShapeIds()[0])!.rotation()
|
if (!pageTransform) continue
|
||||||
|
if (foundFirst) {
|
||||||
|
if (pageTransform.rotation() !== rotation) {
|
||||||
|
// There are at least 2 different rotations, so the common rotation is zero
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// First rotation found
|
||||||
|
foundFirst = true
|
||||||
|
rotation = pageTransform.rotation()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const allRotations = selectedShapeIds.map((id) => this.getShapePageTransform(id)!.rotation())
|
return rotation
|
||||||
// if the rotations are all compatible with each other, return the rotation of any one of them
|
|
||||||
if (allRotations.every((rotation) => Math.abs(rotation - allRotations[0]) < Math.PI / 180)) {
|
|
||||||
return this.getShapePageTransform(selectedShapeIds[0])!.rotation()
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1693,9 +1698,9 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
.flatMap((id) => {
|
.flatMap((id) => {
|
||||||
const pageTransform = this.getShapePageTransform(id)
|
const pageTransform = this.getShapePageTransform(id)
|
||||||
if (!pageTransform) return []
|
if (!pageTransform) return []
|
||||||
return pageTransform.applyToPoints(this.getShapeGeometry(id).vertices)
|
return pageTransform.applyToPoints(this.getShapeGeometry(id).bounds.corners)
|
||||||
})
|
})
|
||||||
.map((p) => Vec.Rot(p, -selectionRotation))
|
.map((p) => p.rot(-selectionRotation))
|
||||||
)
|
)
|
||||||
// now position box so that it's top-left corner is in the right place
|
// now position box so that it's top-left corner is in the right place
|
||||||
boxFromRotatedVertices.point = boxFromRotatedVertices.point.rot(selectionRotation)
|
boxFromRotatedVertices.point = boxFromRotatedVertices.point.rot(selectionRotation)
|
||||||
|
|
Loading…
Reference in a new issue