diff --git a/src/components/Roof2.jsx b/src/components/Roof2.jsx
index 108303b3..eba3000e 100644
--- a/src/components/Roof2.jsx
+++ b/src/components/Roof2.jsx
@@ -7,11 +7,11 @@ import QPolygon from '@/components/fabric/QPolygon'
import RangeSlider from './ui/RangeSlider'
import { useRecoilState, useRecoilValue } from 'recoil'
-import { canvasSizeState, fontSizeState, sortedPolygonArray } from '@/store/canvasAtom'
+import { canvasListState, canvasSizeState, fontSizeState, sortedPolygonArray } from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
export default function Roof2() {
- const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage } = useCanvas('canvas')
+ const { canvas, handleRedo, handleUndo, setCanvasBackgroundWithDots, saveImage, addCanvas, changeCanvas } = useCanvas('canvas')
//canvas 기본 사이즈
const [canvasSize, setCanvasSize] = useRecoilState(canvasSizeState)
@@ -29,6 +29,9 @@ export default function Roof2() {
const [showControl, setShowControl] = useState(false)
+ const [canvasIdx, setCanvasIdx] = useState(0)
+ const canvasList = useRecoilValue(canvasListState)
+
const { mode, changeMode, handleClear, fillCellInPolygon, zoomIn, zoomOut, zoom, togglePolygonLine, handleOuterlinesTest2, applyTemplateB } =
useMode()
@@ -180,6 +183,8 @@ export default function Roof2() {
canvas?.add(polygon)
+ console.log(polygon)
+
handleOuterlinesTest2(polygon)
// const lines = togglePolygonLine(polygon)
@@ -200,17 +205,19 @@ export default function Roof2() {
const makeQLine = () => {
if (canvas) {
- const line = new QLine(
- [50, 50, 200, 50],
+ const line = new fabric.QLine(
+ [200, 200, 500, 500],
{
stroke: 'black',
strokeWidth: 1,
fontSize: fontSize,
+ selectable: true,
},
50,
)
canvas?.add(line)
+ console.log(line)
}
}
@@ -240,6 +247,12 @@ export default function Roof2() {
setShowControl(!showControl)
}
+ const nextCanvas = () => {
+ const nextCanvasNumber = canvasIdx < canvasList.length - 1 ? canvasIdx + 1 : 0
+ setCanvasIdx(nextCanvasNumber)
+ changeCanvas(nextCanvasNumber)
+ }
+
return (
<>
{canvas && (
@@ -333,6 +346,12 @@ export default function Roof2() {
+
+
diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js
index 7796e66e..6a3ce67c 100644
--- a/src/components/fabric/QLine.js
+++ b/src/components/fabric/QLine.js
@@ -16,7 +16,7 @@ export class QLine extends fabric.Group {
isAlreadyInterSection = false
interSectionPoints = []
- #lengthTxt = 0
+ lengthTxt = 0
constructor(points, option = { isActiveLengthText: true }, lengthTxt) {
// 소수점 전부 제거
@@ -44,24 +44,24 @@ export class QLine extends fabric.Group {
this.idx = option.idx
if (lengthTxt > 0) {
- this.#lengthTxt = Number(lengthTxt)
+ this.lengthTxt = Number(lengthTxt)
}
- option.isActiveLengthText ?? this.#init()
- this.#addControl()
+ option.isActiveLengthText ?? this.init()
+ this.addControl()
}
- #init() {
- this.#addLengthText(true)
+ init() {
+ this.addLengthText(true)
}
- #addControl() {
+ addControl() {
this.on('moving', () => {
- this.#addLengthText(false)
+ this.addLengthText(false)
})
this.on('modified', (e) => {
- this.#addLengthText(false)
+ this.addLengthText(false)
})
this.on('selected', () => {
@@ -73,19 +73,19 @@ export class QLine extends fabric.Group {
})
}
- #addLengthText(isFirst) {
+ addLengthText(isFirst) {
if (this.text) {
this.removeWithUpdate(this.text)
this.text = null
}
- if (isFirst && this.#lengthTxt > 0) {
- const text = new fabric.Textbox(this.#lengthTxt.toFixed(0).toString(), {
+ if (isFirst && this.lengthTxt > 0) {
+ const text = new fabric.Textbox(this.lengthTxt.toFixed(0).toString(), {
left: (this.x1 + this.x2) / 2,
top: (this.y1 + this.y2) / 2,
fontSize: this.fontSize,
})
- this.length = this.#lengthTxt
+ this.length = this.lengthTxt
this.text = text
this.addWithUpdate(text)
return
@@ -115,4 +115,37 @@ export class QLine extends fabric.Group {
this.text.set({ fontSize })
this.addWithUpdate()
}
+
+ fromObject(object, callback) {
+ fabric.util.enlivenObjects(object.objects, function (enlivenedObjects) {
+ delete object.objects
+ callback && callback(new fabric.Frindle(enlivenedObjects, object))
+ })
+ }
+
+ async = true
+
+ toObject(propertiesToInclude) {
+ return fabric.util.object.extend(this.callSuper('toObject'), {
+ length: this.length,
+ line: this.line,
+ text: this.text,
+ fontSize: this.fontSize,
+ x1: this.x1,
+ y1: this.y1,
+ x2: this.x2,
+ y2: this.y2,
+ direction: this.direction,
+ idx: this.idx,
+ type: this.type,
+ parent: this.parent,
+ isAlreadyInterSection: this.isAlreadyInterSection,
+ interSectionPoints: this.interSectionPoints,
+ lengthTxt: this.lengthTxt,
+ setFontSize: this.setFontSize,
+ addLengthText: this.addLengthText,
+ init: this.init,
+ addControl: this.addControl,
+ })
+ }
}
diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js
index f7bc2509..75e62a19 100644
--- a/src/components/fabric/QPolygon.js
+++ b/src/components/fabric/QPolygon.js
@@ -28,6 +28,7 @@ export default class QPolygon extends fabric.Group {
helpLines = []
wall
+
constructor(points, options, canvas) {
/*if (points.length !== 4 && points.length !== 6) {
throw new Error('Points must be 4 or 6.')
@@ -51,13 +52,13 @@ export default class QPolygon extends fabric.Group {
this.points = sortPoints
this.polygon = polygon
this.name = options.name
- this.#init()
- this.#addEvent()
- this.#initLines()
+ this.init()
+ this.addEvent()
+ this.initLines()
this.setShape()
}
- #initLines() {
+ initLines() {
this.points.forEach((point, i) => {
const nextPoint = this.points[(i + 1) % this.points.length]
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
@@ -71,13 +72,13 @@ export default class QPolygon extends fabric.Group {
})
}
- #init() {
- this.#addLengthText()
+ init() {
+ this.addLengthText()
}
- #addEvent() {
+ addEvent() {
this.on('scaling', (e) => {
- this.#updateLengthText()
+ this.updateLengthText()
})
this.on('selected', function () {
@@ -110,7 +111,7 @@ export default class QPolygon extends fabric.Group {
this.addWithUpdate()
}
- #addLengthText() {
+ addLengthText() {
if (this.texts.length > 0) {
this.texts.forEach((text) => {
this.canvas.remove(text)
@@ -142,7 +143,7 @@ export default class QPolygon extends fabric.Group {
this.canvas.renderAll()
}
- #updateLengthText() {
+ updateLengthText() {
const points = this.getCurrentPoints()
points.forEach((start, i) => {
@@ -188,7 +189,7 @@ export default class QPolygon extends fabric.Group {
new fabric.Point(rect.left + rect.width, rect.top + rect.height),
]
- const isInside = rectPoints.every((rectPoint) => this.inPolygon(rectPoint) && this.#distanceFromEdge(rectPoint) >= cell.padding)
+ const isInside = rectPoints.every((rectPoint) => this.inPolygon(rectPoint) && this.distanceFromEdge(rectPoint) >= cell.padding)
if (isInside) {
this.addWithUpdate(rect)
@@ -245,7 +246,7 @@ export default class QPolygon extends fabric.Group {
return intersects % 2 === 1
}
- #distanceFromEdge(point) {
+ distanceFromEdge(point) {
const vertices = this.getCurrentPoints()
let minDistance = Infinity
@@ -317,13 +318,13 @@ export default class QPolygon extends fabric.Group {
}
if (this.lines.length === 4) {
- this.#drawHelpLineInRect(chon)
+ this.drawHelpLineInRect(chon)
} else if (this.lines.length === 6 || this.lines.length === 8) {
// TODO : 6각형
- this.#drawHelpLineInHexagon2(chon)
+ this.drawHelpLineInHexagon2(chon)
} /* else if (this.lines.length === 8) {
// TODO : 8각형
- this.#drawHelpLineInOctagon(chon)
+ this.drawHelpLineInOctagon(chon)
}*/
}
@@ -370,7 +371,7 @@ export default class QPolygon extends fabric.Group {
return this.shape
}
- #drawHelpLineInRect(chon) {
+ drawHelpLineInRect(chon) {
let type = 1
let smallestLength = Infinity
let maxLength = 0
@@ -526,7 +527,7 @@ export default class QPolygon extends fabric.Group {
this.canvas.add(ridge)
}
}
- #drawHelpLineInHexagon2(chon) {
+ drawHelpLineInHexagon2(chon) {
const oneSideLines = [...this.lines].map((line) => {
let newX1, newY1, newX2, newY2
if (line.direction === 'top') {
@@ -742,7 +743,7 @@ export default class QPolygon extends fabric.Group {
this.canvas.renderAll()
})
}
- #drawHelpLineInHexagon(chon) {
+ drawHelpLineInHexagon(chon) {
const historyLines = []
const helpPoints = []
const notInterSectionLines = []
@@ -884,5 +885,9 @@ export default class QPolygon extends fabric.Group {
this.canvas.renderAll()
}
- #drawHelpLineInOctagon(chon) {}
+ drawHelpLineInOctagon(chon) {}
+
+ getObject() {
+ return this
+ }
}
diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js
index 5f44060a..54e9609d 100644
--- a/src/hooks/useCanvas.js
+++ b/src/hooks/useCanvas.js
@@ -1,13 +1,9 @@
import { useEffect, useRef, useState } from 'react'
import { fabric } from 'fabric'
-import {
- actionHandler,
- anchorWrapper,
- polygonPositionHandler,
-} from '@/util/canvas-util'
+import { actionHandler, anchorWrapper, getDirectionByPoint, polygonPositionHandler, sortedPoints } from '@/util/canvas-util'
import { useRecoilState } from 'recoil'
-import { canvasSizeState, fontSizeState } from '@/store/canvasAtom'
+import { canvasListState, canvasSizeState, fontSizeState } from '@/store/canvasAtom'
import QPolygon from '@/components/fabric/QPolygon'
import { QLine } from '@/components/fabric/QLine'
import QRect from '@/components/fabric/QRect'
@@ -20,6 +16,8 @@ export function useCanvas(id) {
const [fontSize] = useRecoilState(fontSizeState)
const points = useRef([])
+ const [canvasList, setCanvasList] = useRecoilState(canvasListState)
+
/**
* 처음 셋팅
*/
@@ -31,17 +29,6 @@ export function useCanvas(id) {
selection: false,
})
- // settings for all canvas in the app
- fabric.Object.prototype.transparentCorners = false
- fabric.Object.prototype.cornerColor = '#2BEBC8'
- fabric.Object.prototype.cornerStyle = 'rect'
- fabric.Object.prototype.cornerStrokeColor = '#2BEBC8'
- fabric.Object.prototype.cornerSize = 6
-
- QPolygon.prototype.canvas = c
- QLine.prototype.canvas = c
- QRect.prototype.canvas = c
-
setCanvas(c)
return () => {
c.dispose()
@@ -57,24 +44,14 @@ export function useCanvas(id) {
useEffect(() => {
canvas
?.getObjects()
- .filter(
- (obj) =>
- obj.type === 'textbox' ||
- obj.type === 'text' ||
- obj.type === 'i-text',
- )
+ .filter((obj) => obj.type === 'textbox' || obj.type === 'text' || obj.type === 'i-text')
.forEach((obj) => {
obj.set({ fontSize: fontSize })
})
canvas
?.getObjects()
- .filter(
- (obj) =>
- obj.type === 'QLine' ||
- obj.type === 'QPolygon' ||
- obj.type === 'QRect',
- )
+ .filter((obj) => obj.type === 'QLine' || obj.type === 'QPolygon' || obj.type === 'QRect')
.forEach((obj) => {
obj.setFontSize(fontSize)
})
@@ -121,26 +98,26 @@ export function useCanvas(id) {
*/
const removeMouseLines = () => {
if (canvas?._objects.length > 0) {
- const mouseLines = canvas?._objects.filter(
- (obj) => obj.name === 'mouseLine',
- )
+ const mouseLines = canvas?._objects.filter((obj) => obj.name === 'mouseLine')
mouseLines.forEach((item) => canvas?.remove(item))
}
canvas?.renderAll()
}
- /**
- * 눈금 그리기
- */
const initialize = () => {
canvas?.clear()
+ // settings for all canvas in the app
+ fabric.Object.prototype.transparentCorners = false
+ fabric.Object.prototype.cornerColor = '#2BEBC8'
+ fabric.Object.prototype.cornerStyle = 'rect'
+ fabric.Object.prototype.cornerStrokeColor = '#2BEBC8'
+ fabric.Object.prototype.cornerSize = 6
- // 기존 이벤트가 있을 경우 제거한다.
- // removeEventOnCanvas()
+ QPolygon.prototype.canvas = canvas
+ QLine.prototype.canvas = canvas
+ QRect.prototype.canvas = canvas
- // 작업 후에 event를 추가해준다.
-
- // addEventOnCanvas()
+ fabric.QLine = QLine
}
/**
@@ -176,26 +153,20 @@ export function useCanvas(id) {
}
// 가로선을 그립니다.
- const horizontalLine = new fabric.Line(
- [0, pointer.y, canvasSize.horizontal, pointer.y],
- {
- stroke: 'black',
- strokeWidth: 1,
- selectable: false,
- name: 'mouseLine',
- },
- )
+ const horizontalLine = new fabric.Line([0, pointer.y, canvasSize.horizontal, pointer.y], {
+ stroke: 'black',
+ strokeWidth: 1,
+ selectable: false,
+ name: 'mouseLine',
+ })
// 세로선을 그립니다.
- const verticalLine = new fabric.Line(
- [pointer.x, 0, pointer.x, canvasSize.vertical],
- {
- stroke: 'black',
- strokeWidth: 1,
- selectable: false,
- name: 'mouseLine',
- },
- )
+ const verticalLine = new fabric.Line([pointer.x, 0, pointer.x, canvasSize.vertical], {
+ stroke: 'black',
+ strokeWidth: 1,
+ selectable: false,
+ name: 'mouseLine',
+ })
// 선들을 캔버스에 추가합니다.
canvas?.add(horizontalLine, verticalLine)
@@ -325,7 +296,6 @@ export function useCanvas(id) {
}
const jsonStr = JSON.stringify(canvas)
localStorage.setItem('canvas', jsonStr)
- handleClear()
}
/**
@@ -479,10 +449,7 @@ export function useCanvas(id) {
poly.controls = poly.points.reduce(function (acc, point, index) {
acc['p' + index] = new fabric.Control({
positionHandler: polygonPositionHandler,
- actionHandler: anchorWrapper(
- index > 0 ? index - 1 : lastControl,
- actionHandler,
- ),
+ actionHandler: anchorWrapper(index > 0 ? index - 1 : lastControl, actionHandler),
actionName: 'modifyPolygon',
pointIndex: index,
})
@@ -571,6 +538,33 @@ export function useCanvas(id) {
})
}
+ const addCanvas = () => {
+ const canvasState = canvas?.getObjects()
+
+ canvasState.forEach((state) => {
+ console.log(state)
+ })
+
+ const str = JSON.stringify(canvasState)
+
+ canvas?.clear()
+
+ JSON.parse(str).forEach((state) => {
+ canvas?.add(state)
+ })
+
+ /*const stateArr = canvasState.map((state) => state.getObject().getObjects())
+
+ const newCanvasList = [...canvasList, JSON.stringify(stateArr)]
+
+ setCanvasList(newCanvasList)*/
+ }
+
+ const changeCanvas = (idx) => {
+ canvas?.clear()
+ const canvasState = JSON.parse(canvasList[idx])
+ }
+
return {
canvas,
addShape,
@@ -585,5 +579,7 @@ export function useCanvas(id) {
saveImage,
handleFlip,
setCanvasBackgroundWithDots,
+ addCanvas,
+ changeCanvas,
}
}
diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js
index d1a60e04..c22e9c7b 100644
--- a/src/hooks/useMode.js
+++ b/src/hooks/useMode.js
@@ -718,8 +718,6 @@ export function useMode() {
const handleOuterlinesTest = (polygon, offset = 71) => {
var offsetPoints = []
- debugger
-
const sortedIndex = getStartIndex(polygon.lines)
let tmpArraySorted = rearrangeArray(polygon.lines, sortedIndex)
diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js
index 7d1d63fc..5a3c3d31 100644
--- a/src/store/canvasAtom.js
+++ b/src/store/canvasAtom.js
@@ -35,3 +35,9 @@ export const wallState = atom({
default: {},
dangerouslyAllowMutability: true,
})
+
+export const canvasListState = atom({
+ key: 'canvas',
+ default: [],
+ dangerouslyAllowMutability: true,
+})