everything working but page load camera initialization

This commit is contained in:
Jeff Emmett 2024-12-08 05:45:16 -05:00
parent e466d2b49f
commit 184efcf88a
3 changed files with 106 additions and 75 deletions

View File

@ -1,5 +1,5 @@
import { useEffect } from "react" import { useEffect } from "react"
import { Editor, TLEventMap, TLFrameShape, TLParentId } from "tldraw" import { Editor, TLEventMap, TLFrameShape, TLParentId, TLShapeId } from "tldraw"
import { useSearchParams } from "react-router-dom" import { useSearchParams } from "react-router-dom"
// Define camera state interface // Define camera state interface
@ -38,35 +38,60 @@ export function useCameraControls(editor: Editor | null) {
// Handle URL-based camera positioning // Handle URL-based camera positioning
useEffect(() => { useEffect(() => {
if (!editor) return if (!editor || !editor.store || !editor.getInstanceState().isFocused) {
console.log("Editor not ready:", {
const frameId = searchParams.get("frameId") editor: !!editor,
const x = searchParams.get("x") store: !!editor?.store,
const y = searchParams.get("y") isFocused: editor?.getInstanceState().isFocused,
const zoom = searchParams.get("zoom")
if (x && y && zoom) {
editor.setCamera({
x: parseFloat(x),
y: parseFloat(y),
z: parseFloat(zoom),
}) })
return return
} }
if (frameId) { const x = searchParams.get("x")
const frame = editor.getShape(frameId as TLParentId) as TLFrameShape const y = searchParams.get("y")
if (!frame) { const zoom = searchParams.get("zoom")
console.warn("Frame not found:", frameId) const frameId = searchParams.get("frameId")
return const isLocked = searchParams.get("isLocked") === "true"
}
// Use editor's built-in zoomToBounds with animation console.log("Setting camera:", { x, y, zoom })
editor.zoomToBounds(editor.getShapePageBounds(frame)!, {
inset: 32, // Set camera position if coordinates exist
animation: { duration: 500 }, if (x && y && zoom) {
const position = {
x: parseFloat(x),
y: parseFloat(y),
z: parseFloat(zoom),
}
console.log("Camera position:", position)
requestAnimationFrame(() => {
editor.setCamera(position, { animation: { duration: 0 } })
console.log("Current camera:", editor.getCamera())
}) })
} }
// Handle frame-specific logic
if (frameId) {
const frame = editor.getShape(frameId as TLShapeId)
if (frame) {
editor.select(frameId as TLShapeId)
// If x/y/zoom are not provided in URL, zoom to frame bounds
if (!x || !y || !zoom) {
editor.zoomToBounds(editor.getShapePageBounds(frame)!, {
animation: { duration: 0 },
targetZoom: 1,
})
}
// Apply camera lock after camera is positioned
if (isLocked) {
requestAnimationFrame(() => {
editor.setCameraOptions({ isLocked: true })
})
}
}
}
}, [editor, searchParams]) }, [editor, searchParams])
// Track camera changes // Track camera changes
@ -100,12 +125,6 @@ export function useCameraControls(editor: Editor | null) {
}) })
}, },
copyFrameLink: (frameId: string) => {
const url = new URL(window.location.href)
url.searchParams.set("frameId", frameId)
navigator.clipboard.writeText(url.toString())
},
copyLocationLink: () => { copyLocationLink: () => {
if (!editor) return if (!editor) return
const camera = editor.getCamera() const camera = editor.getCamera()
@ -116,6 +135,12 @@ export function useCameraControls(editor: Editor | null) {
navigator.clipboard.writeText(url.toString()) 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: () => { revertCamera: () => {
if (!editor || cameraHistory.length === 0) return if (!editor || cameraHistory.length === 0) return
const previousCamera = cameraHistory.pop() const previousCamera = cameraHistory.pop()

View File

@ -195,8 +195,8 @@ export const lockCameraToFrame = async (editor: Editor) => {
) )
// Set camera parameters first // Set camera parameters first
url.searchParams.set("x", bounds.x.toString()) url.searchParams.set("x", Math.round(bounds.x).toString())
url.searchParams.set("y", bounds.y.toString()) url.searchParams.set("y", Math.round(bounds.y).toString())
url.searchParams.set("zoom", targetZoom.toString()) url.searchParams.set("zoom", targetZoom.toString())
// Add frame-specific parameters last // Add frame-specific parameters last

View File

@ -1,67 +1,73 @@
import { Editor, TLShapeId } from "tldraw" import { Editor, TLShapeId } from "tldraw"
export const handleInitialPageLoad = (editor: Editor) => { export const handleInitialPageLoad = (editor: Editor) => {
// Wait for editor to be ready
// if (!editor.isMounted()) {
// editor.once("mount", () => handleInitialPageLoad(editor))
// return
// }
const url = new URL(window.location.href) const url = new URL(window.location.href)
console.log("URL params:", {
x: url.searchParams.get("x"),
y: url.searchParams.get("y"),
zoom: url.searchParams.get("zoom"),
})
// Get camera parameters first // Get camera parameters first
const x = url.searchParams.get("x") const x = url.searchParams.get("x")
const y = url.searchParams.get("y") const y = url.searchParams.get("y")
const zoom = url.searchParams.get("zoom") const zoom = url.searchParams.get("zoom")
// Get shape/frame parameters last // Set camera position if coordinates exist
const frameId = url.searchParams.get("frameId") if (x && y && zoom) {
const shapeId = url.searchParams.get("shapeId") console.log("Setting camera to:", {
const isLocked = url.searchParams.get("isLocked") === "true" x: parseFloat(x),
y: parseFloat(y),
z: parseFloat(zoom),
})
// Wait for next tick to ensure editor is ready requestAnimationFrame(() => {
requestAnimationFrame(() => {
// Set camera position if coordinates exist
if (x && y && zoom) {
editor.setCamera({ editor.setCamera({
x: parseFloat(x), x: parseFloat(x),
y: parseFloat(y), y: parseFloat(y),
z: parseFloat(zoom), z: parseFloat(zoom),
}) })
} })
}
// Handle frame-specific logic // Get shape/frame parameters last
if (frameId) { const frameId = url.searchParams.get("frameId")
const frame = editor.getShape(frameId as TLShapeId) const isLocked = url.searchParams.get("isLocked") === "true"
if (frame) {
editor.select(frameId as TLShapeId)
// If x/y/zoom are not provided in URL, zoom to frame bounds // Handle frame-specific logic
if (!x || !y || !zoom) { if (frameId) {
editor.zoomToBounds(editor.getShapePageBounds(frame)!, { const frame = editor.getShape(frameId as TLShapeId)
animation: { duration: 0 }, if (frame) {
targetZoom: 1, editor.select(frameId as TLShapeId)
})
}
// Apply camera lock after camera is positioned // If x/y/zoom are not provided in URL, zoom to frame bounds
if (isLocked) { if (!x || !y || !zoom) {
// Use requestAnimationFrame to ensure camera is set before locking editor.zoomToBounds(editor.getShapePageBounds(frame)!, {
requestAnimationFrame(() => { animation: { duration: 0 },
editor.setCameraOptions({ targetZoom: 1,
isLocked: true, })
// Optional: you may want to also set these options for locked frames
//shouldSnapToGrid: false,
//shouldUseEdgeScrolling: false,
})
})
}
} else {
console.warn("Frame not found:", frameId)
} }
}
// Handle shape-specific logic // Apply camera lock after camera is positioned
else if (shapeId) { if (isLocked) {
const shape = editor.getShape(shapeId as TLShapeId) // Use requestAnimationFrame to ensure camera is set before locking
if (shape) { requestAnimationFrame(() => {
editor.select(shapeId as TLShapeId) editor.setCameraOptions({
} else { isLocked: true,
console.warn("Shape not found:", shapeId) // Optional: you may want to also set these options for locked frames
//shouldSnapToGrid: false,
//shouldUseEdgeScrolling: false,
})
})
} }
} else {
console.warn("Frame not found:", frameId)
} }
}) }
} }