mirror of
https://github.com/ZSeven-W/openpencil.git
synced 2026-05-31 19:04:29 +07:00
feat(canvas): add frame name labels for top-level elements
This commit is contained in:
parent
2ab2a1d074
commit
b9241db194
2 changed files with 66 additions and 0 deletions
|
|
@ -6,6 +6,7 @@ import { useCanvasViewport } from './use-canvas-viewport'
|
|||
import { useCanvasSelection } from './use-canvas-selection'
|
||||
import { useCanvasSync } from './use-canvas-sync'
|
||||
import { useDimensionLabel } from './use-dimension-label'
|
||||
import { useFrameLabels } from './use-frame-labels'
|
||||
|
||||
export default function FabricCanvas() {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||
|
|
@ -18,6 +19,7 @@ export default function FabricCanvas() {
|
|||
useCanvasSelection()
|
||||
useCanvasSync()
|
||||
useDimensionLabel(containerRef)
|
||||
useFrameLabels()
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
64
src/canvas/use-frame-labels.ts
Normal file
64
src/canvas/use-frame-labels.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import { useEffect } from 'react'
|
||||
import { useCanvasStore } from '@/stores/canvas-store'
|
||||
import { useDocumentStore } from '@/stores/document-store'
|
||||
import type { FabricObjectWithPenId } from './canvas-object-factory'
|
||||
|
||||
const LABEL_FONT_SIZE = 12
|
||||
const LABEL_OFFSET_Y = 6
|
||||
const LABEL_COLOR = '#999999'
|
||||
|
||||
export function useFrameLabels() {
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
const canvas = useCanvasStore.getState().fabricCanvas
|
||||
if (!canvas) return
|
||||
clearInterval(interval)
|
||||
|
||||
const onAfterRender = () => {
|
||||
const el = canvas.lowerCanvasEl
|
||||
if (!el) return
|
||||
const ctx = el.getContext('2d')
|
||||
if (!ctx) return
|
||||
|
||||
const vpt = canvas.viewportTransform
|
||||
if (!vpt) return
|
||||
const zoom = vpt[0]
|
||||
const dpr = el.width / el.offsetWidth
|
||||
|
||||
const store = useDocumentStore.getState()
|
||||
// Only top-level document children show labels
|
||||
const topIds = new Set(store.document.children.map((c) => c.id))
|
||||
const objects = canvas.getObjects() as FabricObjectWithPenId[]
|
||||
|
||||
ctx.save()
|
||||
const fontSize = LABEL_FONT_SIZE * dpr
|
||||
ctx.font = `500 ${fontSize}px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`
|
||||
ctx.fillStyle = LABEL_COLOR
|
||||
|
||||
for (const obj of objects) {
|
||||
if (!obj.penNodeId) continue
|
||||
if (!topIds.has(obj.penNodeId)) continue
|
||||
|
||||
const node = store.getNodeById(obj.penNodeId)
|
||||
if (!node) continue
|
||||
|
||||
const name = node.name ?? node.type
|
||||
const x = ((obj.left ?? 0) * zoom + vpt[4]) * dpr
|
||||
const y = ((obj.top ?? 0) * zoom + vpt[5]) * dpr
|
||||
|
||||
ctx.fillText(name, x, y - LABEL_OFFSET_Y * dpr)
|
||||
}
|
||||
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
canvas.on('after:render', onAfterRender)
|
||||
|
||||
return () => {
|
||||
canvas.off('after:render', onAfterRender)
|
||||
}
|
||||
}, 100)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}, [])
|
||||
}
|
||||
Loading…
Reference in a new issue