canvas-website/src/hooks/useCameraControls.ts

88 lines
2.3 KiB
TypeScript

import { useEffect } from "react"
import { Editor, TLEventMap, TLFrameShape, TLParentId } from "tldraw"
import { cameraHistory } from "@/ui/cameraUtils"
// Define camera state interface
interface CameraState {
x: number
y: number
z: number
}
const MAX_HISTORY = 10
// Track camera changes
const trackCameraChange = (editor: Editor) => {
const currentCamera = editor.getCamera()
const lastPosition = cameraHistory[cameraHistory.length - 1]
if (
!lastPosition ||
currentCamera.x !== lastPosition.x ||
currentCamera.y !== lastPosition.y ||
currentCamera.z !== lastPosition.z
) {
cameraHistory.push({ ...currentCamera })
if (cameraHistory.length > MAX_HISTORY) {
cameraHistory.shift()
}
}
}
export function useCameraControls(editor: Editor | null) {
// Track camera changes
useEffect(() => {
if (!editor) return
const handler = () => {
trackCameraChange(editor)
}
editor.on("viewportChange" as keyof TLEventMap, handler)
editor.on("userChangeEnd" as keyof TLEventMap, handler)
return () => {
editor.off("viewportChange" as keyof TLEventMap, handler)
editor.off("userChangeEnd" as keyof TLEventMap, handler)
}
}, [editor])
// Camera control functions
return {
zoomToFrame: (frameId: string) => {
if (!editor) return
const frame = editor.getShape(frameId as TLParentId) as TLFrameShape
if (!frame) return
editor.zoomToBounds(editor.getShapePageBounds(frame)!, {
inset: 32,
animation: { duration: 500 },
})
},
copyLocationLink: () => {
if (!editor) return
const camera = editor.getCamera()
const url = new URL(window.location.href)
url.searchParams.set("x", camera.x.toFixed(2))
url.searchParams.set("y", camera.y.toFixed(2))
url.searchParams.set("zoom", camera.z.toFixed(2))
navigator.clipboard.writeText(url.toString())
},
copyFrameLink: (frameId: string) => {
const url = new URL(window.location.href)
url.searchParams.set("frameId", frameId)
navigator.clipboard.writeText(url.toString())
},
revertCamera: () => {
if (!editor || cameraHistory.length === 0) return
const previousCamera = cameraHistory.pop()
if (previousCamera) {
editor.setCamera(previousCamera, { animation: { duration: 200 } })
}
},
}
}