189 lines
6.6 KiB
TypeScript
189 lines
6.6 KiB
TypeScript
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
|