Skip to content

Instantly share code, notes, and snippets.

@anlisha-maharjan
Last active June 11, 2022 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anlisha-maharjan/187755ed07a75f39074cb2aad83275d8 to your computer and use it in GitHub Desktop.
Save anlisha-maharjan/187755ed07a75f39074cb2aad83275d8 to your computer and use it in GitHub Desktop.
Initialize fabric.Canvas and Draw bounding box with canvas mouse events.
import React, { useEffect, useState } from "react";
import Camera from "react-html5-camera-photo";
import "react-html5-camera-photo/build/css/index.css";
import { fabric } from "fabric";
function App() {
const [canvas, setCanvas] = useState("");
const [image_width, setImageWidth] = useState(768);
const [image_height, setImageHeight] = useState(580);
const [bbox_center_x, setBboxCenterX] = useState(null);
const [bbox_center_y, setBboxCenterY] = useState(null);
const [bbox_width, setBboxWidth] = useState(null);
const [bbox_height, setBboxHeight] = useState(null);
console.log(
"boundingBox",
bbox_center_x,
bbox_center_y,
bbox_width,
bbox_height
);
const initCanvas = () =>
new fabric.Canvas("fabricEl", {
selection: false,
stateful: true,
});
useEffect(() => {
setCanvas(initCanvas());
}, []);
useEffect(() => {
if (canvas) {
var rectangle, startX, startY, flag;
canvas.setDimensions(
{
width: "100%",
height: "100%",
},
{
cssOnly: true,
}
);
canvas.on("mouse:down", function (e) {
if (canvas.getObjects().length === 0) {
flag = true;
var pointer = canvas.getPointer(e.e);
startX = pointer.x;
startY = pointer.y;
rectangle = new fabric.Rect({
id: 1,
top: startY,
left: startX,
width: 0,
height: 0,
originX: "left",
originY: "top",
fill: "rgba(255,0,0,0.3)",
stroke: "rgba(255,0,0,1)",
strokeWidth: 2,
hasControls: true,
hasRotatingPoint: true,
hasBorders: true,
transparentCorners: false,
selectable: true,
cornerSize: 10,
cornerColor: "rgba(255,0,0,1)",
borderColor: "rgba(255,0,0,1)",
cornerStrokeColor: "rgba(255,0,0,1)",
cornerStyle: "rect",
});
canvas.add(rectangle);
canvas.on("mouse:move", function (e) {
if (!flag) {
return;
}
var pointer = canvas.getPointer(e.e);
if (startX > pointer.x) {
rectangle.set({ left: Math.abs(pointer.x) });
}
if (startY > pointer.y) {
rectangle.set({ top: Math.abs(pointer.y) });
}
rectangle.set({ width: Math.abs(startX - pointer.x) });
rectangle.set({ height: Math.abs(startY - pointer.y) });
rectangle.setCoords();
canvas.renderAll();
});
}
});
canvas.on("mouse:up", function (e) {
flag = false;
canvas.forEachObject(function (obj) {
var rect = obj.getBoundingRect();
setBboxWidth(rect.width / image_width);
setBboxHeight(rect.height / image_height);
setBboxCenterX((rect.width / 2 + rect.left) / image_width);
setBboxCenterY((rect.height / 2 + rect.top) / image_height);
});
canvas.off("mouse:down");
canvas.off("mouse:up");
canvas.off("mouse:move");
});
canvas.on("object:moving", function (e) {
var obj = e.target;
// if object is too big ignore
if (
obj.currentHeight > obj.canvas.height ||
obj.currentWidth > obj.canvas.width
) {
return;
}
obj.setCoords();
// top-left corner
if (obj.getBoundingRect().top < 0 || obj.getBoundingRect().left < 0) {
obj.top = Math.max(obj.top, obj.top - obj.getBoundingRect().top);
obj.left = Math.max(obj.left, obj.left - obj.getBoundingRect().left);
}
// bot-right corner
if (
obj.getBoundingRect().top + obj.getBoundingRect().height >
obj.canvas.height ||
obj.getBoundingRect().left + obj.getBoundingRect().width >
obj.canvas.width
) {
obj.top = Math.min(
obj.top,
obj.canvas.height -
obj.getBoundingRect().height +
obj.top -
obj.getBoundingRect().top
);
obj.left = Math.min(
obj.left,
obj.canvas.width -
obj.getBoundingRect().width +
obj.left -
obj.getBoundingRect().left
);
}
});
canvas.on("object:modified", function (e) {
var obj = e.target;
var rect = obj.getBoundingRect();
if (
rect.left < 0 ||
rect.top < 0 ||
rect.left + rect.width > obj.canvas.width ||
rect.top + rect.height > obj.canvas.height
) {
obj.top = obj._stateProperties.top;
obj.left = obj._stateProperties.left;
obj.angle = obj._stateProperties.angle;
obj.scaleX = obj._stateProperties.scaleX;
obj.scaleY = obj._stateProperties.scaleY;
obj.setCoords();
obj.saveState();
} else {
setBboxWidth(rect.width / image_width);
setBboxHeight(rect.height / image_height);
setBboxCenterX((rect.width / 2 + rect.left) / image_width);
setBboxCenterY((rect.height / 2 + rect.top) / image_height);
}
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [canvas]);
return (
<>
<h1 style={{ textAlign: "center", marginTop: "5rem" }}>
Draw Bounding Box over camera using Fabric.js
</h1>
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
padding: "3rem",
}}
>
<div style={{ position: "relative" }}>
<Camera onTakePhoto={(uri) => {}} isImageMirror={false} />
<div
style={{
position: "absolute",
top: 0,
left: 0,
zIndex: 9999,
width: "100%",
height: "100%",
}}
>
<canvas id="fabricEl" width="768" height="580"></canvas>
</div>
</div>
</div>
</>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment