React + Fabric.js

Sew*_*iak 6 fabricjs reactjs

我正在尝试将 React 和 FabricJ 结合起来,但我陷入了困境。

这是我的代码

import React, { useState, useEffect, useRef  } from 'react';
import { fabric } from "fabric";

function App() {

  const [canvas, setCanvas] = useState('');

  useEffect(() => {
    setCanvas(initCanvas());
    
  }, []);

  const initCanvas = () => (
    new fabric.Canvas('canvas', {
      height: 800,
      width: 800,
      backgroundColor: 'pink' ,
      selection: false,
      renderOnAddRemove: true,
     
    })

  )

    canvas.on("mouse:over", ()=>{
      console.log('hello')
    })


  return (

    <div >
      <canvas id="canvas" />
    </div>

  );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

问题是 canvas.on,因为它会导致错误“未捕获的类型错误:canvas.on 不是函数”请告诉我我在这里做错了什么

Luk*_*xim 7

实际上问题是你试图在它是(初始状态)canvas.on中的空字符串时调用canvas

由于我们只需要创建fabric.Canvas一次,我建议将实例存储为React.useRef

我在这里为您创建了一个示例:

--> https://codesandbox.io/s/late-cloud-ed5r6q?file=/src/FabricExample.js

还将在此处显示示例组件的来源:

import React from "react";
import { fabric } from "fabric";

const FabricExample = () => {
  const fabricRef = React.useRef(null);
  const canvasRef = React.useRef(null);

  React.useEffect(() => {
    const initFabric = () => {
      fabricRef.current = new fabric.Canvas(canvasRef.current);
    };

    const addRectangle = () => {
      const rect = new fabric.Rect({
        top: 50,
        left: 50,
        width: 50,
        height: 50,
        fill: "red"
      });

      fabricRef.current.add(rect);
    };

    const disposeFabric = () => {
      fabricRef.current.dispose();
    };

    initFabric();
    addRectangle();

    return () => {
      disposeFabric();
    };
  }, []);

  return <canvas ref={canvasRef} />;
};

export default FabricExample;

Run Code Online (Sandbox Code Playgroud)


sha*_*sup 3

在初始渲染期间,您的canvas变量被设置为初始状态,''useState(''). 直到此之后您useEffect才会运行并更新状态值。

建议:将事件处理程序移至 useEffect 中,并使用ref画布值的替代状态。refs 具有直接可变的属性,并且不需要重新渲染即可使用它们的新值。

import React, { useState, useEffect, useRef  } from 'react';
import { fabric } from "fabric";

function App() {

  const canvas = useRef(null);

  useEffect(() => {
    canvas.current = initCanvas();

    canvas.current.on("mouse:over", () => {
      console.log('hello')
    });
    
    // destroy fabric on unmount
    return () => {
      canvas.current.dispose();
      canvas.current = null;
    };
  }, []);

  const initCanvas = () => (
    new fabric.Canvas('canvas', {
      height: 800,
      width: 800,
      backgroundColor: 'pink' ,
      selection: false,
      renderOnAddRemove: true,
    })
  );

  return (

    <div >
      <canvas ref={canvas} />
    </div>

  );
}

export default App;
Run Code Online (Sandbox Code Playgroud)

值得注意的是,如果您不需要组件中其他地方的画布引用,则不需要使用状态或引用,并且可以在useEffect.

useEffect(() => {
  const canvas = initCanvas();
  canvas.on("mouse:over", () => {
    console.log('hello')
  });

  // destroy fabric on unmount
  return () => {
    canvas.dispose();
  };
})
Run Code Online (Sandbox Code Playgroud)