No impure getters pt6 (#2218)

follow up to #2189 

### Change Type

- [x] `patch` — Bug fix
This commit is contained in:
David Sheldrick 2023-11-14 11:57:43 +00:00 committed by GitHub
parent 25e7bf30c9
commit 6f872c796a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
61 changed files with 493 additions and 259 deletions

View file

@ -763,6 +763,11 @@ export class Editor extends EventEmitter<TLEventMap> {
darkMode?: boolean | undefined;
preserveAspectRatio: React.SVGAttributes<SVGSVGElement>['preserveAspectRatio'];
}>): Promise<SVGSVGElement | undefined>;
getViewportPageBounds(): Box2d;
getViewportPageCenter(): Vec2d;
getViewportScreenBounds(): Box2d;
getViewportScreenCenter(): Vec2d;
getZoomLevel(): number;
groupShapes(shapes: TLShape[] | TLShapeId[], groupId?: TLShapeId): this;
hasAncestor(shape: TLShape | TLShapeId | undefined, ancestorId: TLShapeId): boolean;
// @deprecated (undocumented)
@ -941,12 +946,17 @@ export class Editor extends EventEmitter<TLEventMap> {
updateShapes<T extends TLUnknownShape>(partials: (null | TLShapePartial<T> | undefined)[], historyOptions?: TLCommandHistoryOptions): this;
updateViewportScreenBounds(center?: boolean): this;
readonly user: UserPreferencesManager;
// @deprecated (undocumented)
get viewportPageBounds(): Box2d;
// @deprecated (undocumented)
get viewportPageCenter(): Vec2d;
// @deprecated (undocumented)
get viewportScreenBounds(): Box2d;
// @deprecated (undocumented)
get viewportScreenCenter(): Vec2d;
visitDescendants(parent: TLPage | TLParentId | TLShape, visitor: (id: TLShapeId) => false | void): this;
zoomIn(point?: Vec2d, animation?: TLAnimationOptions): this;
// @deprecated (undocumented)
get zoomLevel(): number;
zoomOut(point?: Vec2d, animation?: TLAnimationOptions): this;
zoomToBounds(bounds: Box2d, targetZoom?: number, animation?: TLAnimationOptions): this;

View file

@ -13275,6 +13275,165 @@
"isAbstract": false,
"name": "getSvg"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getViewportPageBounds:member(1)",
"docComment": "/**\n * The current viewport in the current page space.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getViewportPageBounds(): "
},
{
"kind": "Reference",
"text": "Box2d",
"canonicalReference": "@tldraw/editor!Box2d:class"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getViewportPageBounds"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getViewportPageCenter:member(1)",
"docComment": "/**\n * The center of the viewport in the current page space.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getViewportPageCenter(): "
},
{
"kind": "Reference",
"text": "Vec2d",
"canonicalReference": "@tldraw/editor!Vec2d:class"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getViewportPageCenter"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getViewportScreenBounds:member(1)",
"docComment": "/**\n * The bounds of the editor's viewport in screen space.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getViewportScreenBounds(): "
},
{
"kind": "Reference",
"text": "Box2d",
"canonicalReference": "@tldraw/editor!Box2d:class"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getViewportScreenBounds"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getViewportScreenCenter:member(1)",
"docComment": "/**\n * The center of the editor's viewport in screen space.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getViewportScreenCenter(): "
},
{
"kind": "Reference",
"text": "Vec2d",
"canonicalReference": "@tldraw/editor!Vec2d:class"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getViewportScreenCenter"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#getZoomLevel:member(1)",
"docComment": "/**\n * The current camera zoom level.\n *\n * @public\n */\n",
"excerptTokens": [
{
"kind": "Content",
"text": "getZoomLevel(): "
},
{
"kind": "Content",
"text": "number"
},
{
"kind": "Content",
"text": ";"
}
],
"isStatic": false,
"returnTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
},
"releaseTag": "Public",
"isProtected": false,
"overloadIndex": 1,
"parameters": [],
"isOptional": false,
"isAbstract": false,
"name": "getZoomLevel"
},
{
"kind": "Method",
"canonicalReference": "@tldraw/editor!Editor#groupShapes:member(1)",
@ -19125,7 +19284,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#viewportPageBounds:member",
"docComment": "/**\n * The current viewport in the current page space.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getViewportPageBounds` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -19156,7 +19315,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#viewportPageCenter:member",
"docComment": "/**\n * The center of the viewport in the current page space.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getViewportPageCenter` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -19187,7 +19346,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#viewportScreenBounds:member",
"docComment": "/**\n * The bounds of the editor's viewport in screen space.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getViewportScreenBounds` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -19218,7 +19377,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#viewportScreenCenter:member",
"docComment": "/**\n * The center of the editor's viewport in screen space.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getViewportScreenCenter` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",
@ -19407,7 +19566,7 @@
{
"kind": "Property",
"canonicalReference": "@tldraw/editor!Editor#zoomLevel:member",
"docComment": "/**\n * The current camera zoom level.\n *\n * @public\n */\n",
"docComment": "/**\n * @deprecated\n *\n * Use `getZoomLevel` instead.\n */\n",
"excerptTokens": [
{
"kind": "Content",

View file

@ -148,7 +148,7 @@ function GridWrapper() {
function ScribbleWrapper() {
const editor = useEditor()
const scribbles = useValue('scribbles', () => editor.getInstanceState().scribbles, [editor])
const zoomLevel = useValue('zoomLevel', () => editor.zoomLevel, [editor])
const zoomLevel = useValue('zoomLevel', () => editor.getZoomLevel(), [editor])
const { Scribble } = useEditorComponents()
if (!(Scribble && scribbles.length)) return null
@ -190,7 +190,7 @@ function ZoomBrushWrapper() {
function SnapLinesWrapper() {
const editor = useEditor()
const lines = useValue('snapLines', () => editor.snaps.lines, [editor])
const zoomLevel = useValue('zoomLevel', () => editor.zoomLevel, [editor])
const zoomLevel = useValue('zoomLevel', () => editor.getZoomLevel(), [editor])
const { SnapLine } = useEditorComponents()
if (!(SnapLine && lines.length > 0)) return null
@ -210,7 +210,7 @@ function HandlesWrapper() {
const editor = useEditor()
const { Handles } = useEditorComponents()
const zoomLevel = useValue('zoomLevel', () => editor.zoomLevel, [editor])
const zoomLevel = useValue('zoomLevel', () => editor.getZoomLevel(), [editor])
const isCoarse = useValue('coarse pointer', () => editor.getInstanceState().isCoarsePointer, [
editor,
])

View file

@ -29,8 +29,8 @@ export const GeometryDebuggingView = track(function GeometryDebuggingView({
useTick(showClosestPointOnOutline)
const zoomLevel = editor.getZoomLevel()
const {
zoomLevel,
renderingShapes,
inputs: { currentPagePoint },
} = editor

View file

@ -80,7 +80,8 @@ const Collaborator = track(function Collaborator({
CollaboratorShapeIndicator,
} = useEditorComponents()
const { viewportPageBounds, zoomLevel } = editor
const zoomLevel = editor.getZoomLevel()
const viewportPageBounds = editor.getViewportPageBounds()
const { userId, chatMessage, brush, scribbles, selectedShapeIds, userName, cursor, color } =
latestPresence

View file

@ -2208,10 +2208,17 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get zoomLevel() {
@computed getZoomLevel() {
return this.getCamera().z
}
/**
* @deprecated Use `getZoomLevel` instead.
*/
get zoomLevel() {
return this.getZoomLevel()
}
/** @internal */
private _setCamera(point: VecLike): this {
const currentCamera = this.getCamera()
@ -2264,7 +2271,7 @@ export class Editor extends EventEmitter<TLEventMap> {
setCamera(point: VecLike, animation?: TLAnimationOptions): this {
const x = Number.isFinite(point.x) ? point.x : 0
const y = Number.isFinite(point.y) ? point.y : 0
const z = Number.isFinite(point.z) ? point.z! : this.zoomLevel
const z = Number.isFinite(point.z) ? point.z! : this.getZoomLevel()
// Stop any camera animations
this.stopCameraAnimation()
@ -2275,7 +2282,7 @@ export class Editor extends EventEmitter<TLEventMap> {
}
if (animation) {
const { width, height } = this.viewportScreenBounds
const { width, height } = this.getViewportScreenBounds()
return this._animateToViewport(new Box2d(-x, -y, width / z, height / z), animation)
} else {
this._setCamera({ x, y, z })
@ -2301,9 +2308,7 @@ export class Editor extends EventEmitter<TLEventMap> {
centerOnPoint(point: VecLike, animation?: TLAnimationOptions): this {
if (!this.getInstanceState().canMoveCamera) return this
const {
viewportPageBounds: { width: pw, height: ph },
} = this
const { width: pw, height: ph } = this.getViewportPageBounds()
this.setCamera(
{ x: -(point.x - pw / 2), y: -(point.y - ph / 2), z: this.getCamera().z },
@ -2329,7 +2334,7 @@ export class Editor extends EventEmitter<TLEventMap> {
const bounds = this.getSelectionPageBounds() ?? this.currentPageBounds
if (bounds) {
this.zoomToBounds(bounds, Math.min(1, this.zoomLevel), { duration: 220 })
this.zoomToBounds(bounds, Math.min(1, this.getZoomLevel()), { duration: 220 })
}
return this
@ -2374,7 +2379,7 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
resetZoom(point = this.viewportScreenCenter, animation?: TLAnimationOptions): this {
resetZoom(point = this.getViewportScreenCenter(), animation?: TLAnimationOptions): this {
if (!this.getInstanceState().canMoveCamera) return this
const { x: cx, y: cy, z: cz } = this.getCamera()
@ -2401,7 +2406,7 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
zoomIn(point = this.viewportScreenCenter, animation?: TLAnimationOptions): this {
zoomIn(point = this.getViewportScreenCenter(), animation?: TLAnimationOptions): this {
if (!this.getInstanceState().canMoveCamera) return this
const { x: cx, y: cy, z: cz } = this.getCamera()
@ -2439,7 +2444,7 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
zoomOut(point = this.viewportScreenCenter, animation?: TLAnimationOptions): this {
zoomOut(point = this.getViewportScreenCenter(), animation?: TLAnimationOptions): this {
if (!this.getInstanceState().canMoveCamera) return this
const { x: cx, y: cy, z: cz } = this.getCamera()
@ -2486,7 +2491,7 @@ export class Editor extends EventEmitter<TLEventMap> {
const selectionPageBounds = this.getSelectionPageBounds()
if (!selectionPageBounds) return this
this.zoomToBounds(selectionPageBounds, Math.max(1, this.zoomLevel), animation)
this.zoomToBounds(selectionPageBounds, Math.max(1, this.getZoomLevel()), animation)
return this
}
@ -2505,14 +2510,16 @@ export class Editor extends EventEmitter<TLEventMap> {
if (ids.length <= 0) return this
const selectionBounds = Box2d.Common(compact(ids.map((id) => this.getShapePageBounds(id))))
const { viewportPageBounds } = this
const viewportPageBounds = this.getViewportPageBounds()
if (viewportPageBounds.h < selectionBounds.h || viewportPageBounds.w < selectionBounds.w) {
this.zoomToBounds(selectionBounds, this.getCamera().z, animation)
return this
} else {
const insetViewport = this.viewportPageBounds.clone().expandBy(-32 / this.zoomLevel)
const insetViewport = this.getViewportPageBounds()
.clone()
.expandBy(-32 / this.getZoomLevel())
let offsetX = 0
let offsetY = 0
@ -2562,7 +2569,7 @@ export class Editor extends EventEmitter<TLEventMap> {
zoomToBounds(bounds: Box2d, targetZoom?: number, animation?: TLAnimationOptions): this {
if (!this.getInstanceState().canMoveCamera) return this
const { viewportScreenBounds } = this
const viewportScreenBounds = this.getViewportScreenBounds()
const inset = Math.min(256, viewportScreenBounds.width * 0.28)
@ -2646,7 +2653,7 @@ export class Editor extends EventEmitter<TLEventMap> {
const { elapsed, easing, duration, start, end } = this._viewportAnimation
if (elapsed > duration) {
this._setCamera({ x: -end.x, y: -end.y, z: this.viewportScreenBounds.width / end.width })
this._setCamera({ x: -end.x, y: -end.y, z: this.getViewportScreenBounds().width / end.width })
cancel()
return
}
@ -2658,7 +2665,7 @@ export class Editor extends EventEmitter<TLEventMap> {
const top = start.minY + (end.minY - start.minY) * t
const right = start.maxX + (end.maxX - start.maxX) * t
this._setCamera({ x: -left, y: -top, z: this.viewportScreenBounds.width / (right - left) })
this._setCamera({ x: -left, y: -top, z: this.getViewportScreenBounds().width / (right - left) })
}
/** @internal */
@ -2666,8 +2673,8 @@ export class Editor extends EventEmitter<TLEventMap> {
const { duration = 0, easing = EASINGS.easeInOutCubic } = opts
const {
user: { animationSpeed },
viewportPageBounds,
} = this
const viewportPageBounds = this.getViewportPageBounds()
// If we have an existing animation, then stop it; also stop following any user
this.stopCameraAnimation()
@ -2680,7 +2687,7 @@ export class Editor extends EventEmitter<TLEventMap> {
return this._setCamera({
x: -targetViewportPage.x,
y: -targetViewportPage.y,
z: this.viewportScreenBounds.width / targetViewportPage.width,
z: this.getViewportScreenBounds().width / targetViewportPage.width,
})
}
@ -2811,7 +2818,7 @@ export class Editor extends EventEmitter<TLEventMap> {
animateToShape(shapeId: TLShapeId, opts: TLAnimationOptions = DEFAULT_ANIMATION_OPTIONS): this {
if (!this.getInstanceState().canMoveCamera) return this
const activeArea = this.viewportScreenBounds.clone().expandBy(-32)
const activeArea = this.getViewportScreenBounds().clone().expandBy(-32)
const viewportAspectRatio = activeArea.width / activeArea.height
const shapePageBounds = this.getShapePageBounds(shapeId)
@ -2869,7 +2876,7 @@ export class Editor extends EventEmitter<TLEventMap> {
Math.max(rect.width, 1),
Math.max(rect.height, 1)
)
const boundsAreEqual = screenBounds.equals(this.viewportScreenBounds)
const boundsAreEqual = screenBounds.equals(this.getViewportScreenBounds())
const { _willSetInitialBounds } = this
@ -2886,7 +2893,7 @@ export class Editor extends EventEmitter<TLEventMap> {
} else {
if (center && !this.getInstanceState().followingUserId) {
// Get the page center before the change, make the change, and restore it
const before = this.viewportPageCenter
const before = this.getViewportPageCenter()
this.updateInstanceState(
{ screenBounds: screenBounds.toJson() },
{ squashing: true, ephemeral: true }
@ -2913,18 +2920,32 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get viewportScreenBounds() {
@computed getViewportScreenBounds() {
const { x, y, w, h } = this.getInstanceState().screenBounds
return new Box2d(x, y, w, h)
}
/**
* @deprecated Use `getViewportScreenBounds` instead.
*/
get viewportScreenBounds() {
return this.getViewportScreenBounds()
}
/**
* The center of the editor's viewport in screen space.
*
* @public
*/
@computed get viewportScreenCenter() {
return this.viewportScreenBounds.center
@computed getViewportScreenCenter() {
return this.getViewportScreenBounds().center
}
/**
* @deprecated Use `getViewportScreenCenter` instead.
*/
get viewportScreenCenter() {
return this.getViewportScreenCenter()
}
/**
@ -2932,19 +2953,33 @@ export class Editor extends EventEmitter<TLEventMap> {
*
* @public
*/
@computed get viewportPageBounds() {
const { w, h } = this.viewportScreenBounds
@computed getViewportPageBounds() {
const { w, h } = this.getViewportScreenBounds()
const { x: cx, y: cy, z: cz } = this.getCamera()
return new Box2d(-cx, -cy, w / cz, h / cz)
}
/**
* @deprecated Use `getViewportPageBounds` instead.
*/
get viewportPageBounds() {
return this.getViewportPageBounds()
}
/**
* The center of the viewport in the current page space.
*
* @public
*/
@computed get viewportPageCenter() {
return this.viewportPageBounds.center
@computed getViewportPageCenter() {
return this.getViewportPageBounds().center
}
/**
* @deprecated Use `getViewportPageCenter` instead.
*/
get viewportPageCenter() {
return this.getViewportPageCenter()
}
/**
@ -3053,7 +3088,7 @@ export class Editor extends EventEmitter<TLEventMap> {
}
// Get the bounds of the follower (me) and the leader (them)
const { center, width, height } = this.viewportPageBounds
const { center, width, height } = this.getViewportPageBounds()
const leaderScreen = Box2d.From(leaderPresence.screenBounds)
const leaderWidth = leaderScreen.width / leaderPresence.camera.z
const leaderHeight = leaderScreen.height / leaderPresence.camera.z
@ -3075,8 +3110,8 @@ export class Editor extends EventEmitter<TLEventMap> {
: height / desiredHeight
const targetZoom = clamp(this.getCamera().z * ratio, MIN_ZOOM, MAX_ZOOM)
const targetWidth = this.viewportScreenBounds.w / targetZoom
const targetHeight = this.viewportScreenBounds.h / targetZoom
const targetWidth = this.getViewportScreenBounds().w / targetZoom
const targetHeight = this.getViewportScreenBounds().h / targetZoom
// Figure out where to move the camera
const displacement = leaderCenter.sub(center)
@ -3349,13 +3384,13 @@ export class Editor extends EventEmitter<TLEventMap> {
* @internal
*/
updateRenderingBounds(): this {
const { viewportPageBounds } = this
const viewportPageBounds = this.getViewportPageBounds()
if (viewportPageBounds.equals(this._renderingBounds.__unsafe__getWithoutCapture())) return this
this._renderingBounds.set(viewportPageBounds.clone())
if (Number.isFinite(this.renderingBoundsMargin)) {
this._renderingBoundsExpanded.set(
viewportPageBounds.clone().expandBy(this.renderingBoundsMargin / this.zoomLevel)
viewportPageBounds.clone().expandBy(this.renderingBoundsMargin / this.getZoomLevel())
)
} else {
this._renderingBoundsExpanded.set(viewportPageBounds)
@ -4425,7 +4460,8 @@ export class Editor extends EventEmitter<TLEventMap> {
filter?: (shape: TLShape) => boolean
}
): TLShape | undefined {
const { viewportPageBounds, zoomLevel } = this
const zoomLevel = this.getZoomLevel()
const viewportPageBounds = this.getViewportPageBounds()
const {
filter,
margin = 0,
@ -5479,7 +5515,7 @@ export class Editor extends EventEmitter<TLEventMap> {
// contained in the current viewport. If not, then animate the camera to be centered on the
// new shapes.
const selectionPageBounds = this.getSelectionPageBounds()
const { viewportPageBounds } = this
const viewportPageBounds = this.getViewportPageBounds()
if (selectionPageBounds && !viewportPageBounds.contains(selectionPageBounds)) {
this.centerOnPoint(selectionPageBounds.center, {
duration: ANIMATION_MEDIUM_MS,
@ -7988,7 +8024,7 @@ export class Editor extends EventEmitter<TLEventMap> {
if (!isPageId(pasteParentId)) {
const parent = this.getShape(pasteParentId)
if (parent) {
if (!this.viewportPageBounds.includes(this.getShapePageBounds(parent)!)) {
if (!this.getViewportPageBounds().includes(this.getShapePageBounds(parent)!)) {
pasteParentId = currentPageId
} else {
if (rootShapeIds.length === 1) {
@ -8189,7 +8225,7 @@ export class Editor extends EventEmitter<TLEventMap> {
this.getShapeGeometry(shape).bounds.center
)
} else {
const { viewportPageBounds } = this
const viewportPageBounds = this.getViewportPageBounds()
if (preservePosition || viewportPageBounds.includes(Box2d.From(bounds))) {
// Otherwise, put shapes where they used to be
point = bounds.center
@ -8872,7 +8908,7 @@ export class Editor extends EventEmitter<TLEventMap> {
inputs.isPointing &&
originPagePoint.dist(currentPagePoint) >
(this.getInstanceState().isCoarsePointer ? COARSE_DRAG_DISTANCE : DRAG_DISTANCE) /
this.zoomLevel
this.getZoomLevel()
) {
inputs.isDragging = true
}
@ -8960,7 +8996,7 @@ export class Editor extends EventEmitter<TLEventMap> {
inputs.isPointing &&
originPagePoint.dist(currentPagePoint) >
(this.getInstanceState().isCoarsePointer ? COARSE_DRAG_DISTANCE : DRAG_DISTANCE) /
this.zoomLevel
this.getZoomLevel()
) {
inputs.isDragging = true
}

View file

@ -242,7 +242,7 @@ export class SnapManager {
}
@computed get snapThreshold() {
return 8 / this.editor.zoomLevel
return 8 / this.editor.getZoomLevel()
}
// TODO: make this an incremental derivation

View file

@ -6,7 +6,7 @@ import { getPerfectDashProps } from '../shared/getPerfectDashProps'
export function DashedOutlineBox({ bounds, className }: { bounds: Box2d; className: string }) {
const editor = useEditor()
const zoomLevel = useValue('zoom level', () => editor.zoomLevel, [editor])
const zoomLevel = useValue('zoom level', () => editor.getZoomLevel(), [editor])
return (
<g className={className} pointerEvents="none" strokeLinecap="round" strokeLinejoin="round">

View file

@ -225,7 +225,7 @@ export function useDocumentEvents() {
// touchstart event in that case.
if (
touchXPosition - touchXRadius < 10 ||
touchXPosition + touchXRadius > editor.viewportScreenBounds.width - 10
touchXPosition + touchXRadius > editor.getViewportScreenBounds().width - 10
) {
if ((e.target as HTMLElement)?.tagName === 'BUTTON') {
// Force a click before bailing

View file

@ -155,12 +155,12 @@ export function useGestureEvents(ref: React.RefObject<HTMLDivElement>) {
initPointBetweenFingers.x = origin[0]
initPointBetweenFingers.y = origin[1]
initDistanceBetweenFingers = da[0]
initZoom = editor.zoomLevel
initZoom = editor.getZoomLevel()
editor.dispatch({
type: 'pinch',
name: 'pinch_start',
point: { x: origin[0], y: origin[1], z: editor.zoomLevel },
point: { x: origin[0], y: origin[1], z: editor.getZoomLevel() },
delta: { x: 0, y: 0 },
shiftKey: event.shiftKey,
altKey: event.altKey,
@ -302,9 +302,9 @@ export function useGestureEvents(ref: React.RefObject<HTMLDivElement>) {
target: ref,
eventOptions: { passive: false },
pinch: {
from: () => [editor.zoomLevel, 0], // Return the camera z to use when pinch starts
from: () => [editor.getZoomLevel(), 0], // Return the camera z to use when pinch starts
scaleBounds: () => {
return { from: editor.zoomLevel, max: 8, min: 0.05 }
return { from: editor.getZoomLevel(), max: 8, min: 0.05 }
},
},
})

View file

@ -15,9 +15,9 @@ export function useZoomCss() {
const scheduler = new EffectScheduler('useZoomCss', () => {
const numShapes = editor.currentPageShapeIds.size
if (numShapes < 300) {
setScale(editor.zoomLevel)
setScale(editor.getZoomLevel())
} else {
setScaleDebounced(editor.zoomLevel)
setScaleDebounced(editor.getZoomLevel())
}
})

View file

@ -54,7 +54,7 @@ export const TldrawSelectionForeground: TLSelectionForegroundComponent = track(
if (!bounds) return null
bounds = bounds.clone().expandBy(expandOutlineBy).zeroFix()
const zoom = editor.zoomLevel
const zoom = editor.getZoomLevel()
const isChangingStyle = editor.getInstanceState().isChangingStyle
const width = bounds.width
@ -501,7 +501,7 @@ export const MobileRotateHandle = function RotateHandle({
const events = useSelectionEvents('mobile_rotate')
const editor = useEditor()
const zoom = useValue('zoom level', () => editor.zoomLevel, [editor])
const zoom = useValue('zoom level', () => editor.getZoomLevel(), [editor])
const bgRadius = Math.max(14 * (1 / zoom), 20 / Math.max(1, zoom))
return (

View file

@ -165,7 +165,8 @@ export function registerDefaultExternalContentHandlers(
// svg text
editor.registerExternalContentHandler('svg-text', async ({ point, text }) => {
const position =
point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.viewportPageCenter)
point ??
(editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.getViewportPageCenter())
const svg = new DOMParser().parseFromString(text, 'image/svg+xml').querySelector('svg')
if (!svg) {
@ -197,7 +198,8 @@ export function registerDefaultExternalContentHandlers(
// embeds
editor.registerExternalContentHandler('embed', ({ point, url, embed }) => {
const position =
point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.viewportPageCenter)
point ??
(editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.getViewportPageCenter())
const { width, height } = embed
@ -221,7 +223,8 @@ export function registerDefaultExternalContentHandlers(
// files
editor.registerExternalContentHandler('files', async ({ point, files }) => {
const position =
point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.viewportPageCenter)
point ??
(editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.getViewportPageCenter())
const pagePoint = new Vec2d(position.x, position.y)
@ -272,7 +275,8 @@ export function registerDefaultExternalContentHandlers(
// text
editor.registerExternalContentHandler('text', async ({ point, text }) => {
const p =
point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.viewportPageCenter)
point ??
(editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.getViewportPageCenter())
const defaultProps = editor.getShapeUtil<TLTextShape>('text').getDefaultProps()
@ -301,8 +305,8 @@ export function registerDefaultExternalContentHandlers(
})
const minWidth = Math.min(
isMultiLine ? editor.viewportPageBounds.width * 0.9 : 920,
Math.max(200, editor.viewportPageBounds.width * 0.9)
isMultiLine ? editor.getViewportPageBounds().width * 0.9 : 920,
Math.max(200, editor.getViewportPageBounds().width * 0.9)
)
if (rawSize.w > minWidth) {
@ -323,8 +327,8 @@ export function registerDefaultExternalContentHandlers(
autoSize = true
}
if (p.y - h / 2 < editor.viewportPageBounds.minY + 40) {
p.y = editor.viewportPageBounds.minY + 40 + h / 2
if (p.y - h / 2 < editor.getViewportPageBounds().minY + 40) {
p.y = editor.getViewportPageBounds().minY + 40 + h / 2
}
editor.createShapes<TLTextShape>([
@ -359,7 +363,8 @@ export function registerDefaultExternalContentHandlers(
}
const position =
point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.viewportPageCenter)
point ??
(editor.inputs.shiftKey ? editor.inputs.currentPagePoint : editor.getViewportPageCenter())
const assetId: TLAssetId = AssetRecordType.createId(getHashForString(url))
const shape = createEmptyBookmarkShape(editor, url, position)
@ -475,7 +480,7 @@ export async function createShapesForAssets(
function centerSelectionAroundPoint(editor: Editor, position: VecLike) {
// Re-position shapes so that the center of the group is at the provided point
const { viewportPageBounds } = editor
const viewportPageBounds = editor.getViewportPageBounds()
let selectionPageBounds = editor.getSelectionPageBounds()
if (selectionPageBounds) {

View file

@ -288,7 +288,7 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
precise =
Vec2d.Dist(pointInTargetSpace, targetBounds.center) >
Math.max(4, Math.min(Math.min(targetBounds.width, targetBounds.height) * 0.15, 16)) /
this.editor.zoomLevel
this.editor.getZoomLevel()
}
if (!isPrecise) {

View file

@ -67,7 +67,7 @@ export class BookmarkShapeUtil extends BaseBoxShapeUtil<TLBookmarkShape> {
) : (
<div className="tl-bookmark__placeholder" />
)}
<HyperlinkButton url={shape.props.url} zoomLevel={this.editor.zoomLevel} />
<HyperlinkButton url={shape.props.url} zoomLevel={this.editor.getZoomLevel()} />
</div>
<div className="tl-bookmark__copy_container">
{asset?.props.title && (

View file

@ -87,7 +87,7 @@ export class Drawing extends StateNode {
if (inputs.isPen) {
if (
Vec2d.Dist(inputs.currentPagePoint, this.lastRecordedPoint) >=
1 / this.editor.zoomLevel
1 / this.editor.getZoomLevel()
) {
this.lastRecordedPoint = inputs.currentPagePoint.clone()
this.mergeNextPoint = false
@ -474,7 +474,7 @@ export class Drawing extends StateNode {
if (shouldSnap) {
if (newSegments.length > 2) {
let nearestPoint: Vec2dModel | undefined = undefined
let minDistance = 8 / this.editor.zoomLevel
let minDistance = 8 / this.editor.getZoomLevel()
// Don't try to snap to the last two segments
for (let i = 0, n = segments.length - 2; i < n; i++) {

View file

@ -540,7 +540,7 @@ export class GeoShapeUtil extends BaseBoxShapeUtil<TLGeoShape> {
bounds={props.geo === 'cloud' ? this.getGeometry(shape).bounds : undefined}
/>
{shape.props.url && (
<HyperlinkButton url={shape.props.url} zoomLevel={this.editor.zoomLevel} />
<HyperlinkButton url={shape.props.url} zoomLevel={this.editor.getZoomLevel()} />
)}
</HTMLContainer>
</>

View file

@ -155,7 +155,7 @@ export class ImageShapeUtil extends BaseBoxShapeUtil<TLImageShape> {
)}
</div>
{'url' in shape.props && shape.props.url && (
<HyperlinkButton url={shape.props.url} zoomLevel={this.editor.zoomLevel} />
<HyperlinkButton url={shape.props.url} zoomLevel={this.editor.getZoomLevel()} />
)}
</HTMLContainer>
</>

View file

@ -94,7 +94,7 @@ export class NoteShapeUtil extends ShapeUtil<TLNoteShape> {
</div>
</div>
{'url' in shape.props && shape.props.url && (
<HyperlinkButton url={shape.props.url} zoomLevel={this.editor.zoomLevel} />
<HyperlinkButton url={shape.props.url} zoomLevel={this.editor.getZoomLevel()} />
)}
</>
)

View file

@ -40,10 +40,10 @@ export const ShapeFill = React.memo(function ShapeFill({ theme, d, color, fill }
const PatternFill = function PatternFill({ d, color, theme }: ShapeFillProps) {
const editor = useEditor()
const zoomLevel = useValue('zoomLevel', () => editor.zoomLevel, [editor])
const zoomLevel = useValue('zoomLevel', () => editor.getZoomLevel(), [editor])
const intZoom = Math.ceil(zoomLevel)
const teenyTiny = editor.zoomLevel <= 0.18
const teenyTiny = editor.getZoomLevel() <= 0.18
return (
<>

View file

@ -2,5 +2,5 @@ import { useEditor, useValue } from '@tldraw/editor'
export function useForceSolid() {
const editor = useEditor()
return useValue('zoom', () => editor.zoomLevel < 0.35, [editor])
return useValue('zoom', () => editor.getZoomLevel() < 0.35, [editor])
}

View file

@ -71,7 +71,7 @@ const TLVideoUtilComponent = track(function TLVideoUtilComponent(props: {
}) {
const { shape, videoUtil } = props
const showControls =
videoUtil.editor.getShapeGeometry(shape).bounds.w * videoUtil.editor.zoomLevel >= 110
videoUtil.editor.getShapeGeometry(shape).bounds.w * videoUtil.editor.getZoomLevel() >= 110
const asset = shape.props.assetId ? videoUtil.editor.getAsset(shape.props.assetId) : null
const { time, playing } = shape.props
const isEditing = useIsEditing(shape.id)
@ -208,7 +208,7 @@ const TLVideoUtilComponent = track(function TLVideoUtilComponent(props: {
</div>
</HTMLContainer>
{'url' in shape.props && shape.props.url && (
<HyperlinkButton url={shape.props.url} zoomLevel={videoUtil.editor.zoomLevel} />
<HyperlinkButton url={shape.props.url} zoomLevel={videoUtil.editor.getZoomLevel()} />
)}
</>
)

View file

@ -79,8 +79,8 @@ export class Erasing extends StateNode {
update() {
const erasingShapeIds = this.editor.getErasingShapeIds()
const zoomLevel = this.editor.getZoomLevel()
const {
zoomLevel,
currentPageShapes: currentPageShapes,
inputs: { currentPagePoint, previousPagePoint },
} = this.editor

View file

@ -11,10 +11,10 @@ export class Pointing extends StateNode {
static override id = 'pointing'
override onEnter = () => {
const zoomLevel = this.editor.getZoomLevel()
const {
inputs: { currentPagePoint },
currentPageShapesSorted: sortedShapesOnCurrentPage,
zoomLevel,
} = this.editor
const erasing = new Set<TLShapeId>()

View file

@ -25,8 +25,8 @@ export class HandTool extends StateNode {
override onQuadrupleClick: TLClickEvent = (info) => {
if (info.phase === 'settle') {
const zoomLevel = this.editor.getZoomLevel()
const {
zoomLevel,
inputs: { currentScreenPoint },
} = this.editor

View file

@ -93,8 +93,8 @@ export class Brushing extends StateNode {
}
private hitTestShapes() {
const zoomLevel = this.editor.getZoomLevel()
const {
zoomLevel,
currentPageId,
currentPageShapes: currentPageShapes,
inputs: { originPagePoint, currentPagePoint, shiftKey, ctrlKey },

View file

@ -176,7 +176,7 @@ export class Idle extends StateNode {
? hoveredShape
: this.editor.getSelectedShapeAtPoint(this.editor.inputs.currentPagePoint) ??
this.editor.getShapeAtPoint(this.editor.inputs.currentPagePoint, {
margin: HIT_TEST_MARGIN / this.editor.zoomLevel,
margin: HIT_TEST_MARGIN / this.editor.getZoomLevel(),
hitInside: false,
})
@ -329,7 +329,7 @@ export class Idle extends StateNode {
hoveredShape && !this.editor.isShapeOfType<TLGroupShape>(hoveredShape, 'group')
? hoveredShape
: this.editor.getShapeAtPoint(this.editor.inputs.currentPagePoint, {
margin: HIT_TEST_MARGIN / this.editor.zoomLevel,
margin: HIT_TEST_MARGIN / this.editor.getZoomLevel(),
hitInside: false,
hitLabels: true,
hitFrameInside: false,

View file

@ -62,8 +62,8 @@ export class PointingShape extends StateNode {
override onPointerUp: TLEventHandlers['onPointerUp'] = (info) => {
const selectedShapeIds = this.editor.getSelectedShapeIds()
const focusedGroupId = this.editor.getFocusedGroupId()
const zoomLevel = this.editor.getZoomLevel()
const {
zoomLevel,
inputs: { currentPagePoint, shiftKey },
} = this.editor

View file

@ -85,8 +85,8 @@ export class ScribbleBrushing extends StateNode {
}
private updateScribbleSelection(addPoint: boolean) {
const zoomLevel = this.editor.getZoomLevel()
const {
zoomLevel,
currentPageShapes: currentPageShapes,
inputs: { shiftKey, originPagePoint, previousPagePoint, currentPagePoint },
} = this.editor

View file

@ -43,7 +43,7 @@ export class ZoomBrushing extends StateNode {
private complete() {
const { zoomBrush } = this
const threshold = 8 / this.editor.zoomLevel
const threshold = 8 / this.editor.getZoomLevel()
// If the selected area is small then treat it as a click
if (zoomBrush.width < threshold && zoomBrush.height < threshold) {
const point = this.editor.inputs.currentScreenPoint
@ -53,7 +53,7 @@ export class ZoomBrushing extends StateNode {
this.editor.zoomIn(point, { duration: 220 })
}
} else {
const zoomLevel = this.editor.inputs.altKey ? this.editor.zoomLevel / 2 : undefined
const zoomLevel = this.editor.inputs.altKey ? this.editor.getZoomLevel() / 2 : undefined
this.editor.zoomToBounds(zoomBrush, zoomLevel, { duration: 220 })
}

View file

@ -1,8 +1,8 @@
import { Editor, HIT_TEST_MARGIN, TLShape } from '@tldraw/editor'
export function getHitShapeOnCanvasPointerDown(editor: Editor): TLShape | undefined {
const zoomLevel = editor.getZoomLevel()
const {
zoomLevel,
inputs: { currentPagePoint },
} = editor

View file

@ -6,7 +6,7 @@ export function selectOnCanvasPointerUp(editor: Editor) {
const hitShape = editor.getShapeAtPoint(currentPagePoint, {
hitInside: false,
margin: HIT_TEST_MARGIN / editor.zoomLevel,
margin: HIT_TEST_MARGIN / editor.getZoomLevel(),
hitLabels: true,
renderingOnly: true,
filter: (shape) => !shape.isLocked,

View file

@ -5,7 +5,7 @@ export function updateHoveredId(editor: Editor) {
const hitShape = editor.getShapeAtPoint(editor.inputs.currentPagePoint, {
hitInside: false,
hitLabels: false,
margin: HIT_TEST_MARGIN / editor.zoomLevel,
margin: HIT_TEST_MARGIN / editor.getZoomLevel(),
renderingOnly: true,
})

View file

@ -108,7 +108,7 @@ export const EmbedDialog = track(function EmbedDialog({ onClose }: TLUiDialogPro
editor.putExternalContent({
type: 'embed',
url,
point: editor.viewportPageCenter,
point: editor.getViewportPageCenter(),
embed: embedInfoForUrl.definition,
})

View file

@ -37,8 +37,8 @@ export const HTMLCanvas = track(function HTMLCanvas() {
return (
<canvas
ref={rCanvas}
width={editor.viewportScreenBounds.width}
height={editor.viewportScreenBounds.height}
width={editor.getViewportScreenBounds().width}
height={editor.getViewportScreenBounds().height}
style={{ width: '100%', height: '100%' }}
/>
)

View file

@ -64,7 +64,7 @@ export function Minimap({ shapeFill, selectFill, viewportFill }: MinimapProps) {
const clampedPoint = minimap.minimapScreenPointToPagePoint(e.clientX, e.clientY, false, true)
minimap.originPagePoint.setTo(clampedPoint)
minimap.originPageCenter.setTo(editor.viewportPageBounds.center)
minimap.originPageCenter.setTo(editor.getViewportPageBounds().center)
editor.centerOnPoint(point, { duration: ANIMATION_MEDIUM_MS })
},
@ -85,7 +85,7 @@ export function Minimap({ shapeFill, selectFill, viewportFill }: MinimapProps) {
const clampedPoint = minimap.minimapScreenPointToPagePoint(e.clientX, e.clientY, false, true)
const _vpPageBounds = editor.viewportPageBounds
const _vpPageBounds = editor.getViewportPageBounds()
minimap.isInViewport = _vpPageBounds.containsPoint(clampedPoint)
@ -189,9 +189,9 @@ export function Minimap({ shapeFill, selectFill, viewportFill }: MinimapProps) {
() => {
const {
currentPageShapeIds: shapeIdsOnCurrentPage,
viewportPageBounds,
currentPageBounds: commonBoundsOfAllShapesOnCurrentPage,
} = editor
const viewportPageBounds = editor.getViewportPageBounds()
const _dpr = devicePixelRatio.get() // dereference

View file

@ -118,7 +118,7 @@ export class MinimapManager {
clampToBounds = false
) => {
const { editor } = this
const { viewportPageBounds } = editor
const viewportPageBounds = editor.getViewportPageBounds()
let { x: px, y: py } = this.getPagePoint(x, y)
@ -179,9 +179,8 @@ export class MinimapManager {
this
const { width: cw, height: ch } = canvasScreenBounds
const selectedShapeIds = this.editor.getSelectedShapeIds()
const { viewportPageBounds } = editor
const selectedShapeIds = editor.getSelectedShapeIds()
const viewportPageBounds = editor.getViewportPageBounds()
if (!cvs || !pageBounds) {
return

View file

@ -11,13 +11,13 @@ export const ZoomMenu = track(function ZoomMenu() {
const msg = useTranslation()
const breakpoint = useBreakpoint()
const zoom = editor.zoomLevel
const zoom = editor.getZoomLevel()
const hasShapes = editor.currentPageShapeIds.size > 0
const hasSelected = editor.getSelectedShapeIds().length > 0
const isZoomedTo100 = editor.zoomLevel === 1
const isZoomedTo100 = editor.getZoomLevel() === 1
const handleDoubleClick = React.useCallback(() => {
editor.resetZoom(editor.viewportScreenCenter, { duration: ANIMATION_MEDIUM_MS })
editor.resetZoom(editor.getViewportScreenCenter(), { duration: ANIMATION_MEDIUM_MS })
}, [editor])
return (

View file

@ -345,7 +345,7 @@ export async function pasteExcalidrawContent(editor: Editor, clipboard: any, poi
const rootShapes = compact(rootShapeIds.map((id) => editor.getShape(id)))
const bounds = Box2d.Common(rootShapes.map((s) => editor.getShapePageBounds(s)!))
const viewPortCenter = editor.viewportPageBounds.center
const viewPortCenter = editor.getViewportPageBounds().center
editor.updateShapes(
rootShapes.map((s) => {
const delta = {

View file

@ -409,8 +409,8 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
y: 0,
}
: {
x: 16 / editor.zoomLevel,
y: 16 / editor.zoomLevel,
x: 16 / editor.getZoomLevel(),
y: 16 / editor.getZoomLevel(),
}
editor.mark('duplicate shapes')
editor.duplicateShapes(ids, offset)
@ -869,7 +869,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('zoom-in', { source })
editor.zoomIn(editor.viewportScreenCenter, { duration: ANIMATION_MEDIUM_MS })
editor.zoomIn(editor.getViewportScreenCenter(), { duration: ANIMATION_MEDIUM_MS })
},
},
{
@ -879,7 +879,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('zoom-out', { source })
editor.zoomOut(editor.viewportScreenCenter, { duration: ANIMATION_MEDIUM_MS })
editor.zoomOut(editor.getViewportScreenCenter(), { duration: ANIMATION_MEDIUM_MS })
},
},
{
@ -890,7 +890,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
readonlyOk: true,
onSelect(source) {
trackEvent('reset-zoom', { source })
editor.resetZoom(editor.viewportScreenCenter, { duration: ANIMATION_MEDIUM_MS })
editor.resetZoom(editor.getViewportScreenCenter(), { duration: ANIMATION_MEDIUM_MS })
},
},
{

View file

@ -52,7 +52,7 @@ export const ActionsMenuSchemaProvider = ({
const allowUngroup = useAllowUngroup()
const showEditLink = useHasLinkShapeSelected()
const breakpoint = useBreakpoint()
const isZoomedTo100 = useValue('zoom is 1', () => editor.zoomLevel === 1, [editor])
const isZoomedTo100 = useValue('zoom is 1', () => editor.getZoomLevel() === 1, [editor])
const actionTLUiMenuSchema = useMemo<TLUiMenuSchema>(() => {
const results = [

View file

@ -18,7 +18,7 @@ export function BreakPointProvider({
'breakpoint',
() => {
// This will recompute the viewport screen bounds changes...
const { width } = editor.viewportScreenBounds
const { width } = editor.getViewportScreenBounds()
const maxBreakpoint = forceMobile ? 3 : PORTRAIT_BREAKPOINTS.length - 1

View file

@ -17,7 +17,7 @@ export function useInsertMedia() {
await editor.putExternalContent({
type: 'files',
files: Array.from(fileList),
point: editor.viewportPageBounds.center,
point: editor.getViewportPageBounds().center,
ignoreParent: false,
})
input.value = ''

View file

@ -79,7 +79,7 @@ export function TLUiMenuSchemaProvider({ overrides, children }: TLUiMenuSchemaPr
const allowUngroup = useAllowUngroup()
const canUndo = useCanUndo()
const canRedo = useCanRedo()
const isZoomedTo100 = useValue('isZoomedTo100', () => editor.zoomLevel === 1, [editor])
const isZoomedTo100 = useValue('isZoomedTo100', () => editor.getZoomLevel() === 1, [editor])
const oneEmbedSelected = useValue(
'oneEmbedSelected',

View file

@ -19,55 +19,55 @@ jest.useFakeTimers()
describe(HandTool, () => {
it('Double taps to zoom in', () => {
editor.setCurrentTool('hand')
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
editor.click()
editor.click() // double click!
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).not.toBe(1) // animating
expect(editor.getZoomLevel()).not.toBe(1) // animating
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).toBe(2) // all done
expect(editor.getZoomLevel()).toBe(2) // all done
})
it('Triple taps to zoom out', () => {
editor.setCurrentTool('hand')
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
editor.click()
editor.click()
editor.click() // triple click!
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).not.toBe(1) // animating
expect(editor.getZoomLevel()).not.toBe(1) // animating
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).toBe(0.5) // all done
expect(editor.getZoomLevel()).toBe(0.5) // all done
})
it('Quadruple taps to reset zoom', () => {
editor.setCurrentTool('hand')
editor.zoomIn() // zoom to 2
expect(editor.zoomLevel).toBe(2)
expect(editor.getZoomLevel()).toBe(2)
editor.click()
editor.click()
editor.click()
editor.click() // quad click!
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).not.toBe(2) // animating
expect(editor.getZoomLevel()).not.toBe(2) // animating
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).toBe(1) // all done
expect(editor.getZoomLevel()).toBe(1) // all done
})
it('Quadruple taps from zoom=1 to zoom to fit', () => {
editor.setCurrentTool('hand')
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
editor.createShapes(createDefaultShapes()) // makes some shapes
editor.click()
editor.click()
editor.click()
editor.click() // quad click!
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).not.toBe(1) // animating
expect(editor.getZoomLevel()).not.toBe(1) // animating
jest.advanceTimersByTime(300)
const z = editor.zoomLevel
const z = editor.getZoomLevel()
editor.zoomToFit() // call zoom to fit manually to compare
expect(editor.zoomLevel).toBe(z) // zoom should not have changed
expect(editor.getZoomLevel()).toBe(z) // zoom should not have changed
})
})

View file

@ -39,24 +39,24 @@ describe('TLSelectTool.Zooming', () => {
it('Correctly zooms in when clicking', () => {
editor.keyDown('z')
expect(editor.zoomLevel).toBe(1)
expect(editor.viewportPageBounds).toMatchObject({ x: -0, y: -0, w: 1080, h: 720 })
expect(editor.viewportPageCenter).toMatchObject({ x: 540, y: 360 })
expect(editor.getZoomLevel()).toBe(1)
expect(editor.getViewportPageBounds()).toMatchObject({ x: -0, y: -0, w: 1080, h: 720 })
expect(editor.getViewportPageCenter()).toMatchObject({ x: 540, y: 360 })
editor.click()
editor.expectToBeIn('zoom.idle')
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).toBe(2)
expect(editor.getZoomLevel()).toBe(2)
})
it('Correctly zooms out when clicking while pressing Alt', () => {
editor.keyDown('z')
editor.keyDown('Alt')
expect(editor.zoomLevel).toBe(1)
expect(editor.viewportPageBounds).toMatchObject({ x: -0, y: -0, w: 1080, h: 720 })
expect(editor.viewportPageCenter).toMatchObject({ x: 540, y: 360 })
expect(editor.getZoomLevel()).toBe(1)
expect(editor.getViewportPageBounds()).toMatchObject({ x: -0, y: -0, w: 1080, h: 720 })
expect(editor.getViewportPageCenter()).toMatchObject({ x: 540, y: 360 })
editor.click()
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).toBe(0.5)
expect(editor.getZoomLevel()).toBe(0.5)
})
it('Cancels while pointing', () => {
@ -67,7 +67,7 @@ describe('TLSelectTool.Zooming', () => {
editor.cancel()
editor.expectToBeIn('zoom.idle')
editor.pointerUp()
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
})
it('Cancels while brushing', () => {
@ -80,7 +80,7 @@ describe('TLSelectTool.Zooming', () => {
editor.cancel()
editor.expectToBeIn('zoom.idle')
editor.pointerUp()
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
})
it('Interrupts while pointing', () => {
@ -91,7 +91,7 @@ describe('TLSelectTool.Zooming', () => {
editor.interrupt()
editor.expectToBeIn('select.idle')
editor.pointerUp()
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
})
it('Interrupts while brushing', () => {
@ -104,16 +104,16 @@ describe('TLSelectTool.Zooming', () => {
editor.interrupt()
editor.expectToBeIn('select.idle')
editor.pointerUp()
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
})
it('When the dragged area is small it zooms in instead of zooming to the area', () => {
const originalCenter = { x: 540, y: 360 }
const originalPageBounds = { x: -0, y: -0, w: 1080, h: 720 }
const change = 6
expect(editor.zoomLevel).toBe(1)
expect(editor.viewportPageBounds).toMatchObject(originalPageBounds)
expect(editor.viewportPageCenter).toMatchObject(originalCenter)
expect(editor.getZoomLevel()).toBe(1)
expect(editor.getViewportPageBounds()).toMatchObject(originalPageBounds)
expect(editor.getViewportPageCenter()).toMatchObject(originalCenter)
editor.keyDown('z')
editor.expectToBeIn('zoom.idle')
editor.pointerDown(0, 0)
@ -123,14 +123,14 @@ describe('TLSelectTool.Zooming', () => {
editor.pointerUp(change, change)
editor.expectToBeIn('zoom.idle')
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).toBe(2)
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getZoomLevel()).toBe(2)
expect(editor.getViewportPageBounds()).toMatchObject({
x: change / 2,
y: change / 2,
w: originalPageBounds.w / 2,
h: originalPageBounds.h / 2,
})
expect(editor.viewportPageCenter).toMatchObject({
expect(editor.getViewportPageCenter()).toMatchObject({
x: (originalCenter.x + change) / 2,
y: (originalCenter.y + change) / 2,
})
@ -142,9 +142,9 @@ describe('TLSelectTool.Zooming', () => {
const newBoundsX = 100
const newBoundsY = 200
editor.expectToBeIn('select.idle')
expect(editor.zoomLevel).toBe(1)
expect(editor.viewportPageBounds).toMatchObject({ x: -0, y: -0, w: 1080, h: 720 })
expect(editor.viewportPageCenter).toMatchObject({ x: 540, y: 360 })
expect(editor.getZoomLevel()).toBe(1)
expect(editor.getViewportPageBounds()).toMatchObject({ x: -0, y: -0, w: 1080, h: 720 })
expect(editor.getViewportPageCenter()).toMatchObject({ x: 540, y: 360 })
editor.keyDown('z')
editor.expectToBeIn('zoom.idle')
editor.pointerDown(newBoundsX, newBoundsY)
@ -157,14 +157,14 @@ describe('TLSelectTool.Zooming', () => {
})
editor.pointerUp(newBoundsX + newBoundsWidth, newBoundsY + newBoundsHeight)
jest.advanceTimersByTime(300)
expect(editor.zoomLevel).toBeCloseTo(1.2888)
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getZoomLevel()).toBeCloseTo(1.2888)
expect(editor.getViewportPageBounds()).toMatchObject({
x: -48.9655172413793,
y: 100.68965517241382,
w: 837.9310344827586,
h: 558.6206896551723,
})
expect(editor.viewportPageCenter).toMatchObject({
expect(editor.getViewportPageCenter()).toMatchObject({
x: newBoundsX + newBoundsWidth / 2,
y: newBoundsY + newBoundsHeight / 2,
})
@ -178,9 +178,9 @@ describe('TLSelectTool.Zooming', () => {
const newBoundsY = 200
editor.expectToBeIn('select.idle')
const originalZoomLevel = 1
expect(editor.zoomLevel).toBe(originalZoomLevel)
expect(editor.viewportPageBounds).toMatchObject({ x: -0, y: -0, w: 1080, h: 720 })
expect(editor.viewportPageCenter).toMatchObject({ x: 540, y: 360 })
expect(editor.getZoomLevel()).toBe(originalZoomLevel)
expect(editor.getViewportPageBounds()).toMatchObject({ x: -0, y: -0, w: 1080, h: 720 })
expect(editor.getViewportPageCenter()).toMatchObject({ x: 540, y: 360 })
editor.keyDown('z')
editor.expectToBeIn('zoom.idle')
editor.keyDown('Alt')
@ -194,14 +194,14 @@ describe('TLSelectTool.Zooming', () => {
})
editor.pointerUp()
jest.advanceTimersByTime(500)
expect(editor.zoomLevel).toBeCloseTo(originalZoomLevel / 2)
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getZoomLevel()).toBeCloseTo(originalZoomLevel / 2)
expect(editor.getViewportPageBounds()).toMatchObject({
x: -440,
y: -160,
w: 2160,
h: 1440,
})
expect(editor.viewportPageCenter).toMatchObject({
expect(editor.getViewportPageCenter()).toMatchObject({
x: newBoundsX + newBoundsWidth / 2,
y: newBoundsY + newBoundsHeight / 2,
})

View file

@ -9,30 +9,30 @@ beforeEach(() => {
jest.useFakeTimers()
it('zooms in gradually when duration is present and animtion speed is default', () => {
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
editor.user.updateUserPreferences({ animationSpeed: 1 }) // default
editor.zoomIn(undefined, { duration: 100 })
editor.emit('tick', 25) // <-- quarter way
expect(editor.zoomLevel).not.toBe(2)
expect(editor.getZoomLevel()).not.toBe(2)
editor.emit('tick', 25) // 50 <-- half way
expect(editor.zoomLevel).not.toBe(2)
expect(editor.getZoomLevel()).not.toBe(2)
editor.emit('tick', 50) // 50 <-- done!
expect(editor.zoomLevel).toBe(2)
expect(editor.getZoomLevel()).toBe(2)
})
it('zooms in gradually when duration is present and animtion speed is off', () => {
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
editor.user.updateUserPreferences({ animationSpeed: 0 }) // none
editor.zoomIn(undefined, { duration: 100 })
expect(editor.zoomLevel).toBe(2) // <-- Should skip!
expect(editor.getZoomLevel()).toBe(2) // <-- Should skip!
})
it('zooms in gradually when duration is present and animtion speed is double', () => {
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
editor.user.updateUserPreferences({ animationSpeed: 2 }) // default
editor.zoomIn(undefined, { duration: 100 })
editor.emit('tick', 25) // <-- half way
expect(editor.zoomLevel).not.toBe(2)
expect(editor.getZoomLevel()).not.toBe(2)
editor.emit('tick', 25) // 50 <-- should finish
expect(editor.zoomLevel).toBe(2)
expect(editor.getZoomLevel()).toBe(2)
})

View file

@ -8,14 +8,14 @@ beforeEach(() => {
it('centers on the point', () => {
editor.centerOnPoint({ x: 400, y: 400 })
expect(editor.viewportPageCenter).toMatchObject({ x: 400, y: 400 })
expect(editor.getViewportPageCenter()).toMatchObject({ x: 400, y: 400 })
})
it('centers on the point with animation', () => {
editor.centerOnPoint({ x: 400, y: 400 }, { duration: 200 })
expect(editor.viewportPageCenter).not.toMatchObject({ x: 400, y: 400 })
expect(editor.getViewportPageCenter()).not.toMatchObject({ x: 400, y: 400 })
jest.advanceTimersByTime(100)
expect(editor.viewportPageCenter).not.toMatchObject({ x: 400, y: 400 })
expect(editor.getViewportPageCenter()).not.toMatchObject({ x: 400, y: 400 })
jest.advanceTimersByTime(200)
expect(editor.viewportPageCenter).toMatchObject({ x: 400, y: 400 })
expect(editor.getViewportPageCenter()).toMatchObject({ x: 400, y: 400 })
})

View file

@ -78,7 +78,7 @@ describe('When copying and pasting', () => {
editor.setCamera({
x: editor.getCamera().x - testOffsetX,
y: editor.getCamera().y - testOffsetY,
z: editor.zoomLevel,
z: editor.getZoomLevel(),
})
editor.paste()
@ -123,7 +123,7 @@ describe('When copying and pasting', () => {
editor.setCamera({
x: editor.getCamera().x - testOffsetX,
y: editor.getCamera().y - testOffsetY,
z: editor.zoomLevel,
z: editor.getZoomLevel(),
})
editor.paste()
@ -161,11 +161,11 @@ describe('When copying and pasting', () => {
const testOffsetX = 2000
const testOffsetY = 3000
const { w: screenWidth, h: screenHeight } = editor.viewportScreenBounds
const { w: screenWidth, h: screenHeight } = editor.getViewportScreenBounds()
editor.setCamera({
x: editor.getCamera().x - testOffsetX,
y: editor.getCamera().y - testOffsetY,
z: editor.zoomLevel,
z: editor.getZoomLevel(),
})
editor.paste()
@ -295,7 +295,7 @@ describe('When copying and pasting', () => {
editor.setCamera({
x: editor.getCamera().x - testOffsetX,
y: editor.getCamera().y - testOffsetY,
z: editor.zoomLevel,
z: editor.getZoomLevel(),
})
editor.paste()
@ -325,7 +325,7 @@ describe('When copying and pasting', () => {
editor.setCamera({
x: editor.getCamera().x - testOffsetX,
y: editor.getCamera().y - testOffsetY,
z: editor.zoomLevel,
z: editor.getZoomLevel(),
})
editor.paste()
@ -354,11 +354,11 @@ describe('When copying and pasting', () => {
const testOffsetX = 2000
const testOffsetY = 3000
const { w: screenWidth, h: screenHeight } = editor.viewportScreenBounds
const { w: screenWidth, h: screenHeight } = editor.getViewportScreenBounds()
editor.setCamera({
x: editor.getCamera().x - testOffsetX,
y: editor.getCamera().y - testOffsetY,
z: editor.zoomLevel,
z: editor.getZoomLevel(),
})
editor.paste()

View file

@ -36,7 +36,7 @@ it('Duplicates a page', () => {
// Also duplicates the camera
expect(editor.getCamera().x).toBe(camera.x)
expect(editor.getCamera().y).toBe(camera.y)
expect(editor.zoomLevel).toBe(camera.z)
expect(editor.getZoomLevel()).toBe(camera.z)
editor.undo()
expect(editor.pages.length).toBe(n)

View file

@ -241,6 +241,6 @@ describe('arrows', () => {
editor.moveShapesToPage([ids.box1, ids.box2], ids.page2)
const selectionPageBounds = editor.getSelectionPageBounds()
expect(editor.viewportPageCenter).toMatchObject(selectionPageBounds!.center)
expect(editor.getViewportPageCenter()).toMatchObject(selectionPageBounds!.center)
})
})

View file

@ -15,17 +15,17 @@ describe('When panning', () => {
})
it('Updates the pageBounds', () => {
const screenBounds = editor.viewportScreenBounds
const screenBounds = editor.getViewportScreenBounds()
const beforeScreenBounds = new Box2d(
screenBounds.x,
screenBounds.y,
screenBounds.w,
screenBounds.h
)
const beforePageBounds = editor.viewportPageBounds.clone()
const beforePageBounds = editor.getViewportPageBounds().clone()
editor.pan({ x: 200, y: 200 })
expect(editor.viewportScreenBounds).toMatchObject(beforeScreenBounds.toJson())
expect(editor.viewportPageBounds.toJson()).toMatchObject(
expect(editor.getViewportScreenBounds()).toMatchObject(beforeScreenBounds.toJson())
expect(editor.getViewportPageBounds().toJson()).toMatchObject(
beforePageBounds.translate(new Vec2d(-200, -200)).toJson()
)
})

View file

@ -8,23 +8,23 @@ beforeEach(() => {
describe('When resetting zoom', () => {
it('Resets the zoom when zoomed out', () => {
const center = editor.viewportScreenBounds.center.clone()
const center = editor.getViewportScreenBounds().center.clone()
editor.zoomOut()
editor.resetZoom()
expect(editor.zoomLevel).toBe(1)
expect(editor.getZoomLevel()).toBe(1)
editor.zoomIn()
editor.resetZoom()
expect(editor.zoomLevel).toBe(1)
expect(editor.viewportScreenBounds.center.clone()).toMatchObject(center)
expect(editor.getZoomLevel()).toBe(1)
expect(editor.getViewportScreenBounds().center.clone()).toMatchObject(center)
})
it('Resets the zoom when zoomed in', () => {
const center = editor.viewportScreenBounds.center.clone()
const center = editor.getViewportScreenBounds().center.clone()
editor.zoomOut()
editor.resetZoom()
expect(editor.viewportScreenBounds.center.clone()).toMatchObject(center)
expect(editor.getViewportScreenBounds().center.clone()).toMatchObject(center)
editor.zoomIn()
editor.resetZoom()
expect(editor.viewportScreenBounds.center.clone()).toMatchObject(center)
expect(editor.getViewportScreenBounds().center.clone()).toMatchObject(center)
})
})

View file

@ -47,7 +47,9 @@ describe('viewport.screenToPage', () => {
})
it('converts correctly when offset', () => {
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 100, y: 100 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 100, y: 100 },
})
checkScreenPage({ x: 0, y: 0 }, { x: -100, y: -100 })
checkScreenPage({ x: -100, y: -100 }, { x: -200, y: -200 })
@ -57,7 +59,9 @@ describe('viewport.screenToPage', () => {
it('converts correctly when zoomed out', () => {
// camera at zero, screenbounds at zero, but zoom at .5
editor.setCamera({ x: 0, y: 0, z: 0.5 })
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0 },
})
checkScreenPage({ x: 0, y: 0 }, { x: 0, y: 0 })
checkScreenPage({ x: -100, y: -100 }, { x: -200, y: -200 })
@ -66,7 +70,9 @@ describe('viewport.screenToPage', () => {
it('converts correctly when zoomed in', () => {
editor.setCamera({ x: 0, y: 0, z: 2 })
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0 },
})
checkScreenPage({ x: 0, y: 0 }, { x: 0, y: 0 })
checkScreenPage({ x: -100, y: -100 }, { x: -50, y: -50 })
@ -75,7 +81,9 @@ describe('viewport.screenToPage', () => {
it('converts correctly when zoomed', () => {
// camera at zero, screenbounds at zero, but zoom at .5
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0 },
})
editor.setCamera({ x: 0, y: 0, z: 0.5 })
checkScreenPage({ x: 0, y: 0 }, { x: 0, y: 0 })
@ -85,7 +93,9 @@ describe('viewport.screenToPage', () => {
it('converts correctly when offset and zoomed', () => {
editor.setCamera({ x: 0, y: 0, z: 0.5 })
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 100, y: 100 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 100, y: 100 },
})
checkScreenPage({ x: 0, y: 0 }, { x: -200, y: -200 })
checkScreenPage({ x: -100, y: -100 }, { x: -400, y: -400 })
@ -93,7 +103,9 @@ describe('viewport.screenToPage', () => {
})
it('converts correctly when zoomed and panned', () => {
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0 },
})
editor.setCamera({ x: 100, y: 100, z: 0.5 })
checkScreenPage({ x: 0, y: 0 }, { x: -100, y: -100 })
@ -102,7 +114,9 @@ describe('viewport.screenToPage', () => {
})
it('converts correctly when offset', () => {
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 100, y: 100 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 100, y: 100 },
})
editor.setCamera({ x: 0, y: 0, z: 0.5 })
checkScreenPage({ x: 0, y: 0 }, { x: -200, y: -200 })
@ -111,7 +125,9 @@ describe('viewport.screenToPage', () => {
})
it('converts correctly when panned', () => {
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0 },
})
editor.setCamera({ x: 100, y: 100, z: 1 })
checkScreenPage({ x: 0, y: 0 }, { x: -100, y: -100 })
@ -120,7 +136,9 @@ describe('viewport.screenToPage', () => {
})
it('converts correctly when panned and zoomed', () => {
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0 },
})
editor.setCamera({ x: 100, y: 100, z: 0.5 })
checkScreenPage({ x: 0, y: 0 }, { x: -100, y: -100 })
@ -129,7 +147,9 @@ describe('viewport.screenToPage', () => {
})
it('converts correctly when panned and zoomed and offset', () => {
editor.updateInstanceState({ screenBounds: { ...editor.viewportScreenBounds, x: 100, y: 100 } })
editor.updateInstanceState({
screenBounds: { ...editor.getViewportScreenBounds(), x: 100, y: 100 },
})
editor.setCamera({ x: 100, y: 100, z: 0.5 })
checkScreenPage({ x: 0, y: 0 }, { x: -300, y: -300 })
@ -141,11 +161,11 @@ describe('viewport.screenToPage', () => {
describe('viewportPageBounds', () => {
it('sets the page bounds', () => {
editor.updateInstanceState({
screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0, w: 1000, h: 1000 },
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0, w: 1000, h: 1000 },
})
editor.setCamera({ x: 0, y: 0, z: 1 })
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getViewportPageBounds()).toMatchObject({
x: -0,
y: -0,
w: 1000,
@ -155,11 +175,11 @@ describe('viewportPageBounds', () => {
it('sets the page bounds when camera is zoomed', () => {
editor.updateInstanceState({
screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0, w: 1000, h: 1000 },
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0, w: 1000, h: 1000 },
})
editor.setCamera({ x: 0, y: 0, z: 2 })
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getViewportPageBounds()).toMatchObject({
x: -0,
y: -0,
w: 500,
@ -167,7 +187,7 @@ describe('viewportPageBounds', () => {
})
editor.setCamera({ x: 0, y: 0, z: 0.5 })
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getViewportPageBounds()).toMatchObject({
x: -0,
y: -0,
w: 2000,
@ -177,11 +197,11 @@ describe('viewportPageBounds', () => {
it('sets the page bounds when camera is panned', () => {
editor.updateInstanceState({
screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0, w: 1000, h: 1000 },
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0, w: 1000, h: 1000 },
})
editor.setCamera({ x: 100, y: 100, z: 1 })
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getViewportPageBounds()).toMatchObject({
x: -100,
y: -100,
w: 1000,
@ -193,11 +213,11 @@ describe('viewportPageBounds', () => {
it('sets the page bounds when camera is panned and zoomed', () => {
editor.updateInstanceState({
screenBounds: { ...editor.viewportScreenBounds, x: 0, y: 0, w: 1000, h: 1000 },
screenBounds: { ...editor.getViewportScreenBounds(), x: 0, y: 0, w: 1000, h: 1000 },
})
editor.setCamera({ x: 100, y: 100, z: 2 })
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getViewportPageBounds()).toMatchObject({
x: -100,
y: -100,
w: 500,
@ -209,12 +229,12 @@ describe('viewportPageBounds', () => {
it('sets the page bounds when viewport is offset', () => {
editor.updateInstanceState({
screenBounds: { ...editor.viewportScreenBounds, x: 100, y: 100, w: 1000, h: 1000 },
screenBounds: { ...editor.getViewportScreenBounds(), x: 100, y: 100, w: 1000, h: 1000 },
})
editor.setCamera({ x: 0, y: 0, z: 2 })
// changing the screen bounds should not affect the page bounds
expect(editor.viewportPageBounds).toMatchObject({
expect(editor.getViewportPageBounds()).toMatchObject({
x: -0,
y: -0,
w: 500,

View file

@ -17,7 +17,7 @@ beforeEach(() => {
describe('When resizing', () => {
it('sets the viewport bounds with Editor.resize', () => {
editor.setScreenBounds({ x: 100, y: 200, w: 700, h: 600 })
expect(editor.viewportScreenBounds).toMatchObject({
expect(editor.getViewportScreenBounds()).toMatchObject({
x: 100,
y: 200,
w: 700,
@ -30,7 +30,7 @@ describe('When resizing', () => {
editor.undo() // this should have no effect
expect(editor.viewportScreenBounds).toMatchObject({
expect(editor.getViewportScreenBounds()).toMatchObject({
x: 100,
y: 200,
w: 700,
@ -40,7 +40,7 @@ describe('When resizing', () => {
it('clamps bounds to minimim 0,0,1,1', () => {
editor.setScreenBounds({ x: -100, y: -200, w: -700, h: 0 })
expect(editor.viewportScreenBounds).toMatchObject({
expect(editor.getViewportScreenBounds()).toMatchObject({
x: -100,
y: -200,
w: 1,
@ -54,7 +54,7 @@ describe('When center is false', () => {
const a = editor.screenToPage({ x: 0, y: 0 })
expect(a).toMatchObject({ x: 0, y: 0 })
editor.setScreenBounds({ x: 100, y: 200, w: 500, h: 600 }, false)
expect(editor.viewportScreenBounds).toMatchObject({
expect(editor.getViewportScreenBounds()).toMatchObject({
x: 100,
y: 200,
w: 500,
@ -70,7 +70,7 @@ describe('When center is false', () => {
expect(a).toMatchObject({ x: 100, y: 100 })
editor.setScreenBounds({ x: 100, y: 200, w: 500, h: 600 }, false)
expect(editor.viewportScreenBounds).toMatchObject({
expect(editor.getViewportScreenBounds()).toMatchObject({
x: 100,
y: 200,
w: 500,
@ -87,7 +87,7 @@ describe('When center is false', () => {
expect(editor.screenToPage({ x: 0, y: 0 })).toMatchObject({ x: 100, y: 100 })
editor.setScreenBounds({ x: 100, y: 100, w: 500, h: 600 }, false)
expect(editor.viewportScreenBounds).toMatchObject({
expect(editor.getViewportScreenBounds()).toMatchObject({
x: 100,
y: 100,
w: 500,
@ -99,17 +99,17 @@ describe('When center is false', () => {
describe('When center is true', () => {
it('keep the same page center when resized', () => {
const a = editor.viewportPageCenter.toJson()
const a = editor.getViewportPageCenter().toJson()
editor.setScreenBounds({ x: 100, y: 200, w: 500, h: 600 }, true)
const b = editor.viewportPageCenter.toJson()
const b = editor.getViewportPageCenter().toJson()
expect(a).toMatchObject(b)
})
it('keep the same page center when resized while panned / zoomed', () => {
editor.setCamera({ x: -100, y: -100, z: 1.2 })
const a = editor.viewportPageCenter.toJson()
const a = editor.getViewportPageCenter().toJson()
editor.setScreenBounds({ x: 100, y: 200, w: 500, h: 600 }, true)
const b = editor.viewportPageCenter.toJson()
const b = editor.getViewportPageCenter().toJson()
expect(a).toMatchObject(b)
})
})

View file

@ -9,29 +9,29 @@ beforeEach(() => {
it('zooms by increments', () => {
// Starts at 1
expect(editor.zoomLevel).toBe(1)
expect(editor.zoomLevel).toBe(ZOOMS[3])
expect(editor.getZoomLevel()).toBe(1)
expect(editor.getZoomLevel()).toBe(ZOOMS[3])
// zooms in
expect(editor.zoomLevel).toBe(ZOOMS[3])
expect(editor.getZoomLevel()).toBe(ZOOMS[3])
editor.zoomIn()
expect(editor.zoomLevel).toBe(ZOOMS[4])
expect(editor.getZoomLevel()).toBe(ZOOMS[4])
editor.zoomIn()
expect(editor.zoomLevel).toBe(ZOOMS[5])
expect(editor.getZoomLevel()).toBe(ZOOMS[5])
editor.zoomIn()
expect(editor.zoomLevel).toBe(ZOOMS[6])
expect(editor.getZoomLevel()).toBe(ZOOMS[6])
// does not zoom in past max
editor.zoomIn()
expect(editor.zoomLevel).toBe(ZOOMS[6])
expect(editor.getZoomLevel()).toBe(ZOOMS[6])
})
it('zooms to from B to D when B >= (C - A)/2, else zooms from B to C', () => {
editor.setCamera({ x: 0, y: 0, z: (ZOOMS[2] + ZOOMS[3]) / 2 })
editor.zoomIn()
expect(editor.zoomLevel).toBe(ZOOMS[4])
expect(editor.getZoomLevel()).toBe(ZOOMS[4])
editor.setCamera({ x: 0, y: 0, z: (ZOOMS[2] + ZOOMS[3]) / 2 - 0.1 })
editor.zoomIn()
expect(editor.zoomLevel).toBe(ZOOMS[3])
expect(editor.getZoomLevel()).toBe(ZOOMS[3])
})
it('does not zoom when camera is frozen', () => {

View file

@ -9,17 +9,17 @@ beforeEach(() => {
it('zooms by increments', () => {
// Starts at 1
expect(editor.zoomLevel).toBe(1)
expect(editor.zoomLevel).toBe(ZOOMS[3])
expect(editor.getZoomLevel()).toBe(1)
expect(editor.getZoomLevel()).toBe(ZOOMS[3])
editor.zoomOut()
expect(editor.zoomLevel).toBe(ZOOMS[2])
expect(editor.getZoomLevel()).toBe(ZOOMS[2])
editor.zoomOut()
expect(editor.zoomLevel).toBe(ZOOMS[1])
expect(editor.getZoomLevel()).toBe(ZOOMS[1])
editor.zoomOut()
expect(editor.zoomLevel).toBe(ZOOMS[0])
expect(editor.getZoomLevel()).toBe(ZOOMS[0])
// does not zoom out past min
editor.zoomOut()
expect(editor.zoomLevel).toBe(ZOOMS[0])
expect(editor.getZoomLevel()).toBe(ZOOMS[0])
})
it('does not zoom out when camera is frozen', () => {

View file

@ -9,15 +9,15 @@ beforeEach(() => {
describe('When zooming to bounds', () => {
it('centers the camera on the new bounds', () => {
expect(editor.viewportPageCenter).toMatchObject({ x: 540, y: 360 })
expect(editor.getViewportPageCenter()).toMatchObject({ x: 540, y: 360 })
editor.setScreenBounds({ x: 0, y: 0, w: 1000, h: 1000 })
expect(editor.viewportPageCenter).toMatchObject({ x: 500, y: 500 })
expect(editor.getViewportPageCenter()).toMatchObject({ x: 500, y: 500 })
editor.setCamera({ x: 0, y: 0, z: 1 })
expect(editor.viewportPageBounds).toCloselyMatchObject({
expect(editor.getViewportPageBounds()).toCloselyMatchObject({
x: -0,
y: -0,
w: 1000,
@ -26,25 +26,25 @@ describe('When zooming to bounds', () => {
editor.zoomToBounds(new Box2d(200, 300, 300, 300))
expect(editor.getCamera().z).toCloselyMatchObject((1000 - 256) / 300)
expect(editor.viewportPageBounds.width).toCloselyMatchObject(1000 / ((1000 - 256) / 300))
expect(editor.viewportPageBounds.height).toCloselyMatchObject(1000 / ((1000 - 256) / 300))
expect(editor.getViewportPageBounds().width).toCloselyMatchObject(1000 / ((1000 - 256) / 300))
expect(editor.getViewportPageBounds().height).toCloselyMatchObject(1000 / ((1000 - 256) / 300))
})
})
it('does not zoom past max', () => {
editor.zoomToBounds(new Box2d(0, 0, 1, 1))
expect(editor.zoomLevel).toBe(8)
expect(editor.getZoomLevel()).toBe(8)
})
it('does not zoom past min', () => {
editor.zoomToBounds(new Box2d(0, 0, 1000000, 100000))
expect(editor.zoomLevel).toBe(0.1)
expect(editor.getZoomLevel()).toBe(0.1)
})
it('does not zoom to bounds when camera is frozen', () => {
editor.setScreenBounds({ x: 0, y: 0, w: 1000, h: 1000 })
expect(editor.viewportPageCenter.toJson()).toCloselyMatchObject({ x: 500, y: 500 })
expect(editor.getViewportPageCenter().toJson()).toCloselyMatchObject({ x: 500, y: 500 })
editor.updateInstanceState({ canMoveCamera: false })
editor.zoomToBounds(new Box2d(200, 300, 300, 300))
expect(editor.viewportPageCenter.toJson()).toCloselyMatchObject({ x: 500, y: 500 })
expect(editor.getViewportPageCenter().toJson()).toCloselyMatchObject({ x: 500, y: 500 })
})

View file

@ -23,14 +23,14 @@ it('does not zoom past max', () => {
editor.updateShapes([{ id: ids.box1, type: 'geo', props: { w: 1, h: 1 } }])
editor.select(ids.box1)
editor.zoomToSelection()
expect(editor.zoomLevel).toBe(1) // double check again when we're zooming in hard
expect(editor.getZoomLevel()).toBe(1) // double check again when we're zooming in hard
})
it('does not zoom past min', () => {
editor.updateShapes([{ id: ids.box1, type: 'geo', props: { w: 100000, h: 100000 } }])
editor.select(ids.box1)
editor.zoomToSelection()
expect(editor.zoomLevel).toBe(0.1)
expect(editor.getZoomLevel()).toBe(0.1)
})
it('does not zoom to selection when camera is frozen', () => {

View file

@ -460,11 +460,11 @@ describe('When pasting into frames...', () => {
{
id: ids.frame1,
type: 'frame',
x: editor.viewportScreenBounds.w,
y: editor.viewportScreenBounds.h,
x: editor.getViewportScreenBounds().w,
y: editor.getViewportScreenBounds().h,
props: {
w: editor.viewportScreenBounds.w,
h: editor.viewportScreenBounds.h,
w: editor.getViewportScreenBounds().w,
h: editor.getViewportScreenBounds().h,
},
},
])
@ -472,7 +472,11 @@ describe('When pasting into frames...', () => {
// rotate the frame for hard mode
editor.rotateSelection(45)
// center on the center of the frame
editor.setCamera({ x: -editor.viewportScreenBounds.w, y: -editor.viewportScreenBounds.h, z: 1 })
editor.setCamera({
x: -editor.getViewportScreenBounds().w,
y: -editor.getViewportScreenBounds().h,
z: 1,
})
// paste the box
editor.paste()
const boxId = editor.getOnlySelectedShape()!.id

View file

@ -562,7 +562,7 @@ describe('snapping with single shapes', () => {
editor.pointerDown(25, 5, ids.box2).pointerMove(36, 5, { ctrlKey: true })
expect(editor.snaps.lines!.length).toBe(0)
editor.updateShapes([{ id: ids.box1, type: 'geo', x: editor.viewportScreenBounds.w + 10 }])
editor.updateShapes([{ id: ids.box1, type: 'geo', x: editor.getViewportScreenBounds().w + 10 }])
editor.pointerMove(33, 5, { ctrlKey: true })
expect(editor.snaps.lines!.length).toBe(0)
@ -572,7 +572,7 @@ describe('snapping with single shapes', () => {
expect(editor.snaps.lines!.length).toBe(0)
editor.updateShapes([
{ id: ids.box1, type: 'geo', x: 0, y: editor.viewportScreenBounds.h + 10 },
{ id: ids.box1, type: 'geo', x: 0, y: editor.getViewportScreenBounds().h + 10 },
])
editor.pointerMove(5, 5, { ctrlKey: true })