1

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

2 Answers2

0

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])
0

Just do it with react-fabricJS npm.

https://www.npmjs.com/package/fabricjs-react

ruckie
  • 149
  • 14