fix(scale): fix
This commit is contained in:
@@ -59,6 +59,7 @@ import { findGroupKey, isEditableKeyboardTarget } from "./util"
|
|||||||
import { safeClone } from "./utils/clone"
|
import { safeClone } from "./utils/clone"
|
||||||
import { labelTypeMap } from "./utils/constants"
|
import { labelTypeMap } from "./utils/constants"
|
||||||
import { toggleObjectHideByShortcut } from "./utils/objectVisibility"
|
import { toggleObjectHideByShortcut } from "./utils/objectVisibility"
|
||||||
|
import { getDisplayedImageScale } from "./utils/scale"
|
||||||
|
|
||||||
// Splitter component - will need custom implementation or alternative
|
// Splitter component - will need custom implementation or alternative
|
||||||
|
|
||||||
@@ -325,6 +326,13 @@ const LabelPage = ({
|
|||||||
setObjectOperations,
|
setObjectOperations,
|
||||||
} = useTopToolsStore()
|
} = useTopToolsStore()
|
||||||
const { activeImage } = useBottomToolsStore()
|
const { activeImage } = useBottomToolsStore()
|
||||||
|
const activeRasterScale = usePaperStore(
|
||||||
|
(state) => state.rasterScale[activeImage] ?? 1
|
||||||
|
)
|
||||||
|
const activeRasterSize = usePaperStore(
|
||||||
|
(state) => state.rasterSize[activeImage] ?? null
|
||||||
|
)
|
||||||
|
const currentGroup = usePaperStore((state) => state.group)
|
||||||
const {
|
const {
|
||||||
setDescOperations,
|
setDescOperations,
|
||||||
metaOperation,
|
metaOperation,
|
||||||
@@ -333,6 +341,28 @@ const LabelPage = ({
|
|||||||
setQaData,
|
setQaData,
|
||||||
resetData,
|
resetData,
|
||||||
} = useDescToolsStore()
|
} = useDescToolsStore()
|
||||||
|
const displayedImageScale = useMemo(() => {
|
||||||
|
return getDisplayedImageScale({
|
||||||
|
rasterScale: activeRasterScale,
|
||||||
|
viewScale: scale,
|
||||||
|
})
|
||||||
|
}, [activeRasterScale, scale])
|
||||||
|
const scaleOffsets = useMemo(() => {
|
||||||
|
if (!currentGroup || !activeRasterSize?.[0] || !activeRasterSize?.[1]) {
|
||||||
|
return {
|
||||||
|
offsetX: 0,
|
||||||
|
offsetY: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayedWidth = activeRasterSize[0] * displayedImageScale
|
||||||
|
const displayedHeight = activeRasterSize[1] * displayedImageScale
|
||||||
|
|
||||||
|
return {
|
||||||
|
offsetX: displayedWidth / 2 - currentGroup.position.x,
|
||||||
|
offsetY: displayedHeight / 2 - currentGroup.position.y,
|
||||||
|
}
|
||||||
|
}, [activeRasterSize, currentGroup, displayedImageScale])
|
||||||
|
|
||||||
const asyncGetProjectDetail = useCallback(async () => {
|
const asyncGetProjectDetail = useCallback(async () => {
|
||||||
if (projectId) {
|
if (projectId) {
|
||||||
@@ -2634,18 +2664,18 @@ const LabelPage = ({
|
|||||||
style={{ overflow: "hidden" }}>
|
style={{ overflow: "hidden" }}>
|
||||||
<ScaleComponent
|
<ScaleComponent
|
||||||
options={{
|
options={{
|
||||||
offsetX: 0,
|
offsetX: scaleOffsets.offsetX,
|
||||||
offsetY: 0,
|
offsetY: scaleOffsets.offsetY,
|
||||||
scale: scale,
|
scale: displayedImageScale,
|
||||||
}}
|
}}
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
/>
|
/>
|
||||||
<Flex h="calc(100% - 32px)">
|
<Flex h="calc(100% - 32px)">
|
||||||
<ScaleComponent
|
<ScaleComponent
|
||||||
options={{
|
options={{
|
||||||
offsetX: 0,
|
offsetX: scaleOffsets.offsetX,
|
||||||
offsetY: 0,
|
offsetY: scaleOffsets.offsetY,
|
||||||
scale: scale,
|
scale: displayedImageScale,
|
||||||
}}
|
}}
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,9 +4,13 @@ import React, {
|
|||||||
useCallback,
|
useCallback,
|
||||||
useEffect,
|
useEffect,
|
||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
|
useMemo,
|
||||||
useRef,
|
useRef,
|
||||||
} from "react"
|
} from "react"
|
||||||
|
import { useBottomToolsStore } from "../useBottomToolsStore"
|
||||||
|
import { usePaperStore } from "../usePaperStore"
|
||||||
import { useTopToolsStore } from "../useTopToolsStore"
|
import { useTopToolsStore } from "../useTopToolsStore"
|
||||||
|
import { getDisplayedImageScale } from "../utils/scale"
|
||||||
|
|
||||||
interface CrosshairComponentProps {
|
interface CrosshairComponentProps {
|
||||||
isCarved: boolean
|
isCarved: boolean
|
||||||
@@ -18,7 +22,17 @@ const CrosshairComponent = (
|
|||||||
) => {
|
) => {
|
||||||
const { isCarved } = props
|
const { isCarved } = props
|
||||||
|
|
||||||
const { scale } = useTopToolsStore()
|
const scale = useTopToolsStore((state) => state.scale)
|
||||||
|
const activeImage = useBottomToolsStore((state) => state.activeImage)
|
||||||
|
const rasterScale = usePaperStore(
|
||||||
|
(state) => state.rasterScale[activeImage] ?? 1
|
||||||
|
)
|
||||||
|
const displayedScale = useMemo(() => {
|
||||||
|
return getDisplayedImageScale({
|
||||||
|
rasterScale,
|
||||||
|
viewScale: scale,
|
||||||
|
})
|
||||||
|
}, [rasterScale, scale])
|
||||||
|
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null)
|
const canvasRef = useRef<HTMLCanvasElement>(null)
|
||||||
const lastPointerRef = useRef<{ x: number; y: number } | null>(null)
|
const lastPointerRef = useRef<{ x: number; y: number } | null>(null)
|
||||||
@@ -82,9 +96,9 @@ const CrosshairComponent = (
|
|||||||
ctx.lineWidth = carveLineWidth
|
ctx.lineWidth = carveLineWidth
|
||||||
|
|
||||||
// 间隔
|
// 间隔
|
||||||
const sparsity = getSparsity(scale)
|
const sparsity = getSparsity(displayedScale)
|
||||||
const part = 10
|
const part = 10
|
||||||
const pixelPerUnit = scale * sparsity
|
const pixelPerUnit = displayedScale * sparsity
|
||||||
const gap = pixelPerUnit / part
|
const gap = pixelPerUnit / part
|
||||||
|
|
||||||
const fixed = getFixed(sparsity)
|
const fixed = getFixed(sparsity)
|
||||||
@@ -136,7 +150,7 @@ const CrosshairComponent = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[isCarved, scale]
|
[displayedScale, isCarved]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ import {
|
|||||||
paperShapeToMultiPolygon,
|
paperShapeToMultiPolygon,
|
||||||
} from "../utils/geometry/booleanAdapter"
|
} from "../utils/geometry/booleanAdapter"
|
||||||
import { adjustPoints } from "../utils/paperjs"
|
import { adjustPoints } from "../utils/paperjs"
|
||||||
|
import {
|
||||||
|
getDisplayedImageScale,
|
||||||
|
getViewScaleFromDisplayedScale,
|
||||||
|
} from "../utils/scale"
|
||||||
import AssistShapeComponent from "./AssistShapeComponent"
|
import AssistShapeComponent from "./AssistShapeComponent"
|
||||||
import CrosshairComponent from "./CrosshairComponent"
|
import CrosshairComponent from "./CrosshairComponent"
|
||||||
import { renderOperationIcon } from "./RightObjectTools"
|
import { renderOperationIcon } from "./RightObjectTools"
|
||||||
@@ -2923,6 +2927,80 @@ const PaperContainer = (
|
|||||||
}
|
}
|
||||||
}, [stopMiddleMousePan])
|
}, [stopMiddleMousePan])
|
||||||
|
|
||||||
|
const getPicRasters = useCallback((group: paper.Group) => {
|
||||||
|
return group
|
||||||
|
.getItems({ data: { name: "pic" } })
|
||||||
|
.filter((item): item is paper.Raster => item instanceof paper.Raster)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const getCachedDisplayedScale = useCallback(
|
||||||
|
(group: paper.Group | null | undefined) => {
|
||||||
|
if (!group || !saveCurrentScale) return null
|
||||||
|
const persistedDisplayedScale = useTopToolsStore.getState().displayedScale
|
||||||
|
|
||||||
|
const rasterItems = getPicRasters(group)
|
||||||
|
if (!rasterItems.length) {
|
||||||
|
return Number.isFinite(persistedDisplayedScale) &&
|
||||||
|
persistedDisplayedScale > 0
|
||||||
|
? persistedDisplayedScale
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
const currentRaster = rasterItems.length
|
||||||
|
? rasterItems[rasterItems.length - 1]
|
||||||
|
: null
|
||||||
|
const imageId =
|
||||||
|
typeof currentRaster?.data?.imageId === "string"
|
||||||
|
? currentRaster.data.imageId
|
||||||
|
: useBottomToolsStore.getState().activeImage
|
||||||
|
|
||||||
|
if (!imageId) {
|
||||||
|
return Number.isFinite(persistedDisplayedScale) &&
|
||||||
|
persistedDisplayedScale > 0
|
||||||
|
? persistedDisplayedScale
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewScale =
|
||||||
|
Number.isFinite(group.scaling?.x) && group.scaling.x > 0
|
||||||
|
? group.scaling.x
|
||||||
|
: useTopToolsStore.getState().scale
|
||||||
|
|
||||||
|
return getDisplayedImageScale({
|
||||||
|
rasterScale: usePaperStore.getState().rasterScale[imageId],
|
||||||
|
viewScale,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
[getPicRasters, saveCurrentScale]
|
||||||
|
)
|
||||||
|
|
||||||
|
const getTargetGroupScale = useCallback(
|
||||||
|
({
|
||||||
|
rasterScale,
|
||||||
|
cachedDisplayedScale,
|
||||||
|
fallbackScale,
|
||||||
|
}: {
|
||||||
|
rasterScale: number
|
||||||
|
cachedDisplayedScale?: number | null
|
||||||
|
fallbackScale?: number | null
|
||||||
|
}) => {
|
||||||
|
if (
|
||||||
|
saveCurrentScale &&
|
||||||
|
Number.isFinite(cachedDisplayedScale) &&
|
||||||
|
Number(cachedDisplayedScale) > 0
|
||||||
|
) {
|
||||||
|
return getViewScaleFromDisplayedScale({
|
||||||
|
displayedScale: cachedDisplayedScale,
|
||||||
|
rasterScale,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return Number.isFinite(fallbackScale) && Number(fallbackScale) > 0
|
||||||
|
? Number(fallbackScale)
|
||||||
|
: 1
|
||||||
|
},
|
||||||
|
[saveCurrentScale]
|
||||||
|
)
|
||||||
|
|
||||||
const getTargetGroupPosition = useCallback(
|
const getTargetGroupPosition = useCallback(
|
||||||
({
|
({
|
||||||
defaultPosition,
|
defaultPosition,
|
||||||
@@ -2958,6 +3036,7 @@ const PaperContainer = (
|
|||||||
clearPendingFrameSwitch(token)
|
clearPendingFrameSwitch(token)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const cachedDisplayedScale = getCachedDisplayedScale(currentVisibleGroup)
|
||||||
const preserveGroupPosition =
|
const preserveGroupPosition =
|
||||||
saveCurrentScale &&
|
saveCurrentScale &&
|
||||||
currentVisibleGroup.getItems({ data: { name: "pic" } }).length > 0
|
currentVisibleGroup.getItems({ data: { name: "pic" } }).length > 0
|
||||||
@@ -3034,6 +3113,11 @@ const PaperContainer = (
|
|||||||
const scaleX = canvasWidth / raster.bounds.width
|
const scaleX = canvasWidth / raster.bounds.width
|
||||||
const scaleY = canvasHeight / raster.bounds.height
|
const scaleY = canvasHeight / raster.bounds.height
|
||||||
const scale = Math.min(scaleX, scaleY)
|
const scale = Math.min(scaleX, scaleY)
|
||||||
|
const targetGroupScale = getTargetGroupScale({
|
||||||
|
rasterScale: scale,
|
||||||
|
cachedDisplayedScale,
|
||||||
|
fallbackScale: currentVisibleGroup.scaling.x,
|
||||||
|
})
|
||||||
|
|
||||||
if (!Number.isFinite(scale) || scale <= 0) {
|
if (!Number.isFinite(scale) || scale <= 0) {
|
||||||
cleanupStagingGroup()
|
cleanupStagingGroup()
|
||||||
@@ -3048,6 +3132,10 @@ const PaperContainer = (
|
|||||||
raster.bounds.width / 2,
|
raster.bounds.width / 2,
|
||||||
raster.bounds.height / 2
|
raster.bounds.height / 2
|
||||||
)
|
)
|
||||||
|
stagingGroup.scaling = new paper.Point(
|
||||||
|
targetGroupScale,
|
||||||
|
targetGroupScale
|
||||||
|
)
|
||||||
const centeredGroupPosition = new paper.Point(
|
const centeredGroupPosition = new paper.Point(
|
||||||
raster.bounds.width / 2,
|
raster.bounds.width / 2,
|
||||||
raster.bounds.height / 2
|
raster.bounds.height / 2
|
||||||
@@ -3074,6 +3162,7 @@ const PaperContainer = (
|
|||||||
|
|
||||||
const previousGroup = usePaperStore.getState().group
|
const previousGroup = usePaperStore.getState().group
|
||||||
setGroup(stagingGroup)
|
setGroup(stagingGroup)
|
||||||
|
useTopToolsStore.getState().setScale(targetGroupScale)
|
||||||
setRasterPath(new paper.Path.Rectangle(raster.bounds))
|
setRasterPath(new paper.Path.Rectangle(raster.bounds))
|
||||||
renderedImageRef.current = imageName
|
renderedImageRef.current = imageName
|
||||||
commitFrameSwitch(imageName, token)
|
commitFrameSwitch(imageName, token)
|
||||||
@@ -3101,6 +3190,8 @@ const PaperContainer = (
|
|||||||
[
|
[
|
||||||
clearPendingFrameSwitch,
|
clearPendingFrameSwitch,
|
||||||
commitFrameSwitch,
|
commitFrameSwitch,
|
||||||
|
getCachedDisplayedScale,
|
||||||
|
getTargetGroupScale,
|
||||||
getTargetGroupPosition,
|
getTargetGroupPosition,
|
||||||
imgSize?.clientHeight,
|
imgSize?.clientHeight,
|
||||||
imgSize?.clientWidth,
|
imgSize?.clientWidth,
|
||||||
@@ -3166,12 +3257,6 @@ const PaperContainer = (
|
|||||||
)
|
)
|
||||||
decodeFrameImageRef.current = decodeFrameImage
|
decodeFrameImageRef.current = decodeFrameImage
|
||||||
|
|
||||||
const getPicRasters = useCallback((group: paper.Group) => {
|
|
||||||
return group
|
|
||||||
.getItems({ data: { name: "pic" } })
|
|
||||||
.filter((item): item is paper.Raster => item instanceof paper.Raster)
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const cancelRasterFadeTransition = useCallback(() => {
|
const cancelRasterFadeTransition = useCallback(() => {
|
||||||
rasterFadeTransitionIdRef.current += 1
|
rasterFadeTransitionIdRef.current += 1
|
||||||
if (
|
if (
|
||||||
@@ -3194,6 +3279,7 @@ const PaperContainer = (
|
|||||||
if (activeImage && projectDetail?.id) {
|
if (activeImage && projectDetail?.id) {
|
||||||
const requestId = ++rasterLoadRequestIdRef.current
|
const requestId = ++rasterLoadRequestIdRef.current
|
||||||
const requestImage = activeImage
|
const requestImage = activeImage
|
||||||
|
const cachedDisplayedScale = getCachedDisplayedScale(paperGroup)
|
||||||
const preserveGroupPosition =
|
const preserveGroupPosition =
|
||||||
saveCurrentScale && getPicRasters(paperGroup).length > 0
|
saveCurrentScale && getPicRasters(paperGroup).length > 0
|
||||||
const preservedGroupPosition = preserveGroupPosition
|
const preservedGroupPosition = preserveGroupPosition
|
||||||
@@ -3275,6 +3361,11 @@ const PaperContainer = (
|
|||||||
])
|
])
|
||||||
|
|
||||||
let scale = Math.min(scaleX, scaleY) // Maintain aspect ratio
|
let scale = Math.min(scaleX, scaleY) // Maintain aspect ratio
|
||||||
|
const targetGroupScale = getTargetGroupScale({
|
||||||
|
rasterScale: scale,
|
||||||
|
cachedDisplayedScale,
|
||||||
|
fallbackScale: paperGroup.scaling.x,
|
||||||
|
})
|
||||||
if (!Number.isFinite(scale) || scale <= 0) {
|
if (!Number.isFinite(scale) || scale <= 0) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"[PaperContainer] skip raster scale: invalid scale",
|
"[PaperContainer] skip raster scale: invalid scale",
|
||||||
@@ -3357,6 +3448,10 @@ const PaperContainer = (
|
|||||||
raster.bounds.width / 2,
|
raster.bounds.width / 2,
|
||||||
raster.bounds.height / 2
|
raster.bounds.height / 2
|
||||||
)
|
)
|
||||||
|
paperGroup.scaling = new paper.Point(
|
||||||
|
targetGroupScale,
|
||||||
|
targetGroupScale
|
||||||
|
)
|
||||||
const centeredGroupPosition = new paper.Point(
|
const centeredGroupPosition = new paper.Point(
|
||||||
raster.bounds.width / 2,
|
raster.bounds.width / 2,
|
||||||
raster.bounds.height / 2
|
raster.bounds.height / 2
|
||||||
@@ -3422,6 +3517,7 @@ const PaperContainer = (
|
|||||||
setRasterPath(new paper.Path.Rectangle(raster.bounds))
|
setRasterPath(new paper.Path.Rectangle(raster.bounds))
|
||||||
raster.sendToBack()
|
raster.sendToBack()
|
||||||
renderedImageRef.current = requestImage
|
renderedImageRef.current = requestImage
|
||||||
|
useTopToolsStore.getState().setScale(targetGroupScale)
|
||||||
setRasterInited(true)
|
setRasterInited(true)
|
||||||
usePaperStore.getState().group?.bringToFront()
|
usePaperStore.getState().group?.bringToFront()
|
||||||
}
|
}
|
||||||
@@ -3439,7 +3535,9 @@ const PaperContainer = (
|
|||||||
activeImage,
|
activeImage,
|
||||||
cancelRasterFadeTransition,
|
cancelRasterFadeTransition,
|
||||||
decodeFrameImage,
|
decodeFrameImage,
|
||||||
|
getCachedDisplayedScale,
|
||||||
getPicRasters,
|
getPicRasters,
|
||||||
|
getTargetGroupScale,
|
||||||
getTargetGroupPosition,
|
getTargetGroupPosition,
|
||||||
imgSize?.clientHeight,
|
imgSize?.clientHeight,
|
||||||
imgSize?.clientWidth,
|
imgSize?.clientWidth,
|
||||||
|
|||||||
@@ -1,25 +1,75 @@
|
|||||||
import { ActionIcon, Flex, NumberInput, Stack, Text } from "@mantine/core"
|
import { ActionIcon, Flex, NumberInput, Stack, Text } from "@mantine/core"
|
||||||
import { IconMinus, IconPlus, IconRefresh } from "@tabler/icons-react"
|
import { IconMinus, IconPlus, IconRefresh } from "@tabler/icons-react"
|
||||||
import paper from "paper"
|
import paper from "paper"
|
||||||
import { useMemo } from "react"
|
import { useEffect, useMemo, useRef } from "react"
|
||||||
import { useKeyEventStore } from "../store"
|
import { useKeyEventStore } from "../store"
|
||||||
|
import { useBottomToolsStore } from "../useBottomToolsStore"
|
||||||
import { usePaperStore } from "../usePaperStore"
|
import { usePaperStore } from "../usePaperStore"
|
||||||
import { useTopToolsStore } from "../useTopToolsStore"
|
import { useTopToolsStore } from "../useTopToolsStore"
|
||||||
|
import {
|
||||||
|
getDisplayedImageScale,
|
||||||
|
getViewScaleFromDisplayedScale,
|
||||||
|
} from "../utils/scale"
|
||||||
|
|
||||||
const ScaleToolContainer = () => {
|
const ScaleToolContainer = () => {
|
||||||
const { scale, setScale } = useTopToolsStore()
|
const {
|
||||||
|
scale,
|
||||||
|
setScale,
|
||||||
|
displayedScale: savedDisplayedScale,
|
||||||
|
setDisplayedScale,
|
||||||
|
} = useTopToolsStore()
|
||||||
const { setFocusInput } = useKeyEventStore()
|
const { setFocusInput } = useKeyEventStore()
|
||||||
|
const activeImage = useBottomToolsStore((state) => state.activeImage)
|
||||||
|
const rasterScale = usePaperStore((state) => state.rasterScale[activeImage])
|
||||||
|
const rasterSize = usePaperStore((state) => state.rasterSize[activeImage])
|
||||||
|
const paperScope = usePaperStore((state) => state.paperScope)
|
||||||
|
const group = usePaperStore((state) => state.group)
|
||||||
|
const lastDisplayedScaleRef = useRef(
|
||||||
|
Number.isFinite(savedDisplayedScale) && savedDisplayedScale > 0
|
||||||
|
? savedDisplayedScale
|
||||||
|
: 1
|
||||||
|
)
|
||||||
|
|
||||||
|
const displayedScale = useMemo(() => {
|
||||||
|
const hasValidRasterScale =
|
||||||
|
Number.isFinite(rasterScale) && Number(rasterScale) > 0
|
||||||
|
|
||||||
|
if (!activeImage || !hasValidRasterScale) {
|
||||||
|
if (group) return lastDisplayedScaleRef.current
|
||||||
|
return Number.isFinite(savedDisplayedScale) && savedDisplayedScale > 0
|
||||||
|
? savedDisplayedScale
|
||||||
|
: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return getDisplayedImageScale({
|
||||||
|
rasterScale,
|
||||||
|
viewScale: scale,
|
||||||
|
})
|
||||||
|
}, [activeImage, group, rasterScale, savedDisplayedScale, scale])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!activeImage) return
|
||||||
|
if (!Number.isFinite(displayedScale) || displayedScale <= 0) return
|
||||||
|
lastDisplayedScaleRef.current = displayedScale
|
||||||
|
if (Math.abs(displayedScale - savedDisplayedScale) > 0.000001) {
|
||||||
|
setDisplayedScale(displayedScale)
|
||||||
|
}
|
||||||
|
}, [activeImage, displayedScale, savedDisplayedScale, setDisplayedScale])
|
||||||
|
|
||||||
const displayNumber = useMemo(() => {
|
const displayNumber = useMemo(() => {
|
||||||
return Number((scale * 100).toFixed(0))
|
return Number((displayedScale * 100).toFixed(0))
|
||||||
}, [scale])
|
}, [displayedScale])
|
||||||
|
|
||||||
const setCurrentScale = (n: number) => {
|
const setCurrentScale = (n: number) => {
|
||||||
const currentScale = n / 100
|
const currentScale = getViewScaleFromDisplayedScale({
|
||||||
|
displayedScale: n / 100,
|
||||||
|
rasterScale,
|
||||||
|
})
|
||||||
const group = usePaperStore.getState().group
|
const group = usePaperStore.getState().group
|
||||||
if (!group) return
|
if (!group) return
|
||||||
group.scaling = new paper.Point(currentScale, currentScale)
|
group.scaling = new paper.Point(currentScale, currentScale)
|
||||||
setScale(currentScale)
|
setScale(currentScale)
|
||||||
|
setDisplayedScale(n / 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
@@ -31,9 +81,37 @@ const ScaleToolContainer = () => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
if (!rasterList || !rasterList.length) return
|
if (!rasterList || !rasterList.length) return
|
||||||
const currentRaster = rasterList[0]
|
const currentRaster = rasterList.find(
|
||||||
group.position = currentRaster.position
|
(item): item is paper.Raster => item instanceof paper.Raster
|
||||||
setCurrentScale(100)
|
)
|
||||||
|
if (!currentRaster) return
|
||||||
|
const rawWidth = rasterSize?.[0] ?? currentRaster.width
|
||||||
|
const rawHeight = rasterSize?.[1] ?? currentRaster.height
|
||||||
|
const canvasWidth = paperScope?.view.bounds.width
|
||||||
|
const canvasHeight = paperScope?.view.bounds.height
|
||||||
|
const fitDisplayedScale =
|
||||||
|
rawWidth &&
|
||||||
|
rawHeight &&
|
||||||
|
canvasWidth &&
|
||||||
|
canvasHeight &&
|
||||||
|
Number.isFinite(canvasWidth) &&
|
||||||
|
Number.isFinite(canvasHeight)
|
||||||
|
? Math.min(canvasWidth / rawWidth, canvasHeight / rawHeight)
|
||||||
|
: getDisplayedImageScale({
|
||||||
|
rasterScale,
|
||||||
|
viewScale: 1,
|
||||||
|
})
|
||||||
|
const targetViewScale = getViewScaleFromDisplayedScale({
|
||||||
|
displayedScale: fitDisplayedScale,
|
||||||
|
rasterScale,
|
||||||
|
})
|
||||||
|
group.scaling = new paper.Point(targetViewScale, targetViewScale)
|
||||||
|
group.position = new paper.Point(
|
||||||
|
(rawWidth * fitDisplayedScale) / 2,
|
||||||
|
(rawHeight * fitDisplayedScale) / 2
|
||||||
|
)
|
||||||
|
setScale(targetViewScale)
|
||||||
|
setDisplayedScale(fitDisplayedScale)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleEnter = (e: any) => {
|
const handleEnter = (e: any) => {
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ interface TopToolsState {
|
|||||||
setSaveCurrentScale: (val: boolean) => void
|
setSaveCurrentScale: (val: boolean) => void
|
||||||
scale: number
|
scale: number
|
||||||
setScale: (val: number) => void
|
setScale: (val: number) => void
|
||||||
|
displayedScale: number
|
||||||
|
setDisplayedScale: (val: number) => void
|
||||||
activeOperation: string
|
activeOperation: string
|
||||||
setActiveOperation: (val: string) => void
|
setActiveOperation: (val: string) => void
|
||||||
showObjectList: boolean
|
showObjectList: boolean
|
||||||
@@ -114,6 +116,7 @@ const initialTopToolsState = {
|
|||||||
drawOption: "default" as "default" | "intersect" | "unite",
|
drawOption: "default" as "default" | "intersect" | "unite",
|
||||||
saveCurrentScale: false,
|
saveCurrentScale: false,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
|
displayedScale: 1,
|
||||||
activeOperation: "",
|
activeOperation: "",
|
||||||
showObjectList: false,
|
showObjectList: false,
|
||||||
showGroupList: false,
|
showGroupList: false,
|
||||||
@@ -248,6 +251,12 @@ export const useTopToolsStore = create<TopToolsState>()(
|
|||||||
...state,
|
...state,
|
||||||
scale: val,
|
scale: val,
|
||||||
})),
|
})),
|
||||||
|
displayedScale: initialTopToolsState.displayedScale,
|
||||||
|
setDisplayedScale: (val: number) =>
|
||||||
|
set((state: TopToolsState) => ({
|
||||||
|
...state,
|
||||||
|
displayedScale: Number.isFinite(val) && val > 0 ? val : 1,
|
||||||
|
})),
|
||||||
activeOperation: initialTopToolsState.activeOperation,
|
activeOperation: initialTopToolsState.activeOperation,
|
||||||
setActiveOperation: (val: string) =>
|
setActiveOperation: (val: string) =>
|
||||||
set((state: TopToolsState) => ({
|
set((state: TopToolsState) => ({
|
||||||
|
|||||||
23
components/label/utils/scale.ts
Normal file
23
components/label/utils/scale.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export const normalizeScale = (value: number | null | undefined) => {
|
||||||
|
return Number.isFinite(value) && Number(value) > 0 ? Number(value) : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getDisplayedImageScale = ({
|
||||||
|
rasterScale,
|
||||||
|
viewScale,
|
||||||
|
}: {
|
||||||
|
rasterScale?: number | null
|
||||||
|
viewScale?: number | null
|
||||||
|
}) => {
|
||||||
|
return normalizeScale(rasterScale) * normalizeScale(viewScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getViewScaleFromDisplayedScale = ({
|
||||||
|
displayedScale,
|
||||||
|
rasterScale,
|
||||||
|
}: {
|
||||||
|
displayedScale?: number | null
|
||||||
|
rasterScale?: number | null
|
||||||
|
}) => {
|
||||||
|
return normalizeScale(displayedScale) / normalizeScale(rasterScale)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user