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