Commit 45defd0a authored by Grant's avatar Grant
Browse files

viewport coordinate system

parent f396b4a1
Loading
Loading
Loading
Loading
+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
@@ -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
+9 −0
Original line number Diff line number Diff line
@@ -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>
+10 −2
Original line number Diff line number Diff line
@@ -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";
@@ -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) {
@@ -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>
  );
+40 −0
Original line number Diff line number Diff line
@@ -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();
+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