import { useCallback } from "react" import paper from "paper" import { useLabelStore } from "./store" import { useBottomToolsStore } from "./useBottomToolsStore" import { usePaperStore } from "./usePaperStore" import { useTopToolsStore } from "./useTopToolsStore" export const removeTagTexts = (id?: number) => { const group = usePaperStore.getState().group if (!group) return const items = id ? group.getItems({ data: { id, type: "tag" } }) : group.getItems({ data: { type: "tag" } }) items.forEach((item) => item.remove()) } const useRenderTag = () => { const renderTag = useCallback(() => { const dataMap = useLabelStore.getState().label const activeImage = useBottomToolsStore.getState().activeImage const group = usePaperStore.getState().group if (!group) return const visible = useTopToolsStore.getState().showTags const configs = useTopToolsStore.getState().showTagsConfigs const groupScale = Number.isFinite(group.scaling?.x) && group.scaling.x !== 0 ? group.scaling.x : 1 const applyTagCompensation = ( item: paper.Item, anchor: [number, number] ) => { if (Math.abs(groupScale - 1) < 0.000001) return item.scale(1 / groupScale, new paper.Point(anchor[0], anchor[1])) } // 清空之前渲染的标签 removeTagTexts() for (const [imageId, categoryMap] of dataMap) { if (imageId === activeImage) { for (const [categoryId, labelList] of categoryMap) { let category = useTopToolsStore .getState() .objectOperations.find( (item) => item.category_id.toString() === categoryId )! const { label_class } = category labelList.forEach(([id, _d, detail]) => { const path = usePaperStore.getState().getItemById(id) if (path) { const bounds = path.bounds const tagAnchor: [number, number] = [bounds.left, bounds.top - 6] const pos = [...tagAnchor] let pathData = path.data let content = `` if (configs.includes("ID")) content += `${id}${ path.data.parentGroupId ? `@${path.data.parentGroupId}` : "" }` if (configs.includes("类别")) content += ` ${label_class}` if ( detail.sub_attributes && Object.keys(detail.sub_attributes).length ) { Object.keys(detail.sub_attributes).forEach((key) => { if (configs.includes("子属性")) content += ` ${key}:` if (configs.includes("属性值")) content += `${detail.sub_attributes[key]};` }) } // 文本 const text = new paper.PointText(pos) text.set({ content, fontSize: 12, fontWeight: "bold", fillColor: "black", data: { id, type: "tag", tag_category: "text", tag_anchor: tagAnchor, }, parent: group, visible, }) applyTagCompensation(text, tagAnchor) // 文本框 const textMask = new paper.Path.Rectangle(text.bounds) textMask.set({ fillColor: pathData.fillColor, strokeColor: pathData.strokeColor, strokeWidth: 1, strokeScaling: false, data: { id, type: "tag", tag_category: "text_mask", tag_anchor: tagAnchor, }, parent: group, visible, }) applyTagCompensation(textMask, tagAnchor) // 标注对象外接框 const mask = new paper.Path.Rectangle(bounds) mask.set({ strokeColor: pathData.strokeColor, strokeWidth: 2, strokeScaling: false, data: { id, type: "tag", tag_category: "mask", }, parent: group, visible: visible && configs.includes("外框"), }) // 标注对象点id if (path instanceof paper.CompoundPath) { let index = 1 path.children.forEach((child) => { const segments = (child as paper.Path).segments segments.forEach((segment) => { const pointTextPosition: [number, number] = [ segment.point.x - 10, segment.point.y + 5, ] const pointText = new paper.PointText(pointTextPosition) pointText.set({ content: index, fontSize: 12, fontWeight: "bold", fillColor: pathData.strokeColor, data: { id, type: "tag", tag_category: "point_text", tag_anchor: pointTextPosition, }, parent: group, visible: visible && configs.includes("点ID"), }) applyTagCompensation(pointText, pointTextPosition) index++ }) }) } else { const segments = (path as paper.Path).segments segments.forEach((segment, index) => { const pointTextPosition: [number, number] = [ segment.point.x - 10, segment.point.y + 5, ] const pointText = new paper.PointText(pointTextPosition) pointText.set({ content: index + 1, fontSize: 12, fontWeight: "bold", fillColor: pathData.strokeColor, data: { id, type: "tag", tag_category: "point_text", tag_anchor: pointTextPosition, }, parent: group, visible: visible && configs.includes("点ID"), }) applyTagCompensation(pointText, pointTextPosition) }) } } }) } } } }, []) return { renderTag, } } export default useRenderTag