javascriptreactjscanvasfabricjsfabricjs2

Implementation of fabric.js in react


I am trying to implement fabric.js in react. I have js code of drawing line using fabric.js and I want to convert it into react code. can anyone help me here is my js code. It is running fine in pure js but not react.;

         let canvas = new fabric.Canvas("canvas", {
             width: 600,
             height: 400,
             backgroundColor: "#808080"
            });
        
        let lineBtn = document.getElementById("adding-line");
        let newLineCoor = {};
        let line;
        let isMouseDown = false;
        let addingLineBtnClicked = false;
        
        const activateAddingLine = () => {
          if (addingLineBtnClicked === false) {
            addingLineBtnClicked = true;
            canvas.on("mouse:down", startAddingLine);
            canvas.on("mouse:move", startDrawingLine);
            canvas.on("mouse:up", stopDrawingLine);
            canvas.selection = false;
            // canvas.defaultCursor = "auto";
            canvas.hoverCursor = "auto";
            canvas.getObjects().forEach((element) => {
              if (element.id === "added-line") {
                element.set({
                  selectable: false
                });
              }
            });
          }
        };
        
        lineBtn.addEventListener("click", activateAddingLine);
        
        const startAddingLine = (o) => {
          isMouseDown = true;
          let pointer = canvas.getPointer(o.e);
          line = new fabric.Line([pointer.x, pointer.y, pointer.x, pointer.y], {
            id: "added-line",
            stroke: "red",
            strokeWidth: 3,
            selectable: false
          });
          canvas.add(line);
          canvas.requestRenderAll();
        };
        
        const startDrawingLine = (o) => {
          if (isMouseDown === true) {
            let pointer = canvas.getPointer(o.e);
            line.set({
              x2: pointer.x,
              y2: pointer.y
            });
            canvas.requestRenderAll();
          }
        };
        
        const stopDrawingLine = () => {
          line.setCoords();
          isMouseDown = false;
        };
        
        const deactiveLine = () => {
          canvas.off("mouse:down", startAddingLine);
          canvas.off("mouse:move", startDrawingLine);
          canvas.off("mouse:up", stopDrawingLine);
          canvas.getObjects().forEach((element) => {
            if (element.id === "added-line") {
              element.set({
                selectable: true
              });
            }
          });
          canvas.hoverCursor = "all-scroll";
          addingLineBtnClicked = false;
        };
        
        document
          .getElementById("deactivate-line")
          .addEventListener("click", deactiveLine);
        const addingControlPoints = (o) => {
          let obj = o.target;
          if (!obj) {
            return;
          }
          let pointer1 = new fabric.Circle({
            radius: obj.strokeWidth * 2,
            fill: "blue",
            opacity: 0.7,
            top: newLineCoor.y1,
            left: newLineCoor.x1,
            originX: "center",
            originY: "center"
          });
        
          let pointer2 = new fabric.Circle({
            radius: obj.strokeWidth * 2,
            fill: "blue",
            opacity: 0.7,
            top: newLineCoor.y2,
            left: newLineCoor.x2,
            originX: "center",
            originY: "center"
          });
          canvas.add(pointer1, pointer2);
          canvas.requestRenderAll();
        };
        const updateNewLineCoordinate = (o) => {
          let obj = o.target;
        
          let centerX = obj.getCenterPoint().x;
          let centerY = obj.getCenterPoint().y;
        
          let x1Offset = obj.calcLinePoint().x1;
          let y1Offset = obj.calcLinePoint().y1;
          let x2Offset = obj.calcLinePoint().x2;
          let y2Offset = obj.calcLinePoint().y2;
          newLineCoor = {
            x1: centerX + x1Offset,
            y1: centerY + y1Offset,
            x2: centerX + x2Offset,
            y2: centerX + y2Offset
          };
        };
        
        canvas.on("mouse:dblclick", addingControlPoints);
        canvas.on("object:moved", updateNewLineCoordinate);

Problem in react implementation that I am maintain state of each variables but I cant draw on canvas


Solution

  • It is working now. But need improvement

       // ! Adding Shape tools
          const [openShapeTool, setOpenShapeTool] = useState(false);
        
          // * line func
          let line;
          const [addLine, setAddLine] = useState(false);
          
          // const [isMouseDown, setIsMouseDown] = useState(false);
          let isMouseDown = false;
        
          const handleDrawLine = () => {
            if (addLine === false) {
              setAddLine(true)
            }
          }
        
          const startAddingLine = (o) => {
            isMouseDown = true
            let pointer = canvas.getPointer(o.e);
            line = new fabric.Line([pointer.x, pointer.y, pointer.x, pointer.y], {
              id: "added-line",
              stroke: "red",
              strokeWidth: 3,
              selectable: false
            });
            canvas.add(line); 
            canvas.renderAll();
          }
        
        
          const startDrawingLine = (o) => {
            if(isMouseDown){
              let pointer = canvas.getPointer(o.e);
            line?.set({
              x2: pointer.x,
              y2: pointer.y
            });
            canvas.renderAll();
            }
          }
        
         
          const stopDrawingLine = () => {
            console.log('stop')
            line.setCoords();
            isMouseDown = false
          }
        
         
        
          useEffect(() => {
            if (addLine) {
              canvas.on("mouse:down", startAddingLine);
              canvas.on("mouse:move", startDrawingLine);
              canvas.on("mouse:up", stopDrawingLine);
              canvas.selection = false;
              canvas.hoverCursor = "auto";
              canvas.getObjects().forEach((element) => {
                if (element.id === "added-line") {
                  element.set({
                    selectable: false
                  });
                }
              });
            }
          }, [addLine])