diff --git a/components/label/LabelNossr.tsx b/components/label/LabelNossr.tsx index f246eab..7af68f8 100644 --- a/components/label/LabelNossr.tsx +++ b/components/label/LabelNossr.tsx @@ -745,6 +745,11 @@ const LabelPage = ({ const requestSeq = ++latestTaskDetailRequestSeq try { usePaperStore.getState().setLoadingData(true) + usePaperStore.getState().resetRasterScale() + setLabel(new Map()) + setStateStack([]) + useRightToolsStore.getState().setPathGroupMap(new Map()) + useObjectStore.getState().resetPathAndOperationStatus() setHasReadyVideoFrame(false) setSourceVideoNames([]) // 获取当前任务全量数据 diff --git a/components/label/components/PaperContainer.tsx b/components/label/components/PaperContainer.tsx index 78689fe..6d56065 100644 --- a/components/label/components/PaperContainer.tsx +++ b/components/label/components/PaperContainer.tsx @@ -191,6 +191,8 @@ const PaperContainer = ( const { renderTag } = useRenderTag() const [setup, setSetup] = useState(false) + const labelRenderScaleRef = useRef>({}) + const renderedImageRef = useRef("") const paperScope = useRef(null) useEffect(() => { @@ -204,24 +206,34 @@ const PaperContainer = ( }, [firstRender]) useEffect(() => { + if (!imgSize) return const pScope = paperScope.current if (pScope) { const view = pScope.view - view.bounds.height = imgSize!.clientHeight - view.bounds.width = imgSize!.clientWidth - // 调整可见图层大小 - const layer = pScope.project.activeLayer - layer.view.viewSize = new paper.Size( - imgSize!.clientWidth, - imgSize!.clientHeight + const nextViewSize = new paper.Size( + imgSize.clientWidth, + imgSize.clientHeight ) + view.viewSize = nextViewSize view.center = new paper.Point( - view.bounds.width / 2, - view.bounds.height / 2 + nextViewSize.width / 2, + nextViewSize.height / 2 ) } }, [imgSize]) + useEffect(() => { + if (loadingData) { + labelRenderScaleRef.current = {} + renderedImageRef.current = "" + const group = usePaperStore.getState().group + if (group) { + group.removeChildren() + } + setRasterInited(false) + } + }, [loadingData]) + const renderSupportAnnotation = useCallback( async ( points: Array<[number, number]>, @@ -1370,54 +1382,65 @@ const PaperContainer = ( raster.scale(scale, new paper.Point(0, 0)) const currentImgScale = usePaperStore.getState().rasterScale[activeImage] + const currentLabelRenderScale = + labelRenderScaleRef.current[activeImage] + const scaleEpsilon = 0.000001 console.debug("[PaperContainer] raster scale reconcile", { image: activeImage, currentImgScale, + currentLabelRenderScale, nextScale: scale, - branch: !currentImgScale + branch: !currentLabelRenderScale ? "init-scale" - : currentImgScale !== scale + : Math.abs(currentLabelRenderScale - scale) > scaleEpsilon ? "rescale" : "keep", }) - // 当前图片无缩放比例或缩放比例不等于上次记录比例时 - if (!currentImgScale) { + // 当前图片无已应用的渲染比例时,按原始坐标转换到当前显示比例 + if (!currentLabelRenderScale) { setRasterScale(activeImage, scale) + labelRenderScaleRef.current[activeImage] = scale + if (useLabelStore.getState().label.get(activeImage)) { + const newData = adjustPoints( + activeImage, + useLabelStore.getState().label, + scale + ) + // 处理hollowPoints + useLabelStore.getState().setLabel(newData) + } + let stack = useLabelStore.getState().stateStack + if (stack.length) { + useLabelStore + .getState() + .setStateStack( + stack.map((item) => adjustPoints(activeImage, item, scale)) + ) + } + } else if ( + Math.abs(currentLabelRenderScale - scale) > scaleEpsilon + ) { + const scaleRatio = scale / currentLabelRenderScale + setRasterScale(activeImage, scale) + labelRenderScaleRef.current[activeImage] = scale const newData = adjustPoints( activeImage, useLabelStore.getState().label, - scale + scaleRatio ) - // 处理hollowPoints useLabelStore.getState().setLabel(newData) let stack = useLabelStore.getState().stateStack if (stack.length) { useLabelStore .getState() .setStateStack( - stack.map((item) => adjustPoints(activeImage, item, scale)) + stack.map((item) => + adjustPoints(activeImage, item, scaleRatio) + ) ) } } else if (currentImgScale !== scale) { - // 先将相关数据恢复到原始比例 - const restoreScale = - usePaperStore.getState().reciprocalRasterScale[activeImage] - const restoreData = adjustPoints( - activeImage, - useLabelStore.getState().label, - restoreScale - ) setRasterScale(activeImage, scale) - const newData = adjustPoints(activeImage, restoreData, scale) - useLabelStore.getState().setLabel(newData) - let stack = useLabelStore.getState().stateStack - if (stack.length) { - useLabelStore - .getState() - .setStateStack( - stack.map((item) => adjustPoints(activeImage, item, scale)) - ) - } } // 调整raster的左上角到(0,0) raster.position = new paper.Point( @@ -1429,6 +1452,7 @@ const PaperContainer = ( setRasterPath(new paper.Path.Rectangle(raster.bounds)) // 将raster置底 raster.sendToBack() + renderedImageRef.current = activeImage setRasterInited(true) console.log(usePaperStore.getState().group) usePaperStore.getState().group?.bringToFront() @@ -1471,9 +1495,98 @@ const PaperContainer = ( [renderAndScaleRaster] ) + const resizeCurrentImage = useCallback(() => { + if (!imgSize?.clientWidth || !imgSize?.clientHeight) return false + + const group = usePaperStore.getState().group + if (!group) return false + + const currentRaster = group.getItems({ data: { name: "pic" } })?.[0] as + | paper.Raster + | undefined + if (!currentRaster) return false + + const rawRasterSize = usePaperStore.getState().rasterSize[activeImage] + if (!rawRasterSize?.[0] || !rawRasterSize?.[1]) return false + + const nextScale = Math.min( + imgSize.clientWidth / rawRasterSize[0], + imgSize.clientHeight / rawRasterSize[1] + ) + if (!Number.isFinite(nextScale) || nextScale <= 0) return false + + const currentScale = + labelRenderScaleRef.current[activeImage] ?? + usePaperStore.getState().rasterScale[activeImage] + if (!currentScale || !Number.isFinite(currentScale) || currentScale <= 0) + return false + + const scaleEpsilon = 0.000001 + const scaleRatio = nextScale / currentScale + + if (Math.abs(scaleRatio - 1) <= scaleEpsilon) return true + + if (Math.abs(scaleRatio - 1) > scaleEpsilon) { + currentRaster.scale(scaleRatio, new paper.Point(0, 0)) + + const currentLabel = useLabelStore.getState().label + if (currentLabel.get(activeImage)) { + useLabelStore + .getState() + .setLabel(adjustPoints(activeImage, currentLabel, scaleRatio)) + } + + const stack = useLabelStore.getState().stateStack + if (stack.length) { + useLabelStore + .getState() + .setStateStack( + stack.map((item) => adjustPoints(activeImage, item, scaleRatio)) + ) + } + } + + currentRaster.position = new paper.Point( + currentRaster.bounds.width / 2, + currentRaster.bounds.height / 2 + ) + group.position = currentRaster.position + + group + .getItems({}) + .filter((item) => item !== currentRaster && item.data?.id) + .forEach((item) => { + item.remove() + }) + + setRasterPath(new paper.Path.Rectangle(currentRaster.bounds)) + setRasterScale(activeImage, nextScale) + labelRenderScaleRef.current[activeImage] = nextScale + + const imageData = useLabelStore.getState().label.get(activeImage) + if (imageData) { + objectOperations?.forEach((item) => { + renderPolygons(item.category_id.toString(), imageData) + }) + renderGroupPath() + renderTag() + } + + group.bringToFront() + return true + }, [ + activeImage, + imgSize?.clientHeight, + imgSize?.clientWidth, + objectOperations, + renderPolygons, + renderTag, + setRasterPath, + setRasterScale, + ]) + useEffect(() => { - const hasCachedImage = !!useImagesStore.getState().images.get(activeImage) - if (loadingData && !hasCachedImage) return + if (loadingData) return if (!imgSize?.clientWidth || !imgSize?.clientHeight) return const currentGroup = usePaperStore.getState().group if (currentGroup && projectDetail) { @@ -1485,6 +1598,15 @@ const PaperContainer = ( .getState() .setGroupScale(useTopToolsStore.getState().scale) } + + if ( + renderedImageRef.current === activeImage && + currentGroup.getItems({ data: { name: "pic" } })?.length + ) { + resizeCurrentImage() + return + } + loadImageAndPolygons( // storeLabel.get(activeImage), currentGroup @@ -1497,6 +1619,7 @@ const PaperContainer = ( loadImageAndPolygons, loadingData, projectDetail, + resizeCurrentImage, ]) useEffect(() => { diff --git a/components/label/useRenderTag.ts b/components/label/useRenderTag.ts index 04c2420..bda9efa 100644 --- a/components/label/useRenderTag.ts +++ b/components/label/useRenderTag.ts @@ -1,3 +1,4 @@ +import { useCallback } from "react" import paper from "paper" import { useLabelStore } from "./store" import { useBottomToolsStore } from "./useBottomToolsStore" @@ -14,7 +15,7 @@ export const removeTagTexts = (id?: number) => { } const useRenderTag = () => { - const renderTag = () => { + const renderTag = useCallback(() => { const dataMap = useLabelStore.getState().label const activeImage = useBottomToolsStore.getState().activeImage const group = usePaperStore.getState().group @@ -155,7 +156,7 @@ const useRenderTag = () => { } } } - } + }, []) return { renderTag,