diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx
index 2467798a..e1043d2b 100644
--- a/src/components/Playground.jsx
+++ b/src/components/Playground.jsx
@@ -3,6 +3,7 @@
import { Button, Table, TableBody, TableCell, TableColumn, TableHeader, TableRow } from '@nextui-org/react'
import { useAxios } from '@/hooks/useAxios'
+import { useMessage } from '@/hooks/useMessage'
// import { get } from '@/lib/Axios'
import QSelect from '@/components/ui/QSelect'
@@ -12,6 +13,7 @@ import styles from './playground.module.css'
export default function Playground() {
const { get } = useAxios()
const testVar = process.env.NEXT_PUBLIC_TEST
+ const { getMessage } = useMessage()
const handleUsers = async () => {
// const users = await get('/api/user/find-all')
@@ -58,6 +60,7 @@ export default function Playground() {
+
@@ -742,7 +758,7 @@ export default function Roof2(props) {
- {canvas !== undefined && }
+ {canvas !== undefined && }
>
)
diff --git a/src/components/SettingsModal.jsx b/src/components/SettingsModal.jsx
new file mode 100644
index 00000000..b263b47b
--- /dev/null
+++ b/src/components/SettingsModal.jsx
@@ -0,0 +1,274 @@
+import { useEffect, useRef, useState } from 'react'
+import { Button, Checkbox, CheckboxGroup, RadioGroup, Radio, Input } from '@nextui-org/react'
+import { useRecoilState, useRecoilValue } from 'recoil'
+import { modalContent, modalState } from '@/store/modalAtom'
+import { guideLineState } from '@/store/canvasAtom'
+import { fabric } from 'fabric'
+
+export default function SettingsModal(props) {
+ const { canvasProps } = props
+ const [isCustomGridSetting, setIsCustomGridSetting] = useState(true)
+ const [gridCheckedValue, setGridCheckValue] = useState([])
+ const [ratioValue, setRatioValue] = useState('원치수')
+ const moduleLength = useRef(90) //모듈 mm 길이 입력
+
+ const [open, setOpen] = useRecoilState(modalState)
+ const [guideLine, setGuideLine] = useRecoilState(guideLineState)
+
+ useEffect(() => {
+ setIsCustomGridSetting(ratioValue !== 'custom')
+ }, [ratioValue])
+
+ const drawGridSettings = () => {
+ const gridSettingArray = []
+
+ if (gridCheckedValue.includes('line')) {
+ // fabric.GuideRect = fabric.util.createClass(fabric.Rect, {
+ // _render: function (ctx) {
+ // this.callSuper('_render', ctx)
+ // ctx.strokeStyle = this.stroke || 'blue'
+ // ctx.lineWidth = this.strokeWidth || 1
+
+ // ctx.beginPath()
+ // ctx.moveTo(-this.width / 2, -this.height / 2)
+ // ctx.lineTo(this.width / 2, -this.height / 2)
+ // ctx.lineTo(this.width / 2, this.height / 2)
+ // ctx.stroke()
+ // },
+ // })
+
+ // const guideRect = new fabric.GuideRect({
+ // width: canvasProps.width,
+ // height: canvasProps.height,
+ // stroke: 'blue',
+ // strokeWidth: 1,
+ // selectable: false,
+ // fill: 'transparent',
+ // name: 'guideRect',
+ // })
+
+ // const patternSourceCanvas = new fabric.StaticCanvas(null, {
+ // width: moduleLength.current.value,
+ // height: moduleLength.current.value,
+ // backgroundColor: 'white',
+ // })
+
+ // patternSourceCanvas.add(guideRect)
+ // patternSourceCanvas.renderAll()
+
+ // const pattern = new fabric.Pattern({
+ // source: patternSourceCanvas.getElement(),
+ // repeat: 'repeat',
+ // })
+
+ const horizontalLineArray = []
+ const verticalLineArray = []
+
+ for (let i = 0; i < canvasProps.height / moduleLength.current.value + 1; i++) {
+ const horizontalLine = new fabric.Line(
+ [
+ 0,
+ i * moduleLength.current.value - moduleLength.current.value / 2,
+ canvasProps.width,
+ i * moduleLength.current.value - moduleLength.current.value / 2,
+ ],
+ {
+ stroke: 'gray',
+ strokeWidth: 1,
+ selectable: false,
+ name: 'guideLine',
+ },
+ )
+ canvasProps.add(horizontalLine)
+ horizontalLineArray.push(horizontalLine)
+ }
+
+ for (let i = 0; i < canvasProps.width / moduleLength.current.value + 1; i++) {
+ const verticalLine = new fabric.Line(
+ [
+ i * moduleLength.current.value - moduleLength.current.value / 2,
+ 0,
+ i * moduleLength.current.value - moduleLength.current.value / 2,
+ canvasProps.height,
+ ],
+ {
+ stroke: 'gray',
+ strokeWidth: 1,
+ selectable: false,
+ name: 'guideLine',
+ },
+ )
+ canvasProps.add(verticalLine)
+ verticalLineArray.push(verticalLine)
+ }
+ canvasProps.renderAll()
+
+ const snapDistance = 10
+
+ canvasProps.on('mouse:move', function (e) {
+ let mouseObj = e
+ const mouseCursorX = e.pointer.x
+ const mouseCursorY = e.pointer.y
+
+ horizontalLineArray.forEach((line) => {
+ if (Math.abs(mouseCursorY - line.y1) < snapDistance) {
+ mouseObj.x = mouseCursorX
+ mouseObj.y = line.y1
+ }
+ // if (Math.abs(mouseCursorX - line.x2) < snapDistance) {
+ // line.set({ x2: mouseCursorX })
+ // }
+ })
+ })
+
+ // canvasProps.on('mouse:move', (e) => {
+ // console.log('event', e.pointer)
+
+ // const obj = e
+
+ // if (!obj) return
+
+ // canvasProps.forEachObject(function (target) {
+ // if (target.name === 'guideLine' || target.name === 'guideDot') {
+ // console.log('line : ', target)
+
+ // const lineStartX = target.x1,
+ // lineStartY = target.y1
+ // const lineEndX = target.x2,
+ // lineEndY = target.y2
+
+ // console.log('target.x1', target.x1)
+ // console.log('target.y1', target.y1)
+ // console.log(`obj.pointer.y : ${obj.pointer.y}, obj.pointer.x : ${obj.pointer.x}`)
+
+ // // 수평 선에 대한 스냅
+ // if (Math.abs(obj.pointer.y - lineStartY) < snapDistance) {
+ // obj.pointer.y = lineStartY
+ // }
+
+ // // 수직 선에 대한 스냅
+ // if (Math.abs(obj.pointer.x - lineStartX) < snapDistance) {
+ // obj.pointer.x = lineStartX
+ // }
+ // }
+ // })
+ // })
+
+ const recoilObj = {
+ guideMode: 'guideLine',
+ horizontalLineArray,
+ verticalLineArray,
+ moduleLength: moduleLength.current.value,
+ }
+ gridSettingArray.push(recoilObj)
+ }
+
+ if (gridCheckedValue.includes('dot')) {
+ const circle = new fabric.Circle({
+ radius: 2,
+ fill: 'red',
+ originX: 'center',
+ originY: 'center',
+ selectable: false,
+ lockMovementX: true,
+ lockMovementY: true,
+ lockRotation: true,
+ lockScalingX: true,
+ lockScalingY: true,
+ name: 'guideDot',
+ })
+
+ const patternSourceCanvas = new fabric.StaticCanvas(null, {
+ width: moduleLength.current.value,
+ height: moduleLength.current.value,
+ })
+
+ patternSourceCanvas.add(circle)
+
+ circle.set({
+ left: patternSourceCanvas.width / 2,
+ top: patternSourceCanvas.height / 2,
+ })
+
+ patternSourceCanvas.renderAll()
+
+ const pattern = new fabric.Pattern({
+ source: patternSourceCanvas.getElement(),
+ repeat: 'repeat',
+ })
+
+ const backgroundPolygon = new fabric.Polygon(
+ [
+ { x: 0, y: 0 },
+ { x: canvasProps.width, y: 0 },
+ { x: canvasProps.width, y: canvasProps.height },
+ { x: 0, y: canvasProps.height },
+ ],
+ {
+ fill: pattern,
+ selectable: false,
+ },
+ )
+ canvasProps.add(backgroundPolygon)
+ canvasProps.renderAll()
+
+ const recoilObj = {
+ guideMode: 'guideDot',
+ moduleLength: moduleLength.current.value,
+ }
+
+ gridSettingArray.push(recoilObj)
+ }
+ canvasProps.renderAll()
+ setGuideLine(gridSettingArray)
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+ mm
+
+
+
+ 원치수
+ 1/2
+ 1/4
+ 1/10
+ 임의간격
+
+
+
+
+ 종횡연동
+
+
+
+
+ mm
+
+
+
+ mm
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/util/context-util.js b/src/components/common/context-menu/QContextMenu.jsx
similarity index 86%
rename from src/util/context-util.js
rename to src/components/common/context-menu/QContextMenu.jsx
index 0179fdf0..57aaf45b 100644
--- a/src/util/context-util.js
+++ b/src/components/common/context-menu/QContextMenu.jsx
@@ -1,10 +1,15 @@
-import React, { useState, useEffect, forwardRef, useContext } from 'react'
+'use client'
+import { useEffect, useState } from 'react'
+import { useRecoilState, useRecoilValue } from 'recoil'
-const CanvasWithContextMenu = forwardRef(({ canvasProps }, ref) => {
+export default function QContextMenu(props) {
+ const { contextRef, canvasProps } = props
+
+ // const children = useRecoilValue(modalContent)
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 })
useEffect(() => {
- if (!ref.current) return
+ if (!contextRef.current) return
const handleContextMenu = (e) => {
e.preventDefault() //기존 contextmenu 막고
@@ -34,7 +39,7 @@ const CanvasWithContextMenu = forwardRef(({ canvasProps }, ref) => {
document.removeEventListener('click', handleClick)
document.removeEventListener('click', handleOutsideClick)
}
- }, [ref, contextMenu])
+ }, [contextRef, contextMenu])
const handleMenuClick = (option) => {
alert(`option ${option} clicked`)
@@ -60,6 +65,4 @@ const CanvasWithContextMenu = forwardRef(({ canvasProps }, ref) => {
)}
>
)
-})
-
-export default CanvasWithContextMenu
+}
diff --git a/src/hooks/useMessage.js b/src/hooks/useMessage.js
new file mode 100644
index 00000000..bc2f7eef
--- /dev/null
+++ b/src/hooks/useMessage.js
@@ -0,0 +1,38 @@
+import { useRecoilValue } from 'recoil'
+import { globalLocaleState } from '@/store/localeAtom'
+
+import KO from '@/locales/ko.json'
+import JA from '@/locales/ja.json'
+
+const SESSION_STORAGE_MESSAGE_KEY = 'QCAST_MESSAGE_STORAGE'
+
+export const useMessage = () => {
+ const globalLocale = useRecoilValue(globalLocaleState)
+
+ const getMessage = (key, args = []) => {
+ if (sessionStorage.getItem(SESSION_STORAGE_MESSAGE_KEY) === null) {
+ if (globalLocale === 'ko') {
+ setSessionMessage(JSON.stringify(KO))
+ } else {
+ setSessionMessage(JSON.stringify(JA))
+ }
+ }
+
+ const sessionMessage = getSessionMessage()
+ const message = sessionMessage[key] || key
+
+ return args.reduce((acc, arg, i) => {
+ return acc.replaceAll(`{${i}}`, arg)
+ }, message)
+ }
+
+ const setSessionMessage = (sessionMessage) => {
+ sessionStorage.setItem(SESSION_STORAGE_MESSAGE_KEY, sessionMessage)
+ }
+
+ const getSessionMessage = () => {
+ return JSON.parse(sessionStorage.getItem(SESSION_STORAGE_MESSAGE_KEY))
+ }
+
+ return { getMessage }
+}
diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js
index 77d9de25..11cc0ec2 100644
--- a/src/hooks/useMode.js
+++ b/src/hooks/useMode.js
@@ -4,6 +4,8 @@ import {
distanceBetweenPoints,
findTopTwoIndexesByDistance,
getCenterPoint,
+ getClosestHorizontalLine,
+ getClosestVerticalLine,
getDirection,
getStartIndex,
rearrangeArray,
@@ -23,6 +25,7 @@ import {
sortedPolygonArray,
templateTypeState,
wallState,
+ guideLineState,
} from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { fabric } from 'fabric'
@@ -41,7 +44,6 @@ export function useMode() {
const [canvas, setCanvas] = useState(null)
const [zoom, setZoom] = useState(100)
const [fontSize] = useRecoilState(fontSizeState)
- const [shape, setShape] = useState(0)
const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray)
const [roof, setRoof] = useRecoilState(roofState)
const [wall, setWall] = useRecoilState(wallState)
@@ -64,6 +66,11 @@ export function useMode() {
const compass = useRecoilValue(compassState)
const [isCellCenter, setIsCellCenter] = useState(false)
+ const guideLineInfo = useRecoilValue(guideLineState)
+
+ const [guideLineMode, setGuideLineMode] = useState(false)
+ const [guideDotMode, setGuideDotMode] = useState(false)
+
useEffect(() => {
// 이벤트 리스너 추가
// if (!canvas) {
@@ -101,30 +108,127 @@ export function useMode() {
canvas?.off('mouse:down')
canvas?.on('mouse:down', mouseEvent.editMode)
}
- }, [mode, isGuidePointMode])
+ }, [mode])
+
+ useEffect(() => {
+ setGuideLineMode(false)
+ setGuideDotMode(false)
+ if (isObjectNotEmpty(guideLineInfo)) {
+ const guideLineState = guideLineInfo.filter((item) => item.guideMode === 'guideLine')
+ const guideDotState = guideLineInfo.filter((item) => item.guideMode === 'guideDot')
+
+ setGuideLineMode(guideLineState.length > 0)
+ setGuideDotMode(guideDotState.length > 0)
+ }
+ }, [guideLineInfo])
const drawMouseLines = (e) => {
+ let isGuideLineMode = false,
+ isGuideDotMode = false
+ let guideDotLength, guideLineLength, horizontalLineArray, verticalLineArray
+
+ if (isObjectNotEmpty(guideLineInfo)) {
+ const guideLineState = guideLineInfo.filter((item) => item.guideMode === 'guideLine')
+ const guideDotState = guideLineInfo.filter((item) => item.guideMode === 'guideDot')
+ setGuideLineMode(guideLineState.length > 0)
+ setGuideDotMode(guideDotState.length > 0)
+ isGuideLineMode = guideLineState.length > 0
+ isGuideDotMode = guideDotState.length > 0
+
+ if (isGuideDotMode) {
+ guideDotLength = Number(guideDotState[0].moduleLength)
+ }
+
+ if (isGuideLineMode) {
+ horizontalLineArray = [...guideLineState[0].horizontalLineArray]
+ verticalLineArray = [...guideLineState[0].verticalLineArray]
+ guideLineLength = Number(guideLineState[0].moduleLength)
+ }
+ }
+
// 현재 마우스 포인터의 위치를 가져옵니다.
const pointer = canvas?.getPointer(e.e)
// 기존에 그려진 가이드라인을 제거합니다.
removeMouseLines()
- if (canvas?.getActiveObject()) {
- return
- }
- let newX, newY
- if (isGuidePointMode && mode === Mode.EDIT) {
- newX = Math.round(pointer.x / 200) * 200
- newY = Math.round(pointer.y / 200) * 200
- } else {
- newX = pointer.x
- newY = pointer.y
+ let newX = pointer.x
+ let newY = pointer.y
+
+ if (isGuideLineMode && isGuideDotMode && mode === Mode.EDIT) {
+ const closestHorizontalLine = getClosestHorizontalLine(pointer, horizontalLineArray)
+ const closetVerticalLine = getClosestVerticalLine(pointer, verticalLineArray)
+ const xDiff = Math.abs(pointer.x - closetVerticalLine.x1)
+ const yDiff = Math.abs(pointer.y - closestHorizontalLine.y1)
+
+ const x = pointer.x - guideLineLength * Math.floor(pointer.x / guideLineLength)
+ const y = pointer.y - guideLineLength * Math.floor(pointer.y / guideLineLength)
+
+ const xRate = x / guideLineLength
+ const yRate = y / guideLineLength
+ const isAttachX = xRate >= 0.4 && xRate <= 0.7
+ const isAttachY = yRate >= 0.4 && yRate <= 0.7
+
+ if (isAttachX && isAttachY) {
+ newX = Math.floor(pointer.x / guideLineLength) * guideLineLength + guideLineLength / 2
+ newY = Math.floor(pointer.y / guideLineLength) * guideLineLength + guideLineLength / 2
+ } else {
+ if (Math.min(xDiff, yDiff) <= 20) {
+ if (xDiff < yDiff) {
+ newX = closetVerticalLine.x1
+ newY = pointer.y
+ } else {
+ newX = pointer.x
+ newY = closestHorizontalLine.y1
+ }
+ }
+ }
+ } else if (isGuideDotMode && mode === Mode.EDIT) {
+ const x = pointer.x - guideDotLength * Math.floor(pointer.x / guideDotLength)
+ const y = pointer.y - guideDotLength * Math.floor(pointer.y / guideDotLength)
+
+ const xRate = x / guideDotLength
+ const yRate = y / guideDotLength
+ const isAttachX = xRate >= 0.4 && xRate <= 0.7
+ const isAttachY = yRate >= 0.4 && yRate <= 0.7
+
+ if (isAttachX && isAttachY) {
+ newX = Math.floor(pointer.x / guideDotLength) * guideDotLength + guideDotLength / 2
+ newY = Math.floor(pointer.y / guideDotLength) * guideDotLength + guideDotLength / 2
+ }
+ } else if (isGuideLineMode && mode === Mode.EDIT) {
+ const closestHorizontalLine = getClosestHorizontalLine(pointer, horizontalLineArray)
+ const closetVerticalLine = getClosestVerticalLine(pointer, verticalLineArray)
+ const xDiff = Math.abs(pointer.x - closetVerticalLine.x1)
+ const yDiff = Math.abs(pointer.y - closestHorizontalLine.y1)
+
+ const x = pointer.x - guideLineLength * Math.floor(pointer.x / guideLineLength)
+ const y = pointer.y - guideLineLength * Math.floor(pointer.y / guideLineLength)
+
+ const xRate = x / guideLineLength
+ const yRate = y / guideLineLength
+ const isAttachX = xRate >= 0.4 && xRate <= 0.7
+ const isAttachY = yRate >= 0.4 && yRate <= 0.7
+
+ if (isAttachX && isAttachY) {
+ newX = Math.floor(pointer.x / guideLineLength) * guideLineLength + guideLineLength / 2
+ newY = Math.floor(pointer.y / guideLineLength) * guideLineLength + guideLineLength / 2
+ } else {
+ if (Math.min(xDiff, yDiff) <= 20) {
+ if (xDiff < yDiff) {
+ newX = closetVerticalLine.x1
+ newY = pointer.y
+ } else {
+ newX = pointer.x
+ newY = closestHorizontalLine.y1
+ }
+ }
+ }
}
// 가로선을 그립니다.
const horizontalLine = new fabric.Line([0, newY, canvasSize.horizontal, newY], {
- stroke: 'black',
+ stroke: 'red',
strokeWidth: 1,
selectable: false,
name: 'mouseLine',
@@ -132,7 +236,7 @@ export function useMode() {
// 세로선을 그립니다.
const verticalLine = new fabric.Line([newX, 0, newX, canvasSize.vertical], {
- stroke: 'black',
+ stroke: 'red',
strokeWidth: 1,
selectable: false,
name: 'mouseLine',
@@ -154,7 +258,7 @@ export function useMode() {
}, [pointCount.current])
const removeGuideLines = () => {
- const guideLines = canvas?._objects.filter((obj) => obj.name === 'guideLine')
+ const guideLines = canvas?._objects.filter((obj) => obj.name === 'helpGuideLine')
guideLines?.forEach((item) => canvas?.remove(item))
}
@@ -176,7 +280,7 @@ export function useMode() {
strokeWidth: 1,
strokeDashArray: [1, 1, 1],
})
- guideLine.name = 'guideLine'
+ guideLine.name = 'helpGuideLine'
canvas?.add(guideLine)
} else {
const guideLine1 = new QLine([lastX, lastY, lastX, arrivalY], {
@@ -193,8 +297,8 @@ export function useMode() {
strokeDashArray: [1, 1, 1],
})
- guideLine1.name = 'guideLine'
- guideLine2.name = 'guideLine'
+ guideLine1.name = 'helpGuideLine'
+ guideLine2.name = 'helpGuideLine'
canvas?.add(guideLine1)
canvas?.add(guideLine2)
@@ -587,7 +691,7 @@ export function useMode() {
canvas?.add(circle)
if (points.current.length === 2) {
- if (isGuidePointMode) {
+ if (guideLineMode || guideDotMode) {
const vector = {
x: points.current[1].left - points.current[0].left,
y: points.current[1].top - points.current[0].top,
@@ -757,10 +861,8 @@ export function useMode() {
points.current = []
historyPoints.current = []
- // handleOuterlines()
const wall = makePolygon(null, sort)
wall.set({ name: 'wall' })
- console.log('wall', wall)
return wall
}
@@ -799,33 +901,7 @@ export function useMode() {
const makePolygon = (otherLines, sort = true) => {
// 캔버스에서 모든 라인 객체를 찾습니다.
const lines = otherLines || historyLines.current
-
- if (!otherLines) {
- //외각선 기준
- const topIndex = findTopTwoIndexesByDistance(sortedArray) //배열중에 큰 2값을 가져옴 TODO: 나중에는 인자로 받아서 다각으로 수정 해야됨
-
- //일단 배열 6개 짜리 기준의 선 번호
- if (topIndex[0] === 4) {
- if (topIndex[1] === 5) {
- //1번
- setShape(1)
- }
- } else if (topIndex[0] === 1) {
- //4번
- if (topIndex[1] === 2) {
- setShape(4)
- }
- } else if (topIndex[0] === 0) {
- if (topIndex[1] === 1) {
- //2번
- setShape(2)
- } else if (topIndex[1] === 5) {
- setShape(3)
- }
- }
-
- historyLines.current = []
- }
+ historyLines.current = []
// 각 라인의 시작점과 끝점을 사용하여 다각형의 점 배열을 생성합니다.
const points = lines.map((line) => ({ x: line.x1, y: line.y1 }))
@@ -853,12 +929,10 @@ export function useMode() {
canvas.add(polygon)
// 캔버스를 다시 그립니다.
- if (!otherLines) {
- // polygon.fillCell()
- canvas?.renderAll()
- // polygon.setViewLengthText(false)
- setMode(Mode.DEFAULT)
- }
+ // polygon.fillCell()
+ canvas?.renderAll()
+ // polygon.setViewLengthText(false)
+ setMode(Mode.DEFAULT)
return polygon
}
diff --git a/src/locales/ja.json b/src/locales/ja.json
new file mode 100644
index 00000000..a1725dfd
--- /dev/null
+++ b/src/locales/ja.json
@@ -0,0 +1,3 @@
+{
+ "hi": "こんにちは"
+}
diff --git a/src/locales/ko.json b/src/locales/ko.json
new file mode 100644
index 00000000..282d9722
--- /dev/null
+++ b/src/locales/ko.json
@@ -0,0 +1,3 @@
+{
+ "hi": "안녕하세요"
+}
diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js
index b1bacbdb..062698c0 100644
--- a/src/store/canvasAtom.js
+++ b/src/store/canvasAtom.js
@@ -88,3 +88,9 @@ export const compassState = atom({
default: undefined,
dangerouslyAllowMutability: true,
})
+
+export const guideLineState = atom({
+ key: 'guideLine',
+ default: {},
+ dangerouslyAllowMutability: true,
+})
diff --git a/src/store/localeAtom.js b/src/store/localeAtom.js
new file mode 100644
index 00000000..d82bcf7b
--- /dev/null
+++ b/src/store/localeAtom.js
@@ -0,0 +1,6 @@
+import { atom } from 'recoil'
+
+export const globalLocaleState = atom({
+ key: 'globalLocaleState',
+ default: 'ko',
+})
diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js
index 7374c024..268370c1 100644
--- a/src/util/canvas-util.js
+++ b/src/util/canvas-util.js
@@ -38,7 +38,7 @@ export function actionHandler(eventData, transform, x, y) {
// define a function that can keep the polygon in the same position when we change its width/height/top/left
export function anchorWrapper(anchorIndex, fn) {
- return function(eventData, transform, x, y) {
+ return function (eventData, transform, x, y) {
let fabricObject = transform.target
let originX = fabricObject?.points[anchorIndex].x - fabricObject.pathOffset.x
let originY = fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y
@@ -675,3 +675,33 @@ export function findClosestPointWithDifferentXY(targetPoint, points) {
return closestPoint
}
+
+export const getClosestHorizontalLine = (pointer, horizontalLineArray) => {
+ let closestLine = null
+ let minDistance = Infinity
+
+ horizontalLineArray.forEach((line) => {
+ const distance = Math.abs(line.y1 - pointer.y) // Assuming horizontal lines have the same y1 and y2
+ if (distance < minDistance) {
+ minDistance = distance
+ closestLine = line
+ }
+ })
+
+ return closestLine
+}
+
+export const getClosestVerticalLine = (pointer, verticalLineArray) => {
+ let closestLine = null
+ let minDistance = Infinity
+
+ verticalLineArray.forEach((line) => {
+ const distance = Math.abs(line.x1 - pointer.x) // Assuming horizontal lines have the same y1 and y2
+ if (distance < minDistance) {
+ minDistance = distance
+ closestLine = line
+ }
+ })
+
+ return closestLine
+}