当我从 JSON 加载 Fabric.js 画布元素时,它们在画布上不可见

问题描述 投票:0回答:1

在我的应用程序中,我想在全屏和页内模式之间保持画布的状态。现在,我正在尝试通过在画布上下文中以 JSON 格式保存画布对象来实现此目的。切换模式时,会创建一个新的画布实例,然后我将 JSON 中的对象加载到该新的画布实例中。

问题是对象没有显示出来。当我在执行此 JSON 加载后记录画布实例的对象时,我可以看到它们存在于画布中。然而,当我查看页面时,它们在画布上根本不可见。

我加载的 JSON 错误吗?新画布的大小可能与旧画布不同,但这并不是对象被拉伸或扭曲,它们只是不存在。即使当我切换回旧的画布尺寸时,也看不到任何东西。

文档没有提到这一点,而且我没有发现其他人有这个问题。

以下是我的代码,仅限于与问题相关的内容。

我在加载 JSON 元素后立即渲染画布。

import { useCanvas } from "@/contexts/CanvasContext";
import React, { useEffect, useRef, useState } from "react";

declare global {
  interface Window {
    fabric: any;
  }
}

type FabricCanvasProps = {
  dimensions: { width: number; height: number };
  canvasInstance: any;
  setCanvasInstance: (canvasInstance: any) => void;
};

const FabricCanvas: React.FC<FabricCanvasProps> = ({
  dimensions,
  canvasInstance,
  setCanvasInstance,
}) => {
  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const [prevDimensions, setPrevDimensions] = useState({ width: 0, height: 0 });

  const {
    activeTool,
    setIsDrawnOn,

    canvasData,
    setCanvasData,
  } = useCanvas();

  useEffect(() => {
    const fabricScriptLoaded = () => !!window.fabric;

    if (canvasRef.current && !canvasInstance && fabricScriptLoaded()) {
      const instance = new window.fabric.Canvas(canvasRef.current, {
        isDrawingMode: activeTool !== null,
        height: dimensions.height,
        width: dimensions.width,
        selection: false,
      });

      if (canvasData) {
        instance.loadFromJSON(canvasData, instance.renderAll.bind(instance));
        console.log(canvasData);
        console.log(instance.getObjects());
      }

      // Listen for changes to the canvas
      const updateDrawnState = () => {
        setIsDrawnOn(true);
      };

      instance.on("object:added", updateDrawnState);
      instance.on("object:modified", updateDrawnState);

      setCanvasInstance(instance);
    }
  }, []); // Initializes the canvas instance only once

  // Updates the context with most recent canvas data for re-rendering
  useEffect(() => {
    if (canvasInstance) {
      // Listen for any change that should update the canvas data
      const onChange = () => {
        setCanvasData(canvasInstance.toJSON());
      };

      canvasInstance.on("object:added", onChange);
      canvasInstance.on("object:modified", onChange);
      canvasInstance.on("object:removed", onChange);

      return () => {
        canvasInstance.off("object:added", onChange);
        canvasInstance.off("object:modified", onChange);
        canvasInstance.off("object:removed", onChange);
      };
    }
  }, [canvasInstance]);

// ... Some more useEffects that have to do with canvas size


  return (
    <>
      <canvas ref={canvasRef} className="w-full h-full" />
    </>
  );
};

export default FabricCanvas;

reactjs typescript fabricjs next.js13
1个回答
0
投票

我最终发现了这一点:它实际上确实与我认为无关的画布更新有关。我使用以下代码随着页面大小的变化调整画布内对象的大小:

  const scaleX = dimensions.width / prevDimensions.width;
  const scaleY = dimensions.height / prevDimensions.height;

  canvasInstance.getObjects().forEach((obj: any) => {
    obj.scaleX *= scaleX;
    obj.scaleY *= scaleY;
    obj.left *= scaleX;
    obj.top *= scaleY;
    obj.setCoords();
  }

但是当组件最初渲染时,我的 prevDimensions 为 0。这导致对象缩放到无限大小,同时不会抛出任何错误或指示出现问题,因此我看不到它们。

我通过添加检查来修复此问题,以确保此处不会发生除以 0 的情况。

© www.soinside.com 2019 - 2024. All rights reserved.