Compare commits
13 Commits
34e5d40cae
...
2100daadeb
| Author | SHA1 | Date | |
|---|---|---|---|
| 2100daadeb | |||
| 046280e25c | |||
| 8bcd4a014c | |||
| 5843ffdc9b | |||
| ab2f477b7f | |||
| 0496a48623 | |||
| e089dfabec | |||
| 4904f4d66a | |||
| 9936cd0ffc | |||
| e3e95fd05f | |||
| 3e3ea34e5f | |||
| 00f9c602af | |||
| 9ada6f005f |
@@ -5,13 +5,13 @@ import { fabric } from "fabric";
|
||||
import {
|
||||
GrayMaterial,
|
||||
PerforatedMaterial,
|
||||
WoodgrainMaterial
|
||||
WoodgrainMaterial,
|
||||
} from "Assets/images";
|
||||
import {
|
||||
DockPanelCategories,
|
||||
MaterialType,
|
||||
DockPanelCategoryMap,
|
||||
CylinderType
|
||||
CylinderType,
|
||||
} from "Utils/constants";
|
||||
import { Chevron } from "Assets/svgs";
|
||||
import MkdSDK from "Utils/MkdSDK";
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
getMaterial,
|
||||
getRampsCategory,
|
||||
getWedgesAndRampsMaterial,
|
||||
getWedgesCategory
|
||||
getWedgesCategory,
|
||||
} from "Utils/utils";
|
||||
|
||||
const sdk = new MkdSDK();
|
||||
@@ -32,7 +32,7 @@ export const Builder = ({ editor }) => {
|
||||
DockPanelCategories.RollIn
|
||||
);
|
||||
const rampsInitialState = {
|
||||
data: []
|
||||
data: [],
|
||||
};
|
||||
// const [ramps, setRamps] = useState(null);
|
||||
const [activeLiftRange, setActiveLiftRange] = useState(null);
|
||||
@@ -44,7 +44,7 @@ export const Builder = ({ editor }) => {
|
||||
wedges: [],
|
||||
ramps: [],
|
||||
selectedRamps: [],
|
||||
selectedWedges: []
|
||||
selectedWedges: [],
|
||||
});
|
||||
const [boatLift, setBoatLift] = useState([]);
|
||||
const [liftRanges, setLiftRanges] = useState([]);
|
||||
@@ -60,7 +60,8 @@ export const Builder = ({ editor }) => {
|
||||
[activeMaterial]
|
||||
);
|
||||
|
||||
const onDockSelect = useCallback((dock) => {
|
||||
const onDockSelect = useCallback(
|
||||
(dock) => {
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
@@ -72,7 +73,6 @@ export const Builder = ({ editor }) => {
|
||||
let category;
|
||||
if (["wedges", "ramps"].includes(dock?.type)) {
|
||||
imageTopViewURL = (dock?.top_view).replace("%20", "+");
|
||||
|
||||
materials = getWedgesAndRampsMaterial(dock?.material);
|
||||
} else {
|
||||
imageTopViewURL = dock?.top_view;
|
||||
@@ -100,16 +100,40 @@ export const Builder = ({ editor }) => {
|
||||
no_of_cylinders: dock?.no_of_cylinders,
|
||||
name: dock?.name,
|
||||
thumbnail: dock?.thumbnail,
|
||||
weight_capacity: dock?.weight_capacity
|
||||
weight_capacity: dock?.weight_capacity,
|
||||
};
|
||||
|
||||
// TODO: Add dock to editor
|
||||
// TODO: object which is the image should have the dockData, snapAngle of 45, snapThreshold of 5
|
||||
// TODO: image should be scaled down by scaleFactor
|
||||
// TODO: image should be positioned at the top left of the editor
|
||||
// TODO: image should be added to the editor
|
||||
// TODO: render the editor
|
||||
}, []);
|
||||
// Add dock to editor as an image
|
||||
const imageUrl = imageTopViewURL || dock?.image || dock?.thumbnail;
|
||||
|
||||
if (!imageUrl) return;
|
||||
|
||||
// Add dock to editor
|
||||
fabric.Image.fromURL(
|
||||
imageUrl,
|
||||
function (img) {
|
||||
img.set({
|
||||
left: 300, //To prevent appearing behind the sidebar
|
||||
top: 0,
|
||||
scaleX: scaleFactor,
|
||||
scaleY: scaleFactor,
|
||||
snapAngle: 45, // TODO: snapAngle
|
||||
snapThreshold: 5, // TODO: snapThreshold
|
||||
dockData: dockData, // TODO: attach dockData
|
||||
selectable: true,
|
||||
hasControls: true,
|
||||
});
|
||||
|
||||
// Add to editor and make active
|
||||
editor.add(img); // TODO: add to editor
|
||||
editor.setActiveObject(img);
|
||||
editor.requestRenderAll(); // TODO: render editor
|
||||
},
|
||||
{ crossOrigin: "anonymous" }
|
||||
);
|
||||
},
|
||||
[editor, activeDockCategory]
|
||||
);
|
||||
|
||||
const getItems = useCallback((table) => {
|
||||
// console.log( category, materials );
|
||||
@@ -145,8 +169,8 @@ export const Builder = ({ editor }) => {
|
||||
? [
|
||||
...result?.model.map((item) => ({
|
||||
...item,
|
||||
type: "boatlifts"
|
||||
}))
|
||||
type: "boatlifts",
|
||||
})),
|
||||
]
|
||||
: []
|
||||
);
|
||||
@@ -158,8 +182,8 @@ export const Builder = ({ editor }) => {
|
||||
? [
|
||||
...result?.model.map((item) => ({
|
||||
...item,
|
||||
type: "accessories"
|
||||
}))
|
||||
type: "accessories",
|
||||
})),
|
||||
]
|
||||
: []
|
||||
);
|
||||
@@ -171,10 +195,10 @@ export const Builder = ({ editor }) => {
|
||||
? [
|
||||
...result?.model.map((item) => ({
|
||||
...item,
|
||||
type: "wedges"
|
||||
}))
|
||||
type: "wedges",
|
||||
})),
|
||||
]
|
||||
: []
|
||||
: [],
|
||||
}));
|
||||
case Tables.Ramps:
|
||||
// return console.log( result )
|
||||
@@ -182,7 +206,7 @@ export const Builder = ({ editor }) => {
|
||||
...prev,
|
||||
ramps: result?.model
|
||||
? [...result?.model.map((item) => ({ ...item, type: "ramps" }))]
|
||||
: []
|
||||
: [],
|
||||
}));
|
||||
// return setRamps(() => [...result?.model]);
|
||||
}
|
||||
@@ -231,7 +255,7 @@ export const Builder = ({ editor }) => {
|
||||
[
|
||||
DockPanelCategories.RollIn,
|
||||
DockPanelCategories.Floating,
|
||||
DockPanelCategories.Sectional
|
||||
DockPanelCategories.Sectional,
|
||||
].includes(activeDockCategory)
|
||||
) {
|
||||
// console.log( activeDockCategory, activeMaterial )
|
||||
@@ -296,7 +320,7 @@ export const Builder = ({ editor }) => {
|
||||
: "bg-gray-200"
|
||||
}`}
|
||||
>
|
||||
<img className={`rounded-md`} src={GrayMaterial} alt="GreyMaterial" />
|
||||
<img className={`rounded-md`} src={GrayMaterial} alt='GreyMaterial' />
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -311,7 +335,7 @@ export const Builder = ({ editor }) => {
|
||||
<img
|
||||
className={`rounded-md`}
|
||||
src={PerforatedMaterial}
|
||||
alt="PerforatedMaterial"
|
||||
alt='PerforatedMaterial'
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -327,7 +351,7 @@ export const Builder = ({ editor }) => {
|
||||
<img
|
||||
className={`rounded-md`}
|
||||
src={WoodgrainMaterial}
|
||||
alt="WoodgrainMaterial"
|
||||
alt='WoodgrainMaterial'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -353,7 +377,7 @@ export const Builder = ({ editor }) => {
|
||||
>
|
||||
{dock.length ? (
|
||||
<>
|
||||
<img src={dock[0].image} alt="" className={`rounded-md my-2`} />
|
||||
<img src={dock[0].image} alt='' className={`rounded-md my-2`} />
|
||||
<div className={`grid grid-cols-2`}>
|
||||
{dock?.map((dockItem, index) => (
|
||||
<button
|
||||
@@ -397,7 +421,7 @@ export const Builder = ({ editor }) => {
|
||||
>
|
||||
{dock.length ? (
|
||||
<>
|
||||
<img src={dock[0].image} alt="" className={`rounded-md my-2`} />
|
||||
<img src={dock[0].image} alt='' className={`rounded-md my-2`} />
|
||||
<div className={`grid grid-cols-2`}>
|
||||
{dock?.map((dockItem, index) => (
|
||||
<button
|
||||
@@ -441,7 +465,7 @@ export const Builder = ({ editor }) => {
|
||||
>
|
||||
{dock.length ? (
|
||||
<>
|
||||
<img src={dock[0].image} alt="" className={`rounded-md my-2`} />
|
||||
<img src={dock[0].image} alt='' className={`rounded-md my-2`} />
|
||||
<div className={`grid grid-cols-2`}>
|
||||
{dock?.map((dockItem, index) => (
|
||||
<button
|
||||
@@ -484,7 +508,7 @@ export const Builder = ({ editor }) => {
|
||||
<>
|
||||
<img
|
||||
src={wedgesAndRamps?.wedges[0].image}
|
||||
alt=""
|
||||
alt=''
|
||||
className={`rounded-md my-2`}
|
||||
/>
|
||||
<div className={`grid grid-cols-2`}>
|
||||
@@ -532,7 +556,7 @@ export const Builder = ({ editor }) => {
|
||||
<>
|
||||
<img
|
||||
src={wedgesAndRamps.ramps[0].image}
|
||||
alt=""
|
||||
alt=''
|
||||
className={`rounded-md my-2`}
|
||||
/>
|
||||
<div className={`grid grid-cols-2`}>
|
||||
@@ -606,7 +630,7 @@ export const Builder = ({ editor }) => {
|
||||
</div>
|
||||
<img
|
||||
src={boatLift[0].image}
|
||||
alt=""
|
||||
alt=''
|
||||
className={`rounded-md my-2`}
|
||||
/>
|
||||
<div className={`grid grid-cols-2`}>
|
||||
@@ -677,7 +701,7 @@ export const Builder = ({ editor }) => {
|
||||
</div>
|
||||
<img
|
||||
src={boatLift[0].image}
|
||||
alt=""
|
||||
alt=''
|
||||
className={`rounded-md my-2`}
|
||||
/>
|
||||
<div className={`grid grid-cols-2`}>
|
||||
@@ -735,7 +759,7 @@ export const Builder = ({ editor }) => {
|
||||
<span>{ dockItem.length }'</span> */}
|
||||
<img
|
||||
src={dockItem.thumbnail}
|
||||
alt=""
|
||||
alt=''
|
||||
className={`rounded-md `}
|
||||
/>
|
||||
{/* </div> */}
|
||||
|
||||
@@ -4,7 +4,7 @@ import React, {
|
||||
useCallback,
|
||||
useRef,
|
||||
useState,
|
||||
useContext
|
||||
useContext,
|
||||
} from "react";
|
||||
import { FabricJSCanvas, useFabricJSEditor } from "fabricjs-react";
|
||||
import { fabric } from "fabric";
|
||||
@@ -20,7 +20,7 @@ import { clearClone, clone } from "Utils/DockBuilderUtils/clone";
|
||||
import {
|
||||
edgeDetection,
|
||||
handleEdgeDetection,
|
||||
handleIntersection
|
||||
handleIntersection,
|
||||
} from "Utils/DockBuilderUtils";
|
||||
import {
|
||||
CanvasModes,
|
||||
@@ -32,12 +32,12 @@ import {
|
||||
oneFeet,
|
||||
rotateIcon,
|
||||
scaleFactor,
|
||||
twoSeventyDeg
|
||||
twoSeventyDeg,
|
||||
} from "Utils/constants";
|
||||
import {
|
||||
reScaleXY,
|
||||
resolveHeight,
|
||||
resolveWidth
|
||||
resolveWidth,
|
||||
} from "Utils/DockBuilderUtils/edgeDetection";
|
||||
import { DeleteIcon, RotateIcon } from "Assets/svgs";
|
||||
import { capitalize } from "Utils/helper";
|
||||
@@ -90,7 +90,7 @@ export const DockBuilder = () => {
|
||||
const ext = "png";
|
||||
const base64 = editorMemo.toDataURL({
|
||||
format: ext,
|
||||
enableRetinaScaling: true
|
||||
enableRetinaScaling: true,
|
||||
});
|
||||
setDockImage(base64);
|
||||
setShowEstimateModal(true);
|
||||
@@ -103,36 +103,65 @@ export const DockBuilder = () => {
|
||||
// }, [ editor ] );
|
||||
|
||||
const toJSON = () => {
|
||||
// TODO: download the json file
|
||||
// TODO: get json of editor content
|
||||
// TODO: Ensure dockData is included in the json
|
||||
// TODO: save the json to the local storage as dock
|
||||
// TODO: name the file as paradise_dock_<timestamp here>.dock
|
||||
// Get JSON of editor content, including dockData and snapClone
|
||||
const json = editorMemo.toJSON(["dockData", "snapClone"]);
|
||||
const data = JSON.stringify(json, null, 2);
|
||||
// Save to localStorage
|
||||
localStorage.setItem("dock", data);
|
||||
const blob = new Blob([data], { type: "application/json" });
|
||||
const anchor = document.createElement("a");
|
||||
const timestamp = Date.now();
|
||||
anchor.href = URL.createObjectURL(blob);
|
||||
anchor.download = `paradise_dock_${timestamp}.dock`; // TODO: name the file as paradise_dock_<timestamp here>.dock
|
||||
anchor.click();
|
||||
};
|
||||
|
||||
const uploadFile = (e) => {
|
||||
// TODO: Our own upload the file we must have downloaded previously
|
||||
// TODO: extract the json from the file
|
||||
// TODO: load the json to the editor
|
||||
// TODO: render all
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
try {
|
||||
const json = JSON.parse(event.target.result);
|
||||
console.log(json);
|
||||
editorMemo.loadFromJSON(json, () => {
|
||||
editorMemo.renderAll();
|
||||
});
|
||||
} catch (err) {
|
||||
alert("Invalid file format. Please select a valid .dock file.");
|
||||
}
|
||||
};
|
||||
reader.readAsText(file);
|
||||
// Reset file input to allow reupload of the same file
|
||||
e.target.value = "";
|
||||
};
|
||||
|
||||
const downloadImage = useCallback(() => {
|
||||
// // console.log( 'Download' )
|
||||
const ext = "png";
|
||||
// Generate base64 image of the canvas
|
||||
const base64 = editorMemo.toDataURL({
|
||||
format: ext,
|
||||
enableRetinaScaling: true,
|
||||
});
|
||||
// Download the image
|
||||
const anchor = document.createElement("a");
|
||||
const timestamp = Date.now();
|
||||
anchor.href = base64;
|
||||
anchor.download = `paradise_dock_snapshot_${timestamp}.${ext}`;
|
||||
anchor.click();
|
||||
|
||||
// TODO: download the image
|
||||
// TODO: get the json of the editor content
|
||||
// TODO: extract the dockData from the json
|
||||
// TODO: filter the dockData to ensure it does not contain snapClone
|
||||
// TODO: generate the base64 image
|
||||
// TODO: download the image and name it as paradise_dock_snapshot_<timestamp here>.${ext}
|
||||
// TODO: download the excel file of the dockData you extracted
|
||||
|
||||
// TODO: check if dockData is empty
|
||||
// TODO: generate the base64 image
|
||||
|
||||
// TODO: trigger download of the dockData you extracted in excel format
|
||||
// Extract dockData from all objects (excluding snapClone)
|
||||
const json = editorMemo.toJSON(["dockData", "snapClone"]);
|
||||
const dockDataArr = (json.objects || [])
|
||||
.filter((object) => object.dockData && !object.snapClone)
|
||||
.map((object) => object.dockData);
|
||||
if (dockDataArr.length > 0) {
|
||||
// Download as Excel
|
||||
const worksheet = XLSX.utils.json_to_sheet(dockDataArr);
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "Dock Data");
|
||||
XLSX.writeFile(workbook, `paradise_dock_data_${timestamp}.xlsx`);
|
||||
}
|
||||
}, [editorMemo]);
|
||||
|
||||
const renderBg = useCallback(() => {
|
||||
@@ -144,14 +173,14 @@ export const DockBuilder = () => {
|
||||
function (img) {
|
||||
img.set({
|
||||
scaleX: editorMemo.width / img.width,
|
||||
scaleY: editorMemo.height / img.height
|
||||
scaleY: editorMemo.height / img.height,
|
||||
});
|
||||
editorMemo.setBackgroundImage(img);
|
||||
editorMemo.renderAll();
|
||||
// updateModifications( true, )
|
||||
},
|
||||
{
|
||||
crossOrigin: "anonymous"
|
||||
crossOrigin: "anonymous",
|
||||
}
|
||||
);
|
||||
}, [editorMemo]);
|
||||
@@ -195,7 +224,7 @@ export const DockBuilder = () => {
|
||||
onChange: function (value) {
|
||||
editorMemo.zoomToPoint({ x: pointer.x, y: pointer.y }, value);
|
||||
},
|
||||
fps: 1080
|
||||
fps: 1080,
|
||||
});
|
||||
opt.e.preventDefault();
|
||||
opt.e.stopPropagation();
|
||||
@@ -350,12 +379,12 @@ export const DockBuilder = () => {
|
||||
|
||||
let line = new fabric.Line([0, newTop, editorMemo.getWidth(), newTop], {
|
||||
stroke: "#AAAAAA",
|
||||
testLine: true
|
||||
testLine: true,
|
||||
// strokeDashArray: [ 5 ],
|
||||
});
|
||||
let line2 = new fabric.Line([0, objTop, editorMemo.getWidth(), objTop], {
|
||||
stroke: "#AAAAAA",
|
||||
testLine: true
|
||||
testLine: true,
|
||||
// strokeDashArray: [ 5 ],
|
||||
});
|
||||
editorMemo.add(line);
|
||||
@@ -371,12 +400,12 @@ export const DockBuilder = () => {
|
||||
|
||||
let line = new fabric.Line([newLeft, 0, newLeft, editorMemo.getHeight()], {
|
||||
stroke: "#AAAAAA",
|
||||
testLine: true
|
||||
testLine: true,
|
||||
// strokeDashArray: [ 5 ],
|
||||
});
|
||||
let line2 = new fabric.Line([objLeft, 0, objLeft, editorMemo.getWidth()], {
|
||||
stroke: "#AAAAAA",
|
||||
testLine: true
|
||||
testLine: true,
|
||||
// strokeDashArray: [ 5 ],
|
||||
});
|
||||
editorMemo.add(line);
|
||||
@@ -385,14 +414,96 @@ export const DockBuilder = () => {
|
||||
};
|
||||
|
||||
function edgeDetectionAndSnap(options) {
|
||||
if (this.isZoomed) {
|
||||
if (editorMemo.getZoom() !== 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Edge detection and snap to object within snap range
|
||||
// TODO: Detect if the object is within the snap range of the selected object
|
||||
// TODO: detect if the selected object contains dockData and dockData contains itemName of DockPanelCategories.Accessories || DockPanelCategories.BoatLift2 || DockPanelCategories.BoatLift4
|
||||
const selectedObj = options.target;
|
||||
if (!selectedObj.dockData) return;
|
||||
|
||||
// TODO: Detect if the selected object is in the allowed categories
|
||||
const snapCategories = [
|
||||
DockPanelCategories.Accessories,
|
||||
DockPanelCategories.BoatLift2,
|
||||
DockPanelCategories.BoatLift4,
|
||||
];
|
||||
|
||||
if (!snapCategories.includes(selectedObj.dockData.itemName)) return;
|
||||
|
||||
let closestSnapPoint = null;
|
||||
let minDistance = edgeSnapThreshold;
|
||||
|
||||
editorMemo.forEachObject((obj) => {
|
||||
if (obj === selectedObj || !obj.dockData) return;
|
||||
|
||||
// TODO: Only consider objects in the allowed categories
|
||||
if (!snapCategories.includes(obj.dockData.itemName)) return;
|
||||
|
||||
// TODO: handle rotation of 0, 90, 180, 270 degrees
|
||||
const rotation = obj.angle % 360;
|
||||
const isRotated = rotation !== 0 && rotation !== 180;
|
||||
|
||||
const objCenter = obj.getCenterPoint();
|
||||
const selectedCenter = selectedObj.getCenterPoint();
|
||||
|
||||
// Calculate potential snap points
|
||||
const snapPoints = [];
|
||||
|
||||
// Center point
|
||||
snapPoints.push(objCenter);
|
||||
|
||||
// Edge points
|
||||
if (!isRotated || rotation === 0 || rotation === 180) {
|
||||
// Horizontal edges
|
||||
snapPoints.push(
|
||||
new fabric.Point(objCenter.x, obj.getBoundingRect().top)
|
||||
);
|
||||
snapPoints.push(
|
||||
new fabric.Point(
|
||||
objCenter.x,
|
||||
obj.getBoundingRect().top + obj.getBoundingRect().height
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (!isRotated || rotation === 90 || rotation === 270) {
|
||||
// Vertical edges
|
||||
snapPoints.push(
|
||||
new fabric.Point(obj.getBoundingRect().left, objCenter.y)
|
||||
);
|
||||
snapPoints.push(
|
||||
new fabric.Point(
|
||||
obj.getBoundingRect().left + obj.getBoundingRect().width,
|
||||
objCenter.y
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Find closest snap point
|
||||
snapPoints.forEach((point) => {
|
||||
const distance = Math.sqrt(
|
||||
Math.pow(selectedCenter.x - point.x, 2) +
|
||||
Math.pow(selectedCenter.y - point.y, 2)
|
||||
);
|
||||
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance;
|
||||
closestSnapPoint = point;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Snap to closest point if found
|
||||
if (closestSnapPoint) {
|
||||
const selectedCenter = selectedObj.getCenterPoint();
|
||||
selectedObj.set({
|
||||
left: selectedObj.left + (closestSnapPoint.x - selectedCenter.x),
|
||||
top: selectedObj.top + (closestSnapPoint.y - selectedCenter.y),
|
||||
});
|
||||
selectedObj.setCoords();
|
||||
editorMemo.renderAll();
|
||||
}
|
||||
|
||||
editorMemo.defaultCursor = "default";
|
||||
prevPointer = null;
|
||||
@@ -497,30 +608,116 @@ export const DockBuilder = () => {
|
||||
}, [editor, selectedItems]);
|
||||
|
||||
const onUndoClick = useCallback(() => {
|
||||
// TODO: Undo
|
||||
const undoResult = stack.undo();
|
||||
if (undoResult && undoResult.currentState) {
|
||||
editorMemo.loadFromJSON(undoResult.currentState, () => {
|
||||
editorMemo.renderAll();
|
||||
});
|
||||
}
|
||||
}, [editorMemo]);
|
||||
|
||||
const onRedoClick = useCallback(() => {
|
||||
// TODO: Redo
|
||||
const redoResult = stack.redo();
|
||||
if (redoResult && redoResult.currentState) {
|
||||
// currentState is an array, get the first element
|
||||
const state = Array.isArray(redoResult.currentState)
|
||||
? redoResult.currentState[0]
|
||||
: redoResult.currentState;
|
||||
if (state) {
|
||||
editorMemo.loadFromJSON(state, () => {
|
||||
editorMemo.renderAll();
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [editorMemo]);
|
||||
|
||||
const onPrintScreen = useCallback(() => {
|
||||
// convert the canvas to a data url and download it.
|
||||
// TODO: Print screen
|
||||
// TODO: print screen without background image and background color, the background image should be white
|
||||
// TODO: after printing, the background image and background color should be restored
|
||||
// Save current background
|
||||
const originalBgColor = editorMemo.backgroundColor;
|
||||
const originalBgImage = editorMemo.backgroundImage;
|
||||
|
||||
// Set background to white for printing
|
||||
editorMemo.setBackgroundColor(
|
||||
"#fff",
|
||||
editorMemo.renderAll.bind(editorMemo)
|
||||
);
|
||||
editorMemo.setBackgroundImage(null, editorMemo.renderAll.bind(editorMemo));
|
||||
|
||||
// Give time for background to update
|
||||
setTimeout(() => {
|
||||
const dataUrl = editorMemo.toDataURL({
|
||||
format: "png",
|
||||
enableRetinaScaling: true,
|
||||
});
|
||||
const printWindow = window.open("", "_blank");
|
||||
if (printWindow) {
|
||||
printWindow.document.write(
|
||||
'<html><head><title>Print Canvas</title></head><body style="margin:0"><img src="' +
|
||||
dataUrl +
|
||||
'" style="width:100vw;max-width:100%"/></body></html>'
|
||||
);
|
||||
printWindow.document.close();
|
||||
printWindow.focus();
|
||||
printWindow.onload = function () {
|
||||
printWindow.print();
|
||||
printWindow.close();
|
||||
};
|
||||
}
|
||||
// Restore original background
|
||||
editorMemo.setBackgroundColor(
|
||||
originalBgColor,
|
||||
editorMemo.renderAll.bind(editorMemo)
|
||||
);
|
||||
if (originalBgImage) {
|
||||
editorMemo.setBackgroundImage(
|
||||
originalBgImage,
|
||||
editorMemo.renderAll.bind(editorMemo)
|
||||
);
|
||||
}
|
||||
}, 200);
|
||||
}, [editorMemo]);
|
||||
|
||||
const CopySelection = () => {
|
||||
// TODO: Copy selection
|
||||
const activeObject = editorMemo.getActiveObject();
|
||||
if (activeObject) {
|
||||
activeObject.clone(function (cloned) {
|
||||
// Ensure dockData is copied
|
||||
if (activeObject.dockData) {
|
||||
cloned.dockData = { ...activeObject.dockData };
|
||||
}
|
||||
clipboard = cloned;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const PasteSelection = () => {
|
||||
// TODO: Paste selection
|
||||
if (clipboard) {
|
||||
clipboard.clone(function (clonedObj) {
|
||||
// Ensure dockData is copied
|
||||
if (clipboard.dockData) {
|
||||
clonedObj.dockData = { ...clipboard.dockData };
|
||||
}
|
||||
// Offset the pasted object so it's visible
|
||||
clonedObj.set({
|
||||
left: (clonedObj.left || 0) + 20,
|
||||
top: (clonedObj.top || 0) + 20,
|
||||
evented: true,
|
||||
});
|
||||
editorMemo.add(clonedObj);
|
||||
editorMemo.setActiveObject(clonedObj);
|
||||
editorMemo.requestRenderAll();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const onDeleteSelection = () => {
|
||||
// TODO: Delete selection
|
||||
const activeObject = editorMemo.getActiveObject();
|
||||
if (activeObject) {
|
||||
editorMemo.remove(activeObject);
|
||||
editorMemo.discardActiveObject();
|
||||
editorMemo.renderAll();
|
||||
updateModifications(true, { target: activeObject });
|
||||
}
|
||||
};
|
||||
|
||||
const addLines = useCallback(() => {
|
||||
@@ -539,7 +736,7 @@ export const DockBuilder = () => {
|
||||
[0, oneFeet * i, editorMemo.getWidth(), oneFeet * i],
|
||||
{
|
||||
stroke: "#AAAAAA",
|
||||
strokeDashArray: [5]
|
||||
strokeDashArray: [5],
|
||||
}
|
||||
);
|
||||
|
||||
@@ -548,7 +745,7 @@ export const DockBuilder = () => {
|
||||
fill: "#AAAAAA",
|
||||
fontSize: 18,
|
||||
left: editorMemo.getWidth() - 40,
|
||||
top: oneFeet * i
|
||||
top: oneFeet * i,
|
||||
});
|
||||
|
||||
multiplier++;
|
||||
@@ -576,7 +773,7 @@ export const DockBuilder = () => {
|
||||
|
||||
dispatch({
|
||||
type: "DOCK_LOADING",
|
||||
payload: false
|
||||
payload: false,
|
||||
});
|
||||
setInitialLoad(false);
|
||||
}, [editorMemo, showBuildCanvasFromLocalModal, dispatch, initialLoad]);
|
||||
@@ -625,7 +822,7 @@ export const DockBuilder = () => {
|
||||
bl: false, // bottom-left
|
||||
mb: false, //middle-bottom
|
||||
br: false, //bottom-right
|
||||
mtr: false // rotate icon
|
||||
mtr: false, // rotate icon
|
||||
});
|
||||
// fabric.Object.prototype.controls.deleteControl = new fabric.Control( {
|
||||
// x: -0.8,
|
||||
@@ -654,7 +851,7 @@ export const DockBuilder = () => {
|
||||
sizeX: 40,
|
||||
sizeY: 40,
|
||||
touchSizeX: 40,
|
||||
touchSizeY: 40
|
||||
touchSizeY: 40,
|
||||
});
|
||||
fabric.Object.prototype.hasControls = true;
|
||||
fabric.Object.prototype.lockScalingX = true;
|
||||
@@ -718,7 +915,7 @@ export const DockBuilder = () => {
|
||||
setInitialLoad(false);
|
||||
dispatch({
|
||||
type: "DOCK_LOADING",
|
||||
payload: false
|
||||
payload: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -733,7 +930,7 @@ export const DockBuilder = () => {
|
||||
editorMemo.setBackgroundImage(editorMemo.backgroundImage, (bgImage) => {
|
||||
bgImage.set({
|
||||
scaleX: editorMemo.width / bgImage.width,
|
||||
scaleY: editorMemo.height / bgImage.height
|
||||
scaleY: editorMemo.height / bgImage.height,
|
||||
});
|
||||
});
|
||||
removeLines();
|
||||
@@ -789,8 +986,8 @@ export const DockBuilder = () => {
|
||||
|
||||
<img
|
||||
ref={imageRef}
|
||||
src=""
|
||||
alt=""
|
||||
src=''
|
||||
alt=''
|
||||
width={174}
|
||||
height={116}
|
||||
className={`rounded relative ${objHovered ? "" : "hidden"}`}
|
||||
|
||||
Reference in New Issue
Block a user