kopia lustrzana https://github.com/Tldraw/Tldraw
Fixes rotation, translation
rodzic
638b1b3494
commit
6da9e5f019
|
@ -81,12 +81,13 @@ const circle = registerShapeUtils<CircleShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
translate(shape, delta) {
|
rotateTo(shape, rotation) {
|
||||||
shape.point = vec.add(shape.point, delta)
|
shape.rotation = rotation
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(shape) {
|
translateTo(shape, point) {
|
||||||
|
shape.point = point
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -69,12 +69,12 @@ const dot = registerShapeUtils<DotShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(shape) {
|
rotateTo(shape) {
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
translate(shape, delta) {
|
translateTo(shape, point) {
|
||||||
shape.point = vec.add(shape.point, delta)
|
shape.point = point
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -99,12 +99,13 @@ const ellipse = registerShapeUtils<EllipseShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(shape) {
|
rotateTo(shape, rotation) {
|
||||||
|
shape.rotation = rotation
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
translate(shape, delta) {
|
translateTo(shape, point) {
|
||||||
shape.point = vec.add(shape.point, delta)
|
shape.point = point
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -40,11 +40,11 @@ export interface ShapeUtility<K extends Readonly<Shape>> {
|
||||||
// Create a new shape.
|
// Create a new shape.
|
||||||
create(props: Partial<K>): K
|
create(props: Partial<K>): K
|
||||||
|
|
||||||
// Apply a translation to a shape.
|
// Set the shape's point.
|
||||||
translate(this: ShapeUtility<K>, shape: K, delta: number[]): ShapeUtility<K>
|
translateTo(this: ShapeUtility<K>, shape: K, delta: number[]): ShapeUtility<K>
|
||||||
|
|
||||||
// Apply a rotation to a shape.
|
// Set the shape's rotation.
|
||||||
rotate(this: ShapeUtility<K>, shape: K, rotation: number): ShapeUtility<K>
|
rotateTo(this: ShapeUtility<K>, shape: K, rotation: number): ShapeUtility<K>
|
||||||
|
|
||||||
// Transform to fit a new bounding box when more than one shape is selected.
|
// Transform to fit a new bounding box when more than one shape is selected.
|
||||||
transform(
|
transform(
|
||||||
|
|
|
@ -78,12 +78,12 @@ const line = registerShapeUtils<LineShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(shape) {
|
rotateTo(shape) {
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
translate(shape, delta) {
|
translateTo(shape, point) {
|
||||||
shape.point = vec.add(shape.point, delta)
|
shape.point = point
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -86,12 +86,13 @@ const polyline = registerShapeUtils<PolylineShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(shape) {
|
rotateTo(shape, rotation) {
|
||||||
|
shape.rotation = rotation
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
translate(shape, delta) {
|
translateTo(shape, point) {
|
||||||
shape.point = vec.add(shape.point, delta)
|
shape.point = point
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -78,12 +78,12 @@ const ray = registerShapeUtils<RayShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(shape) {
|
rotateTo(shape) {
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
translate(shape, delta) {
|
translateTo(shape, point) {
|
||||||
shape.point = vec.add(shape.point, delta)
|
shape.point = point
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -95,12 +95,13 @@ const rectangle = registerShapeUtils<RectangleShape>({
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(shape) {
|
rotateTo(shape, rotation) {
|
||||||
|
shape.rotation = rotation
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
translate(shape, delta) {
|
translateTo(shape, point) {
|
||||||
shape.point = vec.add(shape.point, delta)
|
shape.point = point
|
||||||
return this
|
return this
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,7 @@ export default function rotateCommand(
|
||||||
for (let { id, point, rotation } of after.shapes) {
|
for (let { id, point, rotation } of after.shapes) {
|
||||||
const shape = shapes[id]
|
const shape = shapes[id]
|
||||||
const utils = getShapeUtils(shape)
|
const utils = getShapeUtils(shape)
|
||||||
utils.rotate(shape, rotation)
|
utils.rotateTo(shape, rotation).translateTo(shape, point)
|
||||||
utils.translate(shape, point)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.boundsRotation = after.boundsRotation
|
data.boundsRotation = after.boundsRotation
|
||||||
|
@ -33,8 +32,7 @@ export default function rotateCommand(
|
||||||
for (let { id, point, rotation } of before.shapes) {
|
for (let { id, point, rotation } of before.shapes) {
|
||||||
const shape = shapes[id]
|
const shape = shapes[id]
|
||||||
const utils = getShapeUtils(shape)
|
const utils = getShapeUtils(shape)
|
||||||
utils.rotate(shape, rotation)
|
utils.rotateTo(shape, rotation).translateTo(shape, point)
|
||||||
utils.translate(shape, point)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data.boundsRotation = before.boundsRotation
|
data.boundsRotation = before.boundsRotation
|
||||||
|
|
|
@ -34,7 +34,7 @@ export default function translateCommand(
|
||||||
|
|
||||||
for (const { id, point } of initialShapes) {
|
for (const { id, point } of initialShapes) {
|
||||||
const shape = shapes[id]
|
const shape = shapes[id]
|
||||||
getShapeUtils(shape).translate(shape, point)
|
getShapeUtils(shape).translateTo(shape, point)
|
||||||
data.selectedIds.add(id)
|
data.selectedIds.add(id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -52,7 +52,7 @@ export default function translateCommand(
|
||||||
|
|
||||||
for (const { id, point } of initialShapes) {
|
for (const { id, point } of initialShapes) {
|
||||||
const shape = shapes[id]
|
const shape = shapes[id]
|
||||||
getShapeUtils(shape).translate(shape, point)
|
getShapeUtils(shape).translateTo(shape, point)
|
||||||
data.selectedIds.add(id)
|
data.selectedIds.add(id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -45,8 +45,8 @@ export default class RotateSession extends BaseSession {
|
||||||
const shape = page.shapes[id]
|
const shape = page.shapes[id]
|
||||||
|
|
||||||
getShapeUtils(shape)
|
getShapeUtils(shape)
|
||||||
.rotate(shape, (PI2 + (rotation + rot)) % PI2)
|
.rotateTo(shape, (PI2 + (rotation + rot)) % PI2)
|
||||||
.translate(
|
.translateTo(
|
||||||
shape,
|
shape,
|
||||||
vec.sub(vec.rotWith(center, boundsCenter, rot % PI2), offset)
|
vec.sub(vec.rotWith(center, boundsCenter, rot % PI2), offset)
|
||||||
)
|
)
|
||||||
|
@ -58,7 +58,7 @@ export default class RotateSession extends BaseSession {
|
||||||
|
|
||||||
for (let { id, point, rotation } of this.snapshot.shapes) {
|
for (let { id, point, rotation } of this.snapshot.shapes) {
|
||||||
const shape = page.shapes[id]
|
const shape = page.shapes[id]
|
||||||
getShapeUtils(shape).rotate(shape, rotation).translate(shape, point)
|
getShapeUtils(shape).rotateTo(shape, rotation).translateTo(shape, point)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ export default class TranslateSession extends BaseSession {
|
||||||
|
|
||||||
for (const { id, point } of initialShapes) {
|
for (const { id, point } of initialShapes) {
|
||||||
const shape = shapes[id]
|
const shape = shapes[id]
|
||||||
getShapeUtils(shape).translate(shape, point)
|
getShapeUtils(shape).translateTo(shape, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const clone of clones) {
|
for (const clone of clones) {
|
||||||
|
@ -51,7 +51,7 @@ export default class TranslateSession extends BaseSession {
|
||||||
|
|
||||||
for (const { id, point } of clones) {
|
for (const { id, point } of clones) {
|
||||||
const shape = shapes[id]
|
const shape = shapes[id]
|
||||||
getShapeUtils(shape).translate(shape, vec.add(point, delta))
|
getShapeUtils(shape).translateTo(shape, vec.add(point, delta))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.isCloning) {
|
if (this.isCloning) {
|
||||||
|
@ -69,7 +69,7 @@ export default class TranslateSession extends BaseSession {
|
||||||
|
|
||||||
for (const { id, point } of initialShapes) {
|
for (const { id, point } of initialShapes) {
|
||||||
const shape = shapes[id]
|
const shape = shapes[id]
|
||||||
getShapeUtils(shape).translate(shape, vec.add(point, delta))
|
getShapeUtils(shape).translateTo(shape, vec.add(point, delta))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ export default class TranslateSession extends BaseSession {
|
||||||
|
|
||||||
for (const { id, point } of initialShapes) {
|
for (const { id, point } of initialShapes) {
|
||||||
const shape = shapes[id]
|
const shape = shapes[id]
|
||||||
getShapeUtils(shape).translate(shape, point)
|
getShapeUtils(shape).translateTo(shape, point)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const { id } of clones) {
|
for (const { id } of clones) {
|
||||||
|
|
|
@ -72,15 +72,10 @@ const state = createState({
|
||||||
SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" },
|
SELECTED_RECTANGLE_TOOL: { unless: "isReadOnly", to: "rectangle" },
|
||||||
TOGGLED_CODE_PANEL_OPEN: "toggleCodePanel",
|
TOGGLED_CODE_PANEL_OPEN: "toggleCodePanel",
|
||||||
RESET_CAMERA: "resetCamera",
|
RESET_CAMERA: "resetCamera",
|
||||||
ZOOMED_TO_FIT: {
|
ZOOMED_TO_FIT: "zoomCameraToFit",
|
||||||
if: "hasSelection",
|
|
||||||
do: "zoomCameraToFit",
|
|
||||||
else: "resetCamera",
|
|
||||||
},
|
|
||||||
ZOOMED_TO_SELECTION: {
|
ZOOMED_TO_SELECTION: {
|
||||||
if: "hasSelection",
|
if: "hasSelection",
|
||||||
do: "zoomCameraToSelection",
|
do: "zoomCameraToSelection",
|
||||||
else: "resetCamera",
|
|
||||||
},
|
},
|
||||||
ZOOMED_TO_ACTUAL: {
|
ZOOMED_TO_ACTUAL: {
|
||||||
if: "hasSelection",
|
if: "hasSelection",
|
||||||
|
@ -721,7 +716,7 @@ const state = createState({
|
||||||
const bounds = getSelectedBounds(data)
|
const bounds = getSelectedBounds(data)
|
||||||
|
|
||||||
const zoom =
|
const zoom =
|
||||||
bounds.width > bounds.height
|
bounds.width < bounds.height
|
||||||
? (window.innerWidth - 128) / bounds.width
|
? (window.innerWidth - 128) / bounds.width
|
||||||
: (window.innerHeight - 128) / bounds.height
|
: (window.innerHeight - 128) / bounds.height
|
||||||
|
|
||||||
|
@ -742,17 +737,12 @@ const state = createState({
|
||||||
|
|
||||||
const bounds = getSelectedBounds(data)
|
const bounds = getSelectedBounds(data)
|
||||||
|
|
||||||
const zoom = 1
|
const mx = window.innerWidth - bounds.width
|
||||||
|
const my = window.innerHeight - bounds.height
|
||||||
|
|
||||||
const mx = window.innerWidth - 128 - bounds.width * zoom
|
camera.zoom = 1
|
||||||
const my = window.innerHeight - 128 - bounds.height * zoom
|
|
||||||
|
|
||||||
camera.zoom = zoom
|
|
||||||
camera.point = vec.add(
|
|
||||||
[-bounds.minX, -bounds.minY],
|
|
||||||
[mx / 2 / zoom, my / 2 / zoom]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
camera.point = vec.add([-bounds.minX, -bounds.minY], [mx / 2, my / 2])
|
||||||
setZoomCSS(camera.zoom)
|
setZoomCSS(camera.zoom)
|
||||||
},
|
},
|
||||||
zoomCameraToActual(data) {
|
zoomCameraToActual(data) {
|
||||||
|
@ -769,7 +759,13 @@ const state = createState({
|
||||||
},
|
},
|
||||||
zoomCameraToFit(data) {
|
zoomCameraToFit(data) {
|
||||||
const { camera } = data
|
const { camera } = data
|
||||||
const { shapes } = getPage(data)
|
const page = getPage(data)
|
||||||
|
|
||||||
|
const shapes = Object.values(page.shapes)
|
||||||
|
|
||||||
|
if (shapes.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const bounds = getCommonBounds(
|
const bounds = getCommonBounds(
|
||||||
...Object.values(shapes).map((shape) =>
|
...Object.values(shapes).map((shape) =>
|
||||||
|
@ -778,18 +774,15 @@ const state = createState({
|
||||||
)
|
)
|
||||||
|
|
||||||
const zoom =
|
const zoom =
|
||||||
bounds.width > bounds.height
|
bounds.width < bounds.height
|
||||||
? (window.innerWidth - 104) / bounds.width
|
? (window.innerWidth - 128) / bounds.width
|
||||||
: (window.innerHeight - 104) / bounds.height
|
: (window.innerHeight - 128) / bounds.height
|
||||||
|
|
||||||
const mx = window.innerWidth - bounds.width * zoom
|
const mx = (window.innerWidth - bounds.width * zoom) / 2 / zoom
|
||||||
const my = window.innerHeight - bounds.height * zoom
|
const my = (window.innerHeight - bounds.height * zoom) / 2 / zoom
|
||||||
|
|
||||||
camera.zoom = zoom
|
camera.zoom = zoom
|
||||||
camera.point = vec.add(
|
camera.point = vec.add([-bounds.minX, -bounds.minY], [mx, my])
|
||||||
[-bounds.minX, -bounds.minY],
|
|
||||||
[mx / 2 / zoom, my / 2 / zoom]
|
|
||||||
)
|
|
||||||
|
|
||||||
setZoomCSS(camera.zoom)
|
setZoomCSS(camera.zoom)
|
||||||
},
|
},
|
||||||
|
|
Ładowanie…
Reference in New Issue