Loading packages/client-next/src/components/CanvasWrapper.tsx +24 −13 Original line number Diff line number Diff line import React, { createRef, useContext, useEffect } from "react"; import React, { createRef, useCallback, useContext, useEffect } from "react"; import { Canvas } from "../lib/canvas"; import { useAppContext } from "../contexts/AppContext"; import { PanZoomWrapper } from "@sc07-canvas/lib/src/renderer"; import { RendererContext } from "@sc07-canvas/lib/src/renderer/RendererContext"; import { ViewportMoveEvent } from "@sc07-canvas/lib/src/renderer/PanZoom"; import throttle from "lodash.throttle"; import { ICanvasPosition } from "../types"; import { Routes } from "../lib/routes"; export const CanvasWrapper = () => { // to prevent safari from blurring things, use the zoom css property Loading @@ -17,30 +21,37 @@ export const CanvasWrapper = () => { const CanvasInner = () => { const canvasRef = createRef<HTMLCanvasElement>(); const { config } = useAppContext(); const { config, setCanvasPosition } = useAppContext(); const PanZoom = useContext(RendererContext); // const { centerView } = useControls(); // useTransformEffect( // throttle(({ state, instance }) => { // const params = new URLSearchParams(); // params.set("x", state.positionX + ""); // params.set("y", state.positionY + ""); // params.set("zoom", state.scale + ""); // window.location.hash = params.toString(); // }, 1000) // ); useEffect(() => { if (!config.canvas || !canvasRef.current) return; const canvas = canvasRef.current!; const canvasInstance = new Canvas(config, canvas, PanZoom); // centerView(); const handleViewportMove = throttle((state: ViewportMoveEvent) => { const pos = canvasInstance.panZoomTransformToCanvas(); const canvasPosition: ICanvasPosition = { x: pos.canvasX, y: pos.canvasY, zoom: state.scale >> 0, }; setCanvasPosition(canvasPosition); window.location.replace(Routes.canvas(canvasPosition)); }, 1000); PanZoom.addListener("viewportMove", handleViewportMove); return () => { canvasInstance.destroy(); PanZoom.removeListener("viewportMove", handleViewportMove); }; }, [canvasRef, config]); }, [PanZoom, canvasRef, config, setCanvasPosition]); return ( <canvas Loading packages/client-next/src/components/Pallete.tsx +9 −0 Original line number Diff line number Diff line Loading @@ -68,8 +68,17 @@ export const Pallete = () => { }; export const CanvasMeta = () => { const { canvasPosition } = useAppContext(); return ( <div id="canvas-meta"> {canvasPosition && ( <span> <button className="btn-link"> ({canvasPosition.x}, {canvasPosition.y}) </button> </span> )} <span> Pixels: <span>123</span> </span> Loading packages/client-next/src/contexts/AppContext.tsx +10 −2 Original line number Diff line number Diff line Loading @@ -6,7 +6,12 @@ import React, { useState, } from "react"; import { Socket } from "socket.io-client"; import { ClientConfig, IAppContext, IPalleteContext } from "../types"; import { ClientConfig, IAppContext, ICanvasPosition, IPalleteContext, } from "../types"; import { AuthSession } from "@sc07-canvas/lib/src/net"; import { number } from "prop-types"; import Network from "../lib/network"; Loading @@ -18,6 +23,7 @@ export const useAppContext = () => useContext(appContext); export const AppContext = ({ children }: PropsWithChildren) => { const [config, setConfig] = useState<ClientConfig>(undefined as any); const [auth, setAuth] = useState<AuthSession>(); const [canvasPosition, setCanvasPosition] = useState<ICanvasPosition>(); useEffect(() => { function handleConfig(config: ClientConfig) { Loading @@ -41,7 +47,9 @@ export const AppContext = ({ children }: PropsWithChildren) => { }, []); return ( <appContext.Provider value={{ config, user: auth }}> <appContext.Provider value={{ config, user: auth, canvasPosition, setCanvasPosition }} > {config ? children : "Loading..."} </appContext.Provider> ); Loading packages/client-next/src/lib/canvas.ts +40 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,46 @@ export class Canvas extends EventEmitter { }); } panZoomTransformToCanvas() { const { x, y, scale: zoom } = this.PanZoom.transform; const rect = this.canvas.getBoundingClientRect(); let canvasX = 0; let canvasY = 0; if (this.PanZoom.flags.useZoom) { // css zoom doesn't change the bounding client rect // therefore dividing by zoom doesn't return the correct output canvasX = this.canvas.width - (x + rect.width / 2); canvasY = this.canvas.height - (y + rect.height / 2); } else { canvasX = this.canvas.width / 2 - (x + rect.width / zoom); canvasY = this.canvas.height / 2 - (y + rect.height / zoom); canvasX += this.canvas.width; canvasY += this.canvas.height; } canvasX >>= 0; canvasY >>= 0; return { canvasX, canvasY }; } debug(x: number, y: number, id?: string) { if (document.getElementById("debug-" + id)) { document.getElementById("debug-" + id)!.style.top = y + "px"; document.getElementById("debug-" + id)!.style.left = x + "px"; return; } let el = document.createElement("div"); if (id) el.id = "debug-" + id; el.classList.add("debug-point"); el.style.setProperty("top", y + "px"); el.style.setProperty("left", x + "px"); document.body.appendChild(el); } screenToPos(x: number, y: number) { // the rendered dimentions in the browser const rect = this.canvas.getBoundingClientRect(); Loading packages/client-next/src/lib/routes.ts 0 → 100644 +12 −0 Original line number Diff line number Diff line import { ICanvasPosition } from "../types"; export const Routes = { canvas: (pos: ICanvasPosition) => { const params = new URLSearchParams(); params.set("x", pos.x + ""); params.set("y", pos.y + ""); params.set("zoom", pos.zoom + ""); return "/#" + params; }, }; Loading
packages/client-next/src/components/CanvasWrapper.tsx +24 −13 Original line number Diff line number Diff line import React, { createRef, useContext, useEffect } from "react"; import React, { createRef, useCallback, useContext, useEffect } from "react"; import { Canvas } from "../lib/canvas"; import { useAppContext } from "../contexts/AppContext"; import { PanZoomWrapper } from "@sc07-canvas/lib/src/renderer"; import { RendererContext } from "@sc07-canvas/lib/src/renderer/RendererContext"; import { ViewportMoveEvent } from "@sc07-canvas/lib/src/renderer/PanZoom"; import throttle from "lodash.throttle"; import { ICanvasPosition } from "../types"; import { Routes } from "../lib/routes"; export const CanvasWrapper = () => { // to prevent safari from blurring things, use the zoom css property Loading @@ -17,30 +21,37 @@ export const CanvasWrapper = () => { const CanvasInner = () => { const canvasRef = createRef<HTMLCanvasElement>(); const { config } = useAppContext(); const { config, setCanvasPosition } = useAppContext(); const PanZoom = useContext(RendererContext); // const { centerView } = useControls(); // useTransformEffect( // throttle(({ state, instance }) => { // const params = new URLSearchParams(); // params.set("x", state.positionX + ""); // params.set("y", state.positionY + ""); // params.set("zoom", state.scale + ""); // window.location.hash = params.toString(); // }, 1000) // ); useEffect(() => { if (!config.canvas || !canvasRef.current) return; const canvas = canvasRef.current!; const canvasInstance = new Canvas(config, canvas, PanZoom); // centerView(); const handleViewportMove = throttle((state: ViewportMoveEvent) => { const pos = canvasInstance.panZoomTransformToCanvas(); const canvasPosition: ICanvasPosition = { x: pos.canvasX, y: pos.canvasY, zoom: state.scale >> 0, }; setCanvasPosition(canvasPosition); window.location.replace(Routes.canvas(canvasPosition)); }, 1000); PanZoom.addListener("viewportMove", handleViewportMove); return () => { canvasInstance.destroy(); PanZoom.removeListener("viewportMove", handleViewportMove); }; }, [canvasRef, config]); }, [PanZoom, canvasRef, config, setCanvasPosition]); return ( <canvas Loading
packages/client-next/src/components/Pallete.tsx +9 −0 Original line number Diff line number Diff line Loading @@ -68,8 +68,17 @@ export const Pallete = () => { }; export const CanvasMeta = () => { const { canvasPosition } = useAppContext(); return ( <div id="canvas-meta"> {canvasPosition && ( <span> <button className="btn-link"> ({canvasPosition.x}, {canvasPosition.y}) </button> </span> )} <span> Pixels: <span>123</span> </span> Loading
packages/client-next/src/contexts/AppContext.tsx +10 −2 Original line number Diff line number Diff line Loading @@ -6,7 +6,12 @@ import React, { useState, } from "react"; import { Socket } from "socket.io-client"; import { ClientConfig, IAppContext, IPalleteContext } from "../types"; import { ClientConfig, IAppContext, ICanvasPosition, IPalleteContext, } from "../types"; import { AuthSession } from "@sc07-canvas/lib/src/net"; import { number } from "prop-types"; import Network from "../lib/network"; Loading @@ -18,6 +23,7 @@ export const useAppContext = () => useContext(appContext); export const AppContext = ({ children }: PropsWithChildren) => { const [config, setConfig] = useState<ClientConfig>(undefined as any); const [auth, setAuth] = useState<AuthSession>(); const [canvasPosition, setCanvasPosition] = useState<ICanvasPosition>(); useEffect(() => { function handleConfig(config: ClientConfig) { Loading @@ -41,7 +47,9 @@ export const AppContext = ({ children }: PropsWithChildren) => { }, []); return ( <appContext.Provider value={{ config, user: auth }}> <appContext.Provider value={{ config, user: auth, canvasPosition, setCanvasPosition }} > {config ? children : "Loading..."} </appContext.Provider> ); Loading
packages/client-next/src/lib/canvas.ts +40 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,46 @@ export class Canvas extends EventEmitter { }); } panZoomTransformToCanvas() { const { x, y, scale: zoom } = this.PanZoom.transform; const rect = this.canvas.getBoundingClientRect(); let canvasX = 0; let canvasY = 0; if (this.PanZoom.flags.useZoom) { // css zoom doesn't change the bounding client rect // therefore dividing by zoom doesn't return the correct output canvasX = this.canvas.width - (x + rect.width / 2); canvasY = this.canvas.height - (y + rect.height / 2); } else { canvasX = this.canvas.width / 2 - (x + rect.width / zoom); canvasY = this.canvas.height / 2 - (y + rect.height / zoom); canvasX += this.canvas.width; canvasY += this.canvas.height; } canvasX >>= 0; canvasY >>= 0; return { canvasX, canvasY }; } debug(x: number, y: number, id?: string) { if (document.getElementById("debug-" + id)) { document.getElementById("debug-" + id)!.style.top = y + "px"; document.getElementById("debug-" + id)!.style.left = x + "px"; return; } let el = document.createElement("div"); if (id) el.id = "debug-" + id; el.classList.add("debug-point"); el.style.setProperty("top", y + "px"); el.style.setProperty("left", x + "px"); document.body.appendChild(el); } screenToPos(x: number, y: number) { // the rendered dimentions in the browser const rect = this.canvas.getBoundingClientRect(); Loading
packages/client-next/src/lib/routes.ts 0 → 100644 +12 −0 Original line number Diff line number Diff line import { ICanvasPosition } from "../types"; export const Routes = { canvas: (pos: ICanvasPosition) => { const params = new URLSearchParams(); params.set("x", pos.x + ""); params.set("y", pos.y + ""); params.set("zoom", pos.zoom + ""); return "/#" + params; }, };