apps/docs/content/sdk-features/coordinates.mdx
The editor uses three coordinate systems: screen space, viewport space, and page space. When you move the mouse over the canvas, the browser gives you screen coordinates. To create a shape at that location, you need to convert those coordinates to page space.
The editor provides methods to convert between these coordinate systems. You'll use these when building custom tools, positioning DOM overlays, or responding to pointer events. The Camera article explains the camera values these conversions depend on.
| Method | Description |
|---|---|
| Editor#screenToPage | Convert a screen point to page space. |
| Editor#pageToScreen | Convert a page point to screen space. |
| Editor#pageToViewport | Convert a page point to viewport space (relative to the container). |
Screen space uses pixel coordinates from the browser window's top-left corner. These are the values you get from MouseEvent.clientX and MouseEvent.clientY. Screen coordinates include any space outside the editor container, like browser chrome or other page content.
Viewport space uses pixel coordinates from the editor container's top-left corner. This accounts for where the editor sits on the page. If the editor is embedded in a scrollable element or positioned away from the browser's origin, viewport coordinates differ from screen coordinates by that offset.
The editor tracks the container's position in Editor#getViewportScreenBounds.
Page space is the infinite canvas itself. A shape at x: 100, y: 200 stays at those coordinates regardless of how the user pans or zooms. Top-level shapes store their position in page space; children of frames and groups store it relative to their parent. See Parenting for the helpers that convert between shape space and page space.
The camera determines which part of page space is visible. When you zoom in, the same page-space region takes up more screen pixels. When you pan, different page-space coordinates come into view.
Use Editor#screenToPage to convert screen coordinates to page coordinates. This is the most common transformation. It accounts for the editor container's position, the camera position, and the zoom level:
// Convert mouse event coordinates to page space
const pagePoint = editor.screenToPage({ x: event.clientX, y: event.clientY })
// Create a shape at the clicked location
editor.createShape({
type: 'geo',
x: pagePoint.x,
y: pagePoint.y,
props: { w: 100, h: 100, geo: 'rectangle' },
})
Use Editor#pageToScreen to convert page coordinates to screen coordinates, for example to position a DOM element that lives outside the editor container:
// Convert shape position to screen coordinates
const shape = editor.getShape(shapeId)
if (!shape) return
const screenPoint = editor.pageToScreen({ x: shape.x, y: shape.y })
// Position a DOM element at the shape's screen location
element.style.left = `${screenPoint.x}px`
element.style.top = `${screenPoint.y}px`
Use Editor#pageToViewport to convert page coordinates to viewport coordinates. This is pageToScreen() without the container offset, so use it for canvas rendering or for positioning elements inside the editor container:
// Get viewport coordinates for a page point
const viewportPoint = editor.pageToViewport({ x: 500, y: 300 })
// Check if a point is visible in the viewport
const viewportBounds = editor.getViewportScreenBounds()
const isVisible =
viewportPoint.x >= 0 &&
viewportPoint.x <= viewportBounds.w &&
viewportPoint.y >= 0 &&
viewportPoint.y <= viewportBounds.h
Use Editor#getViewportScreenBounds to get the editor container's position and size in screen space:
const screenBounds = editor.getViewportScreenBounds()
// screenBounds.x, screenBounds.y - container position in screen space
// screenBounds.w, screenBounds.h - container dimensions in pixels
Use Editor#getViewportPageBounds to get the visible area in page space:
const pageBounds = editor.getViewportPageBounds()
// pageBounds.x, pageBounds.y - top-left corner of visible area in page space
// pageBounds.w, pageBounds.h - visible area dimensions in page units
Both are reactive, so you can read them inside track components or useValue and re-render when the user pans or zooms. At higher zoom levels, the visible page-space area is smaller.
The editor's inputs manager tracks the current pointer position, so you can read it from anywhere in your code:
// Get the current pointer position
const screenPoint = editor.inputs.getCurrentScreenPoint()
const pagePoint = editor.inputs.getCurrentPagePoint()
// Get the position where the current drag started
const originScreenPoint = editor.inputs.getOriginScreenPoint()
const originPagePoint = editor.inputs.getOriginPagePoint()
Despite the name, the inputs manager's "screen point" is relative to the editor container, which this article calls viewport space. Don't pass it to screenToPage() and don't subtract getViewportScreenBounds() from it.
Pointer event info is different: its point property holds clientX/clientY, so it is in screen space and converts with screenToPage():
editor.on('event', (event) => {
if (event.type === 'pointer' && event.name === 'pointer_down') {
const pagePoint = editor.screenToPage(event.point)
// Use pagePoint for shape manipulation
}
})