186 lines
5.4 KiB
TypeScript
186 lines
5.4 KiB
TypeScript
'use client'
|
|
|
|
import React, { useEffect, useRef, useState } from "react"
|
|
import { useProject } from "../../context/Project/provider"
|
|
import { ipc } from "../../wailsjs/wailsjs/go/models"
|
|
|
|
|
|
const loadImage = (path: string): Promise<HTMLImageElement> => {
|
|
return new Promise((resolve, reject) => {
|
|
const image = new Image()
|
|
image.src = path
|
|
image.onload = () => resolve(image)
|
|
image.onerror = (error) => reject(error)
|
|
})
|
|
}
|
|
|
|
const DocumentRenderer = () => {
|
|
const { getSelectedDocument, requestAddArea } = useProject()
|
|
const [canvasSize, setCanvasSize] = useState({ width: 0, height: 0 })
|
|
const selectedDocument = getSelectedDocument()
|
|
const areas = selectedDocument?.areas
|
|
const documentCanvas = useRef<HTMLCanvasElement>(null)
|
|
const areaCanvas = useRef<HTMLCanvasElement>(null)
|
|
const drawingCanvas = useRef<HTMLCanvasElement>(null)
|
|
|
|
// console.log('selectedDocument: ', selectedDocument)
|
|
|
|
let downClickX = 0
|
|
let downClickY = 0
|
|
let isMouseDown = false
|
|
|
|
const applyCanvasSizes = (size: { width: number, height: number }) => {
|
|
const documentCanvasInstance = documentCanvas.current
|
|
if (!documentCanvasInstance) return
|
|
documentCanvasInstance.width = size.width
|
|
documentCanvasInstance.height = size.height
|
|
|
|
const areaCanvasInstance = areaCanvas.current
|
|
if (!areaCanvasInstance) return
|
|
areaCanvasInstance.width = size.width
|
|
areaCanvasInstance.height = size.height
|
|
|
|
const drawingCanvasInstance = drawingCanvas.current
|
|
if (!drawingCanvasInstance) return
|
|
drawingCanvasInstance.width = size.width
|
|
drawingCanvasInstance.height = size.height
|
|
}
|
|
|
|
const applyDocumentToCanvas = async (path: string) => {
|
|
const image = await loadImage(path)
|
|
applyCanvasSizes({ width: image.naturalWidth, height: image.naturalHeight })
|
|
|
|
const documentCanvasInstance = documentCanvas.current
|
|
if (!documentCanvasInstance) return
|
|
|
|
const context = documentCanvasInstance.getContext('2d')
|
|
if (!context) return
|
|
context.drawImage(image, 0, 0, image.width, image.height)
|
|
|
|
if (areas) applyAreasToCanvas()
|
|
}
|
|
|
|
const applyAreasToCanvas = () => {
|
|
if (!areas || !areas.length) return
|
|
const areaCanvasInstance = areaCanvas.current
|
|
if (!areaCanvasInstance) return
|
|
const context = areaCanvasInstance.getContext("2d")
|
|
if (!context) return
|
|
|
|
context.clearRect(0, 0, areaCanvasInstance.width, areaCanvasInstance.height)
|
|
|
|
areas.forEach(a => {
|
|
console.log('area: ', a)
|
|
const width = a.endX - a.startX
|
|
const height = a.endY - a.startY
|
|
const x = a.startX
|
|
const y = a.startY
|
|
console.log(`context.rect: `, x, y, width, height)
|
|
context.rect(x, y, width, height)
|
|
context.lineWidth = 2
|
|
context.strokeStyle = '#dc8dec'
|
|
context.stroke()
|
|
})
|
|
}
|
|
|
|
const handleMouseDown = (e: React.MouseEvent) => {
|
|
const drawingCanvasInstance = drawingCanvas.current
|
|
if (!drawingCanvasInstance) return
|
|
|
|
downClickX = e.nativeEvent.offsetX
|
|
downClickY = e.nativeEvent.offsetY
|
|
isMouseDown = true
|
|
}
|
|
|
|
const handleMouseUp = async (e: React.MouseEvent) => {
|
|
const drawingCanvasInstance = drawingCanvas.current
|
|
if (!drawingCanvasInstance) return
|
|
|
|
const mouseX = e.nativeEvent.offsetX
|
|
const mouseY = e.nativeEvent.offsetY
|
|
|
|
let startX: number, endX: number
|
|
if (downClickX < mouseX) {
|
|
startX = downClickX
|
|
endX = mouseX
|
|
} else {
|
|
startX = mouseX
|
|
endX = downClickX
|
|
}
|
|
|
|
let startY: number, endY: number
|
|
if (downClickY < mouseY) {
|
|
startY = downClickY
|
|
endY = mouseY
|
|
} else {
|
|
startY = mouseY
|
|
endY = downClickY
|
|
}
|
|
|
|
if (selectedDocument?.id)
|
|
requestAddArea(selectedDocument.id, { startX, startY, endX, endY }).then(response => {
|
|
console.log('requestAddArea: ', response)
|
|
}).catch(err => console.log('err requestAddArea :', err))
|
|
|
|
const context = drawingCanvasInstance.getContext('2d')
|
|
context?.clearRect(0, 0, drawingCanvasInstance.width, drawingCanvasInstance.height)
|
|
isMouseDown = false
|
|
downClickX = 0
|
|
downClickY = 0
|
|
}
|
|
|
|
const handleMouseMove = (e: React.MouseEvent) => {
|
|
const drawingCanvasInstance = drawingCanvas.current
|
|
if (!drawingCanvasInstance) return
|
|
|
|
let mouseX = e.nativeEvent.offsetX
|
|
let mouseY = e.nativeEvent.offsetY
|
|
|
|
if (isMouseDown) {
|
|
const context = drawingCanvasInstance.getContext('2d')
|
|
if (!context) return
|
|
|
|
context.clearRect(0, 0, drawingCanvasInstance.width, drawingCanvasInstance.height)
|
|
context.beginPath()
|
|
const width = mouseX - downClickX
|
|
const height = mouseY - downClickY
|
|
context.rect(downClickX, downClickY, width, height)
|
|
context.strokeStyle = '#000'
|
|
context.lineWidth = 2
|
|
context.stroke()
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (selectedDocument?.path) applyDocumentToCanvas(selectedDocument.path)
|
|
}, [selectedDocument?.id])
|
|
|
|
useEffect(() => {
|
|
applyAreasToCanvas()
|
|
}, [areas, areas?.length])
|
|
|
|
return <div className="relative">
|
|
<canvas
|
|
className="absolute"
|
|
ref={documentCanvas}
|
|
/>
|
|
<canvas
|
|
className="absolute"
|
|
ref={areaCanvas}
|
|
// width={canvasSize.width}
|
|
// height={canvasSize.height}
|
|
/>
|
|
<canvas
|
|
className="absolute"
|
|
ref={drawingCanvas}
|
|
onMouseDown={handleMouseDown}
|
|
onMouseUp={handleMouseUp}
|
|
onMouseMove={handleMouseMove}
|
|
// width={canvasSize.width}
|
|
// height={canvasSize.height}
|
|
/>
|
|
</div>
|
|
}
|
|
|
|
export default DocumentRenderer
|