import React from "react" import * as fabric from 'fabric' import { FullscreenOutlined } from "@ant-design/icons" import { Button, Tooltip } from "antd" /** * @deprecated - Fabric.js cannot be used as its limited to drawing, elements cannot be added to canvas */ class Canvas extends React.Component { constructor(props) { super(props) /** @type {fabric.Canvas | null} */ this.fabricCanvas = null this.canvasRef = React.createRef() this.mousePressed = false this.mousePos = { startX: 0, startY: 0 } this.modes = { DEFAULT: '', PAN: 'pan', } this.currentMode = this.modes.DEFAULT this.updateCanvasDimensions = this.updateCanvasDimensions.bind(this) } componentDidMount() { this.initCanvas() window.addEventListener("resize", this.updateCanvasDimensions) this.updateCanvasDimensions() } componentWillUnmount() { this.fabricCanvas.clear() this.fabricCanvas.dispose() window.removeEventListener("resize", this.updateCanvasDimensions) } updateCanvasDimensions() { if (!this.canvasRef.current || !this.fabricCanvas) return const parent = this.canvasRef.current.parentNode.parentNode // Get the outer container this.fabricCanvas.setDimensions({ width: parent.clientWidth, height: parent.clientHeight }) this.fabricCanvas.calcOffset() this.fabricCanvas.renderAll() } initCanvas(){ this.fabricCanvas = new fabric.Canvas(this.canvasRef.current, { selection: false, }) this.fabricCanvas.hoverCursor = this.fabricCanvas.moveCursor = 'pointer' const rect = new fabric.Rect({ left: 100, top: 100, fill: 'red', width: 200, height: 100, angle: 0 }) this.fabricCanvas.add(rect) fabric.FabricImage.fromURL("https://images.unsplash.com/photo-1722898614949-c9a315e35209?q=80&w=1974&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D").then((img) => { img.scale(0.2) this.fabricCanvas.add(img) }) // this.fabricCanvas.renderAll() this.initEvents() } initEvents(){ this.fabricCanvas.on("mouse:down", (event) => { this.mousePressed = true if (this.fabricCanvas.getActiveObjects().length === 0){ this.currentMode = this.modes.PAN } this.mousePos.startX = event.e.clientX this.mousePos.startY = event.e.clientY this.fabricCanvas.setCursor("grab") }) this.fabricCanvas.on("mouse:up", () => { this.mousePressed = false this.fabricCanvas.setCursor("default") }) this.fabricCanvas.on("mouse:move", (event) => { if (event.e.buttons === 1 && this.currentMode === this.modes.PAN){ this.fabricCanvas.setCursor("grab") // TODO: add panning limits const deltaX = event.e.clientX - this.mousePos.startX const deltaY = event.e.clientY - this.mousePos.startY this.fabricCanvas.relativePan({ x: deltaX, y: deltaY }) this.mousePos.startX = event.e.clientX this.mousePos.startY = event.e.clientY } }) this.fabricCanvas.on("selection:created", () => { console.log("selected") this.currentMode = this.modes.DEFAULT }) this.fabricCanvas.on('mouse:wheel', (opt) => { // console.log("opt: ", opt) let delta = opt.e.deltaY let zoom = this.fabricCanvas.getZoom() zoom *= 0.999 ** delta if (zoom > 20) zoom = 20 if (zoom < 0.01) zoom = 0.01 this.fabricCanvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom) opt.e.preventDefault() opt.e.stopPropagation() }) } getCanvasObjectsBoundingBox(padding = 0) { const objects = this.fabricCanvas.getObjects() if (objects.length === 0) { return { left: 0, top: 0, width: this.fabricCanvas.width, height: this.fabricCanvas.height } } const boundingBox = objects.reduce((acc, obj) => { const objBoundingBox = obj.getBoundingRect(true) acc.left = Math.min(acc.left, objBoundingBox.left) acc.top = Math.min(acc.top, objBoundingBox.top) acc.right = Math.max(acc.right, objBoundingBox.left + objBoundingBox.width) acc.bottom = Math.max(acc.bottom, objBoundingBox.top + objBoundingBox.height) return acc }, { left: Infinity, top: Infinity, right: -Infinity, bottom: -Infinity }) // Adding padding boundingBox.left -= padding boundingBox.top -= padding boundingBox.right += padding boundingBox.bottom += padding return { left: boundingBox.left, top: boundingBox.top, width: boundingBox.right - boundingBox.left, height: boundingBox.bottom - boundingBox.top } } resetZoom(){ this.fabricCanvas.setViewportTransform([1,0,0,1,0,0]) } resetPan(){ this.fabricCanvas.setViewportTransform([1,0,0,1,0,0]) } render() { return (