[fix] Fixes off-center bugs (#101)
* moves center from window center to center of element * Removes onMount in Renderer, adds onBoundsChange * Fix centered-g css * Fix zoom to fit
This commit is contained in:
parent
7d61d24398
commit
68efbf69fa
15 changed files with 125 additions and 104 deletions
|
@ -34,7 +34,7 @@ export function Page<T extends TLShape, M extends Record<string, unknown>>({
|
|||
page,
|
||||
pageState,
|
||||
shapeUtils,
|
||||
inputs.size,
|
||||
[inputs.bounds.width, inputs.bounds.height],
|
||||
meta,
|
||||
callbacks.onRenderCountChange
|
||||
)
|
||||
|
@ -59,7 +59,7 @@ export function Page<T extends TLShape, M extends Record<string, unknown>>({
|
|||
<Bounds
|
||||
zoom={zoom}
|
||||
bounds={bounds}
|
||||
viewportWidth={inputs.size[0]}
|
||||
viewportWidth={inputs.bounds.width}
|
||||
isLocked={isLocked}
|
||||
rotation={rotation}
|
||||
/>
|
||||
|
|
|
@ -56,9 +56,13 @@ export interface RendererProps<T extends TLShape, E extends Element = any, M = a
|
|||
*/
|
||||
meta?: M
|
||||
/**
|
||||
* A callback that receives the renderer's inputs manager.
|
||||
* (optional) A callback that receives the renderer's inputs manager.
|
||||
*/
|
||||
onMount?: (inputs: Inputs) => void
|
||||
/**
|
||||
* (optional) A callback that is fired when the editor's client bounding box changes.
|
||||
*/
|
||||
onBoundsChange?: (bounds: TLBounds) => void
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +87,7 @@ export function Renderer<T extends TLShape, E extends Element, M extends Record<
|
|||
}: RendererProps<T, E, M>): JSX.Element {
|
||||
useTLTheme(theme)
|
||||
|
||||
const rScreenBounds = React.useRef<TLBounds>(null)
|
||||
const rSelectionBounds = React.useRef<TLBounds>(null)
|
||||
|
||||
const rPageState = React.useRef<TLPageState>(pageState)
|
||||
|
||||
|
@ -96,7 +100,7 @@ export function Renderer<T extends TLShape, E extends Element, M extends Record<
|
|||
const [context] = React.useState<TLContextType<T, E, M>>(() => ({
|
||||
callbacks: rest,
|
||||
shapeUtils,
|
||||
rScreenBounds,
|
||||
rSelectionBounds,
|
||||
rPageState,
|
||||
inputs: new Inputs(),
|
||||
}))
|
||||
|
|
|
@ -15,17 +15,5 @@ export function useCameraCss(ref: React.RefObject<HTMLDivElement>, pageState: TL
|
|||
ref.current!.style.setProperty('--tl-camera-y', pageState.camera.point[1] + 'px')
|
||||
}, [pageState.camera.point])
|
||||
|
||||
// Update the group's position when the camera moves or zooms
|
||||
// React.useEffect(() => {
|
||||
// const {
|
||||
// zoom,
|
||||
// point: [x = 0, y = 0],
|
||||
// } = pageState.camera
|
||||
// rLayer.current?.style.setProperty(
|
||||
// 'transform',
|
||||
// `scale(${zoom},${zoom}) translate(${x}px,${y}px)`
|
||||
// )
|
||||
// }, [pageState.camera])
|
||||
|
||||
return rLayer
|
||||
}
|
||||
|
|
|
@ -5,11 +5,18 @@ import type { TLBounds } from '+types'
|
|||
export function usePosition(bounds: TLBounds, rotation = 0) {
|
||||
const rBounds = React.useRef<HTMLDivElement>(null)
|
||||
|
||||
// Update the transform
|
||||
React.useLayoutEffect(() => {
|
||||
const elm = rBounds.current!
|
||||
|
||||
const transform = `
|
||||
translate(calc(${bounds.minX}px - var(--tl-padding)),calc(${bounds.minY}px - var(--tl-padding)))
|
||||
translate3d(
|
||||
calc(${bounds.minX}px - var(--tl-padding)),
|
||||
calc(${bounds.minY}px - var(--tl-padding)),
|
||||
0px
|
||||
)
|
||||
rotate(${rotation + (bounds.rotation || 0)}rad)`
|
||||
|
||||
elm.style.setProperty('transform', transform)
|
||||
|
||||
elm.style.setProperty('width', `calc(${Math.floor(bounds.width)}px + (var(--tl-padding) * 2))`)
|
||||
|
|
|
@ -3,31 +3,48 @@ import * as React from 'react'
|
|||
import { Utils } from '+utils'
|
||||
|
||||
export function useResizeObserver<T extends Element>(ref: React.RefObject<T>) {
|
||||
const { inputs } = useTLContext()
|
||||
const { inputs, callbacks } = useTLContext()
|
||||
|
||||
const rIsMounted = React.useRef(false)
|
||||
|
||||
const forceUpdate = React.useReducer((x) => x + 1, 0)[1]
|
||||
|
||||
const updateOffsets = React.useCallback(() => {
|
||||
// When the element resizes, update the bounds (stored in inputs)
|
||||
// and broadcast via the onBoundsChange callback prop.
|
||||
const updateBounds = React.useCallback(() => {
|
||||
if (rIsMounted.current) {
|
||||
const rect = ref.current?.getBoundingClientRect()
|
||||
|
||||
if (rect) {
|
||||
inputs.offset = [rect.left, rect.top]
|
||||
inputs.size = [rect.width, rect.height]
|
||||
inputs.bounds = {
|
||||
minX: rect.left,
|
||||
maxX: rect.left + rect.width,
|
||||
minY: rect.top,
|
||||
maxY: rect.top + rect.height,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
}
|
||||
|
||||
callbacks.onBoundsChange?.(inputs.bounds)
|
||||
|
||||
// Force an update for a second mount
|
||||
forceUpdate()
|
||||
}
|
||||
} else {
|
||||
// Skip the first mount
|
||||
rIsMounted.current = true
|
||||
}
|
||||
rIsMounted.current = true
|
||||
}, [ref, forceUpdate])
|
||||
}, [ref, forceUpdate, inputs, callbacks.onBoundsChange])
|
||||
|
||||
React.useEffect(() => {
|
||||
const debouncedUpdateOffsets = Utils.debounce(updateOffsets, 100)
|
||||
window.addEventListener('scroll', debouncedUpdateOffsets)
|
||||
window.addEventListener('resize', debouncedUpdateOffsets)
|
||||
const debouncedupdateBounds = Utils.debounce(updateBounds, 100)
|
||||
window.addEventListener('scroll', debouncedupdateBounds)
|
||||
window.addEventListener('resize', debouncedupdateBounds)
|
||||
return () => {
|
||||
window.removeEventListener('scroll', debouncedUpdateOffsets)
|
||||
window.removeEventListener('resize', debouncedUpdateOffsets)
|
||||
window.removeEventListener('scroll', debouncedupdateBounds)
|
||||
window.removeEventListener('resize', debouncedupdateBounds)
|
||||
}
|
||||
}, [inputs])
|
||||
}, [])
|
||||
|
||||
React.useEffect(() => {
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
|
@ -36,7 +53,7 @@ export function useResizeObserver<T extends Element>(ref: React.RefObject<T>) {
|
|||
}
|
||||
|
||||
if (entries[0].contentRect) {
|
||||
updateOffsets()
|
||||
updateBounds()
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -50,6 +67,6 @@ export function useResizeObserver<T extends Element>(ref: React.RefObject<T>) {
|
|||
}, [ref, inputs])
|
||||
|
||||
React.useEffect(() => {
|
||||
updateOffsets()
|
||||
updateBounds()
|
||||
}, [ref])
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export function useSelection<T extends TLShape, E extends Element>(
|
|||
pageState: TLPageState,
|
||||
shapeUtils: TLShapeUtils<T, E>
|
||||
) {
|
||||
const { rScreenBounds } = useTLContext()
|
||||
const { rSelectionBounds } = useTLContext()
|
||||
const { selectedIds } = pageState
|
||||
|
||||
let bounds: TLBounds | undefined = undefined
|
||||
|
@ -50,7 +50,7 @@ export function useSelection<T extends TLShape, E extends Element>(
|
|||
const [minX, minY] = canvasToScreen([bounds.minX, bounds.minY], pageState.camera)
|
||||
const [maxX, maxY] = canvasToScreen([bounds.maxX, bounds.maxY], pageState.camera)
|
||||
|
||||
rScreenBounds.current = {
|
||||
rSelectionBounds.current = {
|
||||
minX,
|
||||
minY,
|
||||
maxX,
|
||||
|
@ -59,7 +59,7 @@ export function useSelection<T extends TLShape, E extends Element>(
|
|||
height: maxY - minY,
|
||||
}
|
||||
} else {
|
||||
rScreenBounds.current = null
|
||||
rSelectionBounds.current = null
|
||||
}
|
||||
|
||||
return { bounds, rotation, isLocked }
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Utils } from '+utils'
|
|||
import { TLContext } from '+hooks'
|
||||
|
||||
export function useShapeEvents(id: string, disable = false) {
|
||||
const { rPageState, rScreenBounds, callbacks, inputs } = React.useContext(TLContext)
|
||||
const { rPageState, rSelectionBounds, callbacks, inputs } = React.useContext(TLContext)
|
||||
|
||||
const onPointerDown = React.useCallback(
|
||||
(e: React.PointerEvent) => {
|
||||
|
@ -26,8 +26,8 @@ export function useShapeEvents(id: string, disable = false) {
|
|||
// treat the event as a bounding box click. Unfortunately there's no way I know to pipe
|
||||
// the event to the actual bounds background element.
|
||||
if (
|
||||
rScreenBounds.current &&
|
||||
Utils.pointInBounds(info.point, rScreenBounds.current) &&
|
||||
rSelectionBounds.current &&
|
||||
Utils.pointInBounds(info.point, rSelectionBounds.current) &&
|
||||
!rPageState.current.selectedIds.includes(id)
|
||||
) {
|
||||
callbacks.onPointBounds?.(inputs.pointerDown(e, 'bounds'), e)
|
||||
|
|
|
@ -151,8 +151,7 @@ const tlcss = css`
|
|||
height: 0;
|
||||
width: 0;
|
||||
contain: layout size;
|
||||
transform: scale(var(--tl-zoom), var(--tl-zoom))
|
||||
translate(var(--tl-camera-x), var(--tl-camera-y));
|
||||
transform: scale(var(--tl-zoom)) translate3d(var(--tl-camera-x), var(--tl-camera-y), 0px);
|
||||
}
|
||||
|
||||
.tl-absolute {
|
||||
|
|
|
@ -2,12 +2,13 @@ import * as React from 'react'
|
|||
import type { Inputs } from '+inputs'
|
||||
import type { TLCallbacks, TLShape, TLBounds, TLPageState, TLShapeUtils } from '+types'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export interface TLContextType<T extends TLShape, E extends Element, M = any> {
|
||||
id?: string
|
||||
callbacks: Partial<TLCallbacks<T>>
|
||||
shapeUtils: TLShapeUtils<T, E, M>
|
||||
rPageState: React.MutableRefObject<TLPageState>
|
||||
rScreenBounds: React.MutableRefObject<TLBounds | null>
|
||||
rSelectionBounds: React.MutableRefObject<TLBounds | null>
|
||||
inputs: Inputs
|
||||
}
|
||||
|
||||
|
|
|
@ -2,17 +2,27 @@ import type React from 'react'
|
|||
import type { TLKeyboardInfo, TLPointerInfo } from './types'
|
||||
import { Utils } from './utils'
|
||||
import { Vec } from '@tldraw/vec'
|
||||
import type { TLBounds } from '+index'
|
||||
|
||||
const DOUBLE_CLICK_DURATION = 250
|
||||
|
||||
export class Inputs {
|
||||
pointer?: TLPointerInfo<string>
|
||||
|
||||
keyboard?: TLKeyboardInfo
|
||||
|
||||
keys: Record<string, boolean> = {}
|
||||
|
||||
isPinching = false
|
||||
|
||||
offset = [0, 0]
|
||||
size = [10, 10]
|
||||
bounds: TLBounds = {
|
||||
minX: 0,
|
||||
maxX: 640,
|
||||
minY: 0,
|
||||
maxY: 480,
|
||||
width: 640,
|
||||
height: 480,
|
||||
}
|
||||
|
||||
pointerUpTime = 0
|
||||
|
||||
|
@ -41,9 +51,9 @@ export class Inputs {
|
|||
const info: TLPointerInfo<T> = {
|
||||
target,
|
||||
pointerId: touch.identifier,
|
||||
origin: Inputs.getPoint(touch),
|
||||
origin: Inputs.getPoint(touch, this.bounds),
|
||||
delta: [0, 0],
|
||||
point: Inputs.getPoint(touch),
|
||||
point: Inputs.getPoint(touch, this.bounds),
|
||||
pressure: Inputs.getPressure(touch),
|
||||
shiftKey,
|
||||
ctrlKey,
|
||||
|
@ -64,9 +74,9 @@ export class Inputs {
|
|||
const info: TLPointerInfo<T> = {
|
||||
target,
|
||||
pointerId: touch.identifier,
|
||||
origin: Inputs.getPoint(touch),
|
||||
origin: Inputs.getPoint(touch, this.bounds),
|
||||
delta: [0, 0],
|
||||
point: Inputs.getPoint(touch),
|
||||
point: Inputs.getPoint(touch, this.bounds),
|
||||
pressure: Inputs.getPressure(touch),
|
||||
shiftKey,
|
||||
ctrlKey,
|
||||
|
@ -88,7 +98,7 @@ export class Inputs {
|
|||
|
||||
const prev = this.pointer
|
||||
|
||||
const point = Inputs.getPoint(touch)
|
||||
const point = Inputs.getPoint(touch, this.bounds)
|
||||
|
||||
const delta = prev?.point ? Vec.sub(point, prev.point) : [0, 0]
|
||||
|
||||
|
@ -114,7 +124,7 @@ export class Inputs {
|
|||
pointerDown<T extends string>(e: PointerEvent | React.PointerEvent, target: T): TLPointerInfo<T> {
|
||||
const { shiftKey, ctrlKey, metaKey, altKey } = e
|
||||
|
||||
const point = Inputs.getPoint(e, this.offset)
|
||||
const point = Inputs.getPoint(e, this.bounds)
|
||||
|
||||
this.activePointer = e.pointerId
|
||||
|
||||
|
@ -142,7 +152,7 @@ export class Inputs {
|
|||
): TLPointerInfo<T> {
|
||||
const { shiftKey, ctrlKey, metaKey, altKey } = e
|
||||
|
||||
const point = Inputs.getPoint(e, this.offset)
|
||||
const point = Inputs.getPoint(e, this.bounds)
|
||||
|
||||
const info: TLPointerInfo<T> = {
|
||||
target,
|
||||
|
@ -167,7 +177,7 @@ export class Inputs {
|
|||
|
||||
const prev = this.pointer
|
||||
|
||||
const point = Inputs.getPoint(e, this.offset)
|
||||
const point = Inputs.getPoint(e, this.bounds)
|
||||
|
||||
const delta = prev?.point ? Vec.sub(point, prev.point) : [0, 0]
|
||||
|
||||
|
@ -195,7 +205,7 @@ export class Inputs {
|
|||
|
||||
const prev = this.pointer
|
||||
|
||||
const point = Inputs.getPoint(e, this.offset)
|
||||
const point = Inputs.getPoint(e, this.bounds)
|
||||
|
||||
const delta = prev?.point ? Vec.sub(point, prev.point) : [0, 0]
|
||||
|
||||
|
@ -231,7 +241,7 @@ export class Inputs {
|
|||
origin: this.pointer?.origin || [0, 0],
|
||||
delta: [0, 0],
|
||||
pressure: 0.5,
|
||||
point: Inputs.getPoint(e, this.offset),
|
||||
point: Inputs.getPoint(e, this.bounds),
|
||||
shiftKey,
|
||||
ctrlKey,
|
||||
metaKey,
|
||||
|
@ -252,7 +262,7 @@ export class Inputs {
|
|||
|
||||
const prev = this.pointer
|
||||
|
||||
const point = Inputs.getPoint(e, this.offset)
|
||||
const point = Inputs.getPoint(e, this.bounds)
|
||||
|
||||
const info: TLPointerInfo<'wheel'> = {
|
||||
...prev,
|
||||
|
@ -330,7 +340,7 @@ export class Inputs {
|
|||
target: 'pinch',
|
||||
origin,
|
||||
delta: delta,
|
||||
point: Vec.sub(Vec.round(point), this.offset),
|
||||
point: Vec.sub(Vec.round(point), [this.bounds.minX, this.bounds.minY]),
|
||||
pressure: 0.5,
|
||||
shiftKey,
|
||||
ctrlKey,
|
||||
|
@ -353,9 +363,9 @@ export class Inputs {
|
|||
|
||||
static getPoint(
|
||||
e: PointerEvent | React.PointerEvent | Touch | React.Touch | WheelEvent,
|
||||
offset = [0, 0]
|
||||
bounds: TLBounds
|
||||
): number[] {
|
||||
return [+e.clientX.toFixed(2) - offset[0], +e.clientY.toFixed(2) - offset[1]]
|
||||
return [+e.clientX.toFixed(2) - bounds.minX, +e.clientY.toFixed(2) - bounds.minY]
|
||||
}
|
||||
|
||||
static getPressure(e: PointerEvent | React.PointerEvent | Touch | React.Touch | WheelEvent) {
|
||||
|
|
|
@ -7,13 +7,13 @@ import { Inputs } from '+inputs'
|
|||
|
||||
export const ContextWrapper: React.FC = ({ children }) => {
|
||||
useTLTheme()
|
||||
const rScreenBounds = React.useRef<TLBounds>(null)
|
||||
const rSelectionBounds = React.useRef<TLBounds>(null)
|
||||
const rPageState = React.useRef<TLPageState>(mockDocument.pageState)
|
||||
|
||||
const [context] = React.useState(() => ({
|
||||
callbacks: {},
|
||||
shapeUtils: mockUtils,
|
||||
rScreenBounds,
|
||||
rSelectionBounds,
|
||||
rPageState,
|
||||
inputs: new Inputs(),
|
||||
}))
|
||||
|
|
|
@ -205,6 +205,7 @@ export interface TLCallbacks<T extends TLShape> {
|
|||
onShapeBlur: TLShapeBlurHandler<any>
|
||||
onRenderCountChange: (ids: string[]) => void
|
||||
onError: (error: Error) => void
|
||||
onBoundsChange: (bounds: TLBounds) => void
|
||||
}
|
||||
|
||||
export interface TLBounds {
|
||||
|
|
|
@ -220,7 +220,7 @@ function InnerTldraw({
|
|||
onRenderCountChange={tlstate.onRenderCountChange}
|
||||
onShapeChange={tlstate.onShapeChange}
|
||||
onShapeBlur={tlstate.onShapeBlur}
|
||||
onMount={tlstate.handleMount}
|
||||
onBoundsChange={tlstate.updateBounds}
|
||||
/>
|
||||
</ContextMenu>
|
||||
<div className={menuButtons()}>
|
||||
|
|
|
@ -33,20 +33,6 @@ export class TLDR {
|
|||
return Vec.sub(Vec.div(point, camera.zoom), camera.point)
|
||||
}
|
||||
|
||||
static getViewport(data: Data): TLBounds {
|
||||
const [minX, minY] = TLDR.screenToWorld(data, [0, 0])
|
||||
const [maxX, maxY] = TLDR.screenToWorld(data, [window.innerWidth, window.innerHeight])
|
||||
|
||||
return {
|
||||
minX,
|
||||
minY,
|
||||
maxX,
|
||||
maxY,
|
||||
height: maxX - minX,
|
||||
width: maxY - minY,
|
||||
}
|
||||
}
|
||||
|
||||
static getCameraZoom(zoom: number) {
|
||||
return Utils.clamp(zoom, 0.1, 5)
|
||||
}
|
||||
|
|
|
@ -119,6 +119,16 @@ export class TLDrawState extends StateManager<Data> {
|
|||
|
||||
selectedGroupId?: string
|
||||
|
||||
// The editor's bounding client rect
|
||||
bounds: TLBounds = {
|
||||
minX: 0,
|
||||
minY: 0,
|
||||
maxX: 640,
|
||||
maxY: 480,
|
||||
width: 640,
|
||||
height: 480,
|
||||
}
|
||||
|
||||
private pasteInfo = {
|
||||
center: [0, 0],
|
||||
offset: [0, 0],
|
||||
|
@ -354,6 +364,14 @@ export class TLDrawState extends StateManager<Data> {
|
|||
this.inputs = inputs
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the bounding box when the renderer's bounds change.
|
||||
* @param bounds
|
||||
*/
|
||||
updateBounds = (bounds: TLBounds) => {
|
||||
this.bounds = { ...bounds }
|
||||
}
|
||||
|
||||
/* -------------------------------------------------- */
|
||||
/* Settings & UI */
|
||||
/* -------------------------------------------------- */
|
||||
|
@ -861,14 +879,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
|
||||
const commonBounds = Utils.getCommonBounds(shapesToPaste.map(TLDR.getBounds))
|
||||
|
||||
let center = Vec.round(
|
||||
this.getPagePoint(
|
||||
point ||
|
||||
(this.inputs
|
||||
? [this.inputs.size[0] / 2, this.inputs.size[1] / 2]
|
||||
: [window.innerWidth / 2, window.innerHeight / 2])
|
||||
)
|
||||
)
|
||||
let center = Vec.round(this.getPagePoint(point || this.centerPoint))
|
||||
|
||||
if (
|
||||
Vec.dist(center, this.pasteInfo.center) < 2 ||
|
||||
|
@ -914,10 +925,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
type: TLDrawShapeType.Text,
|
||||
parentId: this.appState.currentPageId,
|
||||
text: result,
|
||||
point: this.getPagePoint(
|
||||
[window.innerWidth / 2, window.innerHeight / 2],
|
||||
this.currentPageId
|
||||
),
|
||||
point: this.getPagePoint(this.centerPoint, this.currentPageId),
|
||||
style: { ...this.appState.currentStyle },
|
||||
})
|
||||
|
||||
|
@ -1030,11 +1038,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* Reset the camera to the default position
|
||||
*/
|
||||
resetCamera = (): this => {
|
||||
return this.setCamera(
|
||||
Vec.round([window.innerWidth / 2, window.innerHeight / 2]),
|
||||
1,
|
||||
`reset_camera`
|
||||
)
|
||||
return this.setCamera(this.centerPoint, 1, `reset_camera`)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1066,7 +1070,7 @@ export class TLDrawState extends StateManager<Data> {
|
|||
* @param next The new zoom level.
|
||||
* @param center The point to zoom towards (defaults to screen center).
|
||||
*/
|
||||
zoomTo = (next: number, center = [window.innerWidth / 2, window.innerHeight / 2]): this => {
|
||||
zoomTo = (next: number, center = this.centerPoint): this => {
|
||||
const { zoom, point } = this.pageState.camera
|
||||
const p0 = Vec.sub(Vec.div(center, zoom), point)
|
||||
const p1 = Vec.sub(Vec.div(center, next), point)
|
||||
|
@ -1102,13 +1106,13 @@ export class TLDrawState extends StateManager<Data> {
|
|||
const bounds = Utils.getCommonBounds(Object.values(shapes).map(TLDR.getBounds))
|
||||
|
||||
const zoom = TLDR.getCameraZoom(
|
||||
window.innerWidth < window.innerHeight
|
||||
? (window.innerWidth - 128) / bounds.width
|
||||
: (window.innerHeight - 128) / bounds.height
|
||||
this.bounds.width < this.bounds.height
|
||||
? (this.bounds.width - 128) / bounds.width
|
||||
: (this.bounds.height - 128) / bounds.height
|
||||
)
|
||||
|
||||
const mx = (window.innerWidth - bounds.width * zoom) / 2 / zoom
|
||||
const my = (window.innerHeight - bounds.height * zoom) / 2 / zoom
|
||||
const mx = (this.bounds.width - bounds.width * zoom) / 2 / zoom
|
||||
const my = (this.bounds.height - bounds.height * zoom) / 2 / zoom
|
||||
|
||||
return this.setCamera(
|
||||
Vec.round(Vec.add([-bounds.minX, -bounds.minY], [mx, my])),
|
||||
|
@ -1126,13 +1130,13 @@ export class TLDrawState extends StateManager<Data> {
|
|||
const bounds = TLDR.getSelectedBounds(this.state)
|
||||
|
||||
const zoom = TLDR.getCameraZoom(
|
||||
window.innerWidth < window.innerHeight
|
||||
? (window.innerWidth - 128) / bounds.width
|
||||
: (window.innerHeight - 128) / bounds.height
|
||||
this.bounds.width < this.bounds.height
|
||||
? (this.bounds.width - 128) / bounds.width
|
||||
: (this.bounds.height - 128) / bounds.height
|
||||
)
|
||||
|
||||
const mx = (window.innerWidth - bounds.width * zoom) / 2 / zoom
|
||||
const my = (window.innerHeight - bounds.height * zoom) / 2 / zoom
|
||||
const mx = (this.bounds.width - bounds.width * zoom) / 2 / zoom
|
||||
const my = (this.bounds.height - bounds.height * zoom) / 2 / zoom
|
||||
|
||||
return this.setCamera(
|
||||
Vec.round(Vec.add([-bounds.minX, -bounds.minY], [mx, my])),
|
||||
|
@ -1153,8 +1157,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
const bounds = Utils.getCommonBounds(Object.values(shapes).map(TLDR.getBounds))
|
||||
|
||||
const { zoom } = pageState.camera
|
||||
const mx = (window.innerWidth - bounds.width * zoom) / 2 / zoom
|
||||
const my = (window.innerHeight - bounds.height * zoom) / 2 / zoom
|
||||
const mx = (this.bounds.width - bounds.width * zoom) / 2 / zoom
|
||||
const my = (this.bounds.height - bounds.height * zoom) / 2 / zoom
|
||||
|
||||
return this.setCamera(
|
||||
Vec.round(Vec.add([-bounds.minX, -bounds.minY], [mx, my])),
|
||||
|
@ -2813,4 +2817,8 @@ export class TLDrawState extends StateManager<Data> {
|
|||
onError = () => {
|
||||
// TODO
|
||||
}
|
||||
|
||||
get centerPoint() {
|
||||
return Vec.round(Utils.getBoundsCenter(this.bounds))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue