aa
This commit is contained in:
parent
2f4560c2c9
commit
3d126dbfc7
@ -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() {
|
||||
<Button className="m-1 p-2" onClick={PolygonToLine}>
|
||||
PolygonToLine
|
||||
</Button>
|
||||
<Button className="m-1 p-2" onClick={addCanvas}>
|
||||
캔버스 추가
|
||||
</Button>
|
||||
<Button className="m-1 p-2" onClick={nextCanvas}>
|
||||
다음 캔버스
|
||||
</Button>
|
||||
<Button className="m-1 p-2" color={`${showControl ? 'primary' : 'default'}`} onClick={handleShowController}>
|
||||
canvas 컨트롤러 {`${showControl ? '숨기기' : '보이기'}`}
|
||||
</Button>
|
||||
|
||||
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -35,3 +35,9 @@ export const wallState = atom({
|
||||
default: {},
|
||||
dangerouslyAllowMutability: true,
|
||||
})
|
||||
|
||||
export const canvasListState = atom({
|
||||
key: 'canvas',
|
||||
default: [],
|
||||
dangerouslyAllowMutability: true,
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user