fix(righttool): fix
This commit is contained in:
@@ -80,6 +80,9 @@ const initialState: LabelState = new Map()
|
||||
const operationTypeList = [101, 102, 103, 104]
|
||||
let latestProjectDetailRequestSeq = 0
|
||||
let latestTaskDetailRequestSeq = 0
|
||||
const RIGHT_PANEL_TRANSITION =
|
||||
"width 160ms ease, min-width 160ms ease, opacity 160ms ease"
|
||||
const RIGHT_PANEL_WILL_CHANGE = "width, min-width, opacity"
|
||||
|
||||
// utils
|
||||
const getRectPoints = ([sx, sy, w, h]: number[]) => {
|
||||
@@ -95,6 +98,19 @@ const getSegmentPoints = (arr: Array<number[]>) => {
|
||||
return arr.map((item) => [item[0], item[1]])
|
||||
}
|
||||
|
||||
const getRightPanelViewportStyle = (width: number) => {
|
||||
const stableWidth = Math.max(0, Math.round(width))
|
||||
return {
|
||||
position: "absolute" as const,
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: stableWidth,
|
||||
minWidth: stableWidth,
|
||||
height: "100%",
|
||||
contain: "layout paint",
|
||||
}
|
||||
}
|
||||
|
||||
const videoExtPattern = /\.(mp4|mov|avi|mkv|webm|h264|264|ts|m4v)$/i
|
||||
const GLOBAL_LOADING_Z_INDEX = 900
|
||||
const videoMimeByExt: Record<string, string> = {
|
||||
@@ -2551,17 +2567,16 @@ const LabelPage = ({
|
||||
}
|
||||
}, [])
|
||||
|
||||
const mainBoxHeight = useMemo(() => {
|
||||
const bottomToolsHeight = useMemo(() => {
|
||||
if (projectDetail?.label_type === 5 && metaOperation) {
|
||||
let h = `calc(100% - ${headerHeight}px - 198px)`
|
||||
return h
|
||||
} else if (showMultiFrame) {
|
||||
let h = `calc(100% - ${headerHeight}px - 150px)`
|
||||
return h
|
||||
return 128
|
||||
}
|
||||
let h = `calc(100% - ${headerHeight}px - 70px)`
|
||||
return h
|
||||
}, [projectDetail?.label_type, metaOperation, showMultiFrame, headerHeight])
|
||||
return 80
|
||||
}, [metaOperation, projectDetail?.label_type])
|
||||
|
||||
const mainBoxHeight = useMemo(() => {
|
||||
return `calc(100% - ${headerHeight}px - ${70 + bottomToolsHeight}px)`
|
||||
}, [bottomToolsHeight, headerHeight])
|
||||
|
||||
const selectedTagPreviewList = useMemo(() => {
|
||||
if (!showTags) return []
|
||||
@@ -2741,48 +2756,139 @@ const LabelPage = ({
|
||||
</Flex>
|
||||
</Box>
|
||||
</Box>
|
||||
{showTaskList && (
|
||||
<Box w={sizes[1]} miw={300} style={{ flexShrink: 0 }}>
|
||||
<Box
|
||||
w={sizes[1]}
|
||||
miw={showTaskList ? 300 : 0}
|
||||
style={{
|
||||
position: "relative",
|
||||
flexShrink: 0,
|
||||
overflow: "hidden",
|
||||
opacity: showTaskList ? 1 : 0,
|
||||
visibility: showTaskList ? "visible" : "hidden",
|
||||
pointerEvents: showTaskList ? "auto" : "none",
|
||||
transition: RIGHT_PANEL_TRANSITION,
|
||||
willChange: RIGHT_PANEL_WILL_CHANGE,
|
||||
}}>
|
||||
<Box style={getRightPanelViewportStyle(Math.max(sizes[1], 300))}>
|
||||
<RightTaskTools
|
||||
projectDetail={projectDetail}
|
||||
project_id={projectId}
|
||||
task_id={taskId}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{showGroupList && (
|
||||
<Box w={sizes[2]} miw={200} style={{ flexShrink: 0 }}>
|
||||
</Box>
|
||||
<Box
|
||||
w={sizes[2]}
|
||||
miw={showGroupList ? 200 : 0}
|
||||
style={{
|
||||
position: "relative",
|
||||
flexShrink: 0,
|
||||
overflow: "hidden",
|
||||
opacity: showGroupList ? 1 : 0,
|
||||
visibility: showGroupList ? "visible" : "hidden",
|
||||
pointerEvents: showGroupList ? "auto" : "none",
|
||||
transition: RIGHT_PANEL_TRANSITION,
|
||||
willChange: RIGHT_PANEL_WILL_CHANGE,
|
||||
}}>
|
||||
<Box style={getRightPanelViewportStyle(Math.max(sizes[2], 200))}>
|
||||
<RightGroupTools
|
||||
labelState={labelState}
|
||||
projectDetail={projectDetail}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{showDescList && projectDetail && projectDetail.label_type === 5 && (
|
||||
<Box w={sizes[3]} miw={350} style={{ flexShrink: 0 }}>
|
||||
</Box>
|
||||
<Box
|
||||
w={sizes[3]}
|
||||
miw={
|
||||
showDescList && projectDetail && projectDetail.label_type === 5
|
||||
? 350
|
||||
: 0
|
||||
}
|
||||
style={{
|
||||
position: "relative",
|
||||
flexShrink: 0,
|
||||
overflow: "hidden",
|
||||
opacity:
|
||||
showDescList && projectDetail && projectDetail.label_type === 5
|
||||
? 1
|
||||
: 0,
|
||||
visibility:
|
||||
showDescList && projectDetail && projectDetail.label_type === 5
|
||||
? "visible"
|
||||
: "hidden",
|
||||
pointerEvents:
|
||||
showDescList && projectDetail && projectDetail.label_type === 5
|
||||
? "auto"
|
||||
: "none",
|
||||
transition: RIGHT_PANEL_TRANSITION,
|
||||
willChange: RIGHT_PANEL_WILL_CHANGE,
|
||||
}}>
|
||||
<Box style={getRightPanelViewportStyle(Math.max(sizes[3], 350))}>
|
||||
<RightDescTools taskDetail={taskDetail} />
|
||||
</Box>
|
||||
)}
|
||||
{showDescList && projectDetail && projectDetail.label_type === 6 && (
|
||||
<Box w={sizes[4]} miw={350} style={{ flexShrink: 0 }}>
|
||||
</Box>
|
||||
<Box
|
||||
w={sizes[4]}
|
||||
miw={
|
||||
showDescList && projectDetail && projectDetail.label_type === 6
|
||||
? 350
|
||||
: 0
|
||||
}
|
||||
style={{
|
||||
position: "relative",
|
||||
flexShrink: 0,
|
||||
overflow: "hidden",
|
||||
opacity:
|
||||
showDescList && projectDetail && projectDetail.label_type === 6
|
||||
? 1
|
||||
: 0,
|
||||
visibility:
|
||||
showDescList && projectDetail && projectDetail.label_type === 6
|
||||
? "visible"
|
||||
: "hidden",
|
||||
pointerEvents:
|
||||
showDescList && projectDetail && projectDetail.label_type === 6
|
||||
? "auto"
|
||||
: "none",
|
||||
transition: RIGHT_PANEL_TRANSITION,
|
||||
willChange: RIGHT_PANEL_WILL_CHANGE,
|
||||
}}>
|
||||
<Box style={getRightPanelViewportStyle(Math.max(sizes[4], 350))}>
|
||||
<RightQATools ref={qaToolContainerRef} taskDetail={taskDetail} />
|
||||
</Box>
|
||||
)}
|
||||
{showObjectList && (
|
||||
<Box w={sizes[5]} miw={350} style={{ flexShrink: 0 }}>
|
||||
</Box>
|
||||
<Box
|
||||
w={sizes[5]}
|
||||
miw={showObjectList ? 350 : 0}
|
||||
style={{
|
||||
position: "relative",
|
||||
flexShrink: 0,
|
||||
overflow: "hidden",
|
||||
opacity: showObjectList ? 1 : 0,
|
||||
visibility: showObjectList ? "visible" : "hidden",
|
||||
pointerEvents: showObjectList ? "auto" : "none",
|
||||
transition: RIGHT_PANEL_TRANSITION,
|
||||
willChange: RIGHT_PANEL_WILL_CHANGE,
|
||||
}}>
|
||||
<Box style={getRightPanelViewportStyle(Math.max(sizes[5], 350))}>
|
||||
<RightObjectTools
|
||||
taskDetail={taskDetail}
|
||||
labelState={labelState}
|
||||
projectDetail={projectDetail}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
{/* </Flex> */}
|
||||
</Flex>
|
||||
<Box
|
||||
w="100%"
|
||||
h={projectDetail?.label_type === 5 && metaOperation ? 128 : 80}
|
||||
display={showMultiFrame ? "block" : "none"}>
|
||||
h={bottomToolsHeight}
|
||||
style={{
|
||||
overflow: "hidden",
|
||||
opacity: showMultiFrame ? 1 : 0,
|
||||
pointerEvents: showMultiFrame ? "auto" : "none",
|
||||
transition: "opacity 160ms ease",
|
||||
}}>
|
||||
<BottomTools
|
||||
labelState={labelState}
|
||||
projectDetail={projectDetail}
|
||||
|
||||
@@ -64,8 +64,11 @@ const BottomTools: React.FC<BottomToolsComponentProps> = (props) => {
|
||||
inputNumber,
|
||||
setInputNumber,
|
||||
activeImage,
|
||||
pendingImage,
|
||||
frameSwitchStatus,
|
||||
setActiveImage,
|
||||
setActiveImageId,
|
||||
requestFrameSwitch,
|
||||
onlyKeyFrame,
|
||||
setOnlyKeyFrame,
|
||||
keyFrameData,
|
||||
@@ -168,24 +171,32 @@ const BottomTools: React.FC<BottomToolsComponentProps> = (props) => {
|
||||
if (index < 0 || index >= currentKeys.length) return false
|
||||
|
||||
const nextImage = currentKeys[index]
|
||||
const absoluteIndex = allKeys.findIndex((k) => k === nextImage)
|
||||
if (!nextImage) return false
|
||||
|
||||
scrollToIndex(index)
|
||||
setInputNumber(String(index + 1))
|
||||
setActiveImageId(absoluteIndex >= 0 ? absoluteIndex + 1 : 0)
|
||||
setActiveImage(nextImage)
|
||||
if (
|
||||
frameSwitchStatus === "preparing" &&
|
||||
pendingImage &&
|
||||
pendingImage === nextImage
|
||||
) {
|
||||
closeRightContext()
|
||||
return true
|
||||
}
|
||||
if (nextImage !== activeImage) {
|
||||
requestFrameSwitch(nextImage)
|
||||
}
|
||||
closeRightContext()
|
||||
|
||||
return true
|
||||
},
|
||||
[
|
||||
allKeys,
|
||||
activeImage,
|
||||
closeRightContext,
|
||||
currentKeys,
|
||||
frameSwitchStatus,
|
||||
pendingImage,
|
||||
requestFrameSwitch,
|
||||
scrollToIndex,
|
||||
setActiveImage,
|
||||
setActiveImageId,
|
||||
setInputNumber,
|
||||
]
|
||||
)
|
||||
|
||||
@@ -569,9 +580,14 @@ const BottomTools: React.FC<BottomToolsComponentProps> = (props) => {
|
||||
radius={"sm"}
|
||||
onClick={() => {
|
||||
let flag = false
|
||||
keyFrameData.entries().forEach(([key, value]) => {
|
||||
if (labelState.has(key) && value?.key_frame) flag = true
|
||||
})
|
||||
keyFrameData
|
||||
.entries()
|
||||
.forEach(
|
||||
([key, value]: [string, { key_frame?: boolean }]) => {
|
||||
if (labelState.has(key) && value?.key_frame)
|
||||
flag = true
|
||||
}
|
||||
)
|
||||
if (!flag) {
|
||||
showNotification({
|
||||
title: "警告",
|
||||
@@ -711,6 +727,10 @@ const BottomTools: React.FC<BottomToolsComponentProps> = (props) => {
|
||||
<Flex gap={0} w="max-content" h="100%" align="center">
|
||||
{currentKeys.map((key, index) => {
|
||||
const isActive = activeImage === key
|
||||
const isPending =
|
||||
frameSwitchStatus === "preparing" &&
|
||||
pendingImage === key &&
|
||||
!isActive
|
||||
const isSelected =
|
||||
selectedItems.length && selectedItems.includes(key)
|
||||
const isHighlight = isActive || isSelected
|
||||
@@ -735,12 +755,17 @@ const BottomTools: React.FC<BottomToolsComponentProps> = (props) => {
|
||||
style={{
|
||||
border: isHighlight
|
||||
? "1px solid var(--mantine-color-blue-6)"
|
||||
: "1px solid var(--mantine-color-gray-3)",
|
||||
: isPending
|
||||
? "1px dashed var(--mantine-color-blue-4)"
|
||||
: "1px solid var(--mantine-color-gray-3)",
|
||||
borderRadius: "6px",
|
||||
backgroundColor: isHighlight
|
||||
? "var(--mantine-color-blue-6)"
|
||||
: undefined,
|
||||
: isPending
|
||||
? "rgba(34, 139, 230, 0.08)"
|
||||
: undefined,
|
||||
color: isHighlight ? "white" : undefined,
|
||||
opacity: isPending ? 0.85 : 1,
|
||||
cursor: "pointer",
|
||||
position: "relative",
|
||||
display: "flex",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -158,7 +158,7 @@ const TopTools = (
|
||||
renderPolygons,
|
||||
} = props
|
||||
const { backUrl, basePath } = useBackUrlStore()
|
||||
const { mode, loadingData } = usePaperStore()
|
||||
const { mode, loadingData, requestResizeGhost } = usePaperStore()
|
||||
const router = useRouter()
|
||||
const user_id = usePermissionStore.getState().user_id
|
||||
|
||||
@@ -232,6 +232,32 @@ const TopTools = (
|
||||
const autoSaveGap = useIntervalStore((state) => state.autoSaveGap)
|
||||
const setAutoSaveGap = useIntervalStore((state) => state.setAutoSaveGap)
|
||||
|
||||
const visibleRightPanelCount = useMemo(() => {
|
||||
return [
|
||||
showTaskList,
|
||||
showGroupList,
|
||||
showDescList &&
|
||||
!!projectDetail &&
|
||||
[5, 6].includes(projectDetail.label_type),
|
||||
showObjectList,
|
||||
].filter(Boolean).length
|
||||
}, [projectDetail, showDescList, showGroupList, showObjectList, showTaskList])
|
||||
|
||||
const toggleRightPanel = useCallback(
|
||||
(visible: boolean, setter: (val: boolean) => void) => {
|
||||
const nextVisible = !visible
|
||||
const nextCount = visibleRightPanelCount + (nextVisible ? 1 : -1)
|
||||
if (
|
||||
(visibleRightPanelCount === 0 && nextCount === 1) ||
|
||||
(visibleRightPanelCount === 1 && nextCount === 0)
|
||||
) {
|
||||
requestResizeGhost()
|
||||
}
|
||||
setter(nextVisible)
|
||||
},
|
||||
[requestResizeGhost, visibleRightPanelCount]
|
||||
)
|
||||
|
||||
// 当前是否可以操作功能按键
|
||||
const currentEditAuth = useMemo(() => {
|
||||
if (!taskDetail) return false
|
||||
@@ -2432,7 +2458,7 @@ const TopTools = (
|
||||
c={!showTaskList ? "gray" : "var(--mantine-color-text)"}
|
||||
style={{ width: "auto", display: "flex", gap: 4 }}
|
||||
onClick={() => {
|
||||
setShowTaskList(!showTaskList)
|
||||
toggleRightPanel(showTaskList, setShowTaskList)
|
||||
}}>
|
||||
<ClipboardList style={{ width: 20, height: 20 }} />
|
||||
<Text size="xs">任务</Text>
|
||||
@@ -2452,7 +2478,7 @@ const TopTools = (
|
||||
c={!showGroupList ? "gray" : "var(--mantine-color-text)"}
|
||||
style={{ width: "auto", display: "flex", gap: 4 }}
|
||||
onClick={() => {
|
||||
setShowGroupList(!showGroupList)
|
||||
toggleRightPanel(showGroupList, setShowGroupList)
|
||||
}}>
|
||||
<GroupIcon style={{ width: 20, height: 20 }} />
|
||||
<Text size="xs">群组</Text>
|
||||
@@ -2463,7 +2489,7 @@ const TopTools = (
|
||||
c={!showDescList ? "gray" : "var(--mantine-color-text)"}
|
||||
style={{ width: "auto", display: "flex", gap: 4 }}
|
||||
onClick={() => {
|
||||
setShowDescList(!showDescList)
|
||||
toggleRightPanel(showDescList, setShowDescList)
|
||||
}}>
|
||||
<BadgeInfoIcon style={{ width: 20, height: 20 }} />
|
||||
<Text size="xs">描述</Text>
|
||||
@@ -2474,7 +2500,7 @@ const TopTools = (
|
||||
c={!showObjectList ? "gray" : "var(--mantine-color-text)"}
|
||||
style={{ width: "auto", display: "flex", gap: 4 }}
|
||||
onClick={() => {
|
||||
setShowObjectList(!showObjectList)
|
||||
toggleRightPanel(showObjectList, setShowObjectList)
|
||||
}}>
|
||||
<Component style={{ width: 20, height: 20 }} />
|
||||
<Text size="xs">对象</Text>
|
||||
|
||||
56
components/label/config/performance.ts
Normal file
56
components/label/config/performance.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
const parseEnvInt = (
|
||||
value: string | undefined,
|
||||
fallback: number,
|
||||
min: number,
|
||||
max: number
|
||||
) => {
|
||||
if (!value) return fallback
|
||||
const parsed = Number.parseInt(value, 10)
|
||||
if (!Number.isFinite(parsed)) return fallback
|
||||
return Math.min(max, Math.max(min, parsed))
|
||||
}
|
||||
|
||||
export const labelimagePerformanceConfig = {
|
||||
// 单次渲染的路径切片大小。越小越丝滑,越大越快完成。
|
||||
polygonRenderBatchSize: parseEnvInt(
|
||||
process.env.NEXT_PUBLIC_LABELIMAGE_POLYGON_BATCH_SIZE,
|
||||
12,
|
||||
1,
|
||||
200
|
||||
),
|
||||
// 每帧渲染预算(毫秒)。越小越不卡操作,越大越快完成绘制。
|
||||
polygonRenderBatchBudgetMs: parseEnvInt(
|
||||
process.env.NEXT_PUBLIC_LABELIMAGE_POLYGON_BATCH_BUDGET_MS,
|
||||
6,
|
||||
1,
|
||||
33
|
||||
),
|
||||
// 切帧准备超过该阈值后才显示轻量提示,避免短切换频繁闪动提示。
|
||||
frameSwitchLoadingDelayMs: parseEnvInt(
|
||||
process.env.NEXT_PUBLIC_LABELIMAGE_FRAME_SWITCH_LOADING_DELAY_MS,
|
||||
120,
|
||||
0,
|
||||
1000
|
||||
),
|
||||
// 切帧时新旧图层的交叉淡入时长(毫秒)。设为 0 可关闭淡入。
|
||||
rasterCrossfadeDurationMs: parseEnvInt(
|
||||
process.env.NEXT_PUBLIC_LABELIMAGE_RASTER_CROSSFADE_MS,
|
||||
90,
|
||||
0,
|
||||
400
|
||||
),
|
||||
// 容器尺寸连续变化时,延迟提交 canvas 实际宽高,减少频繁重置导致的白闪。
|
||||
resizeCommitDebounceMs: parseEnvInt(
|
||||
process.env.NEXT_PUBLIC_LABELIMAGE_RESIZE_COMMIT_DEBOUNCE_MS,
|
||||
90,
|
||||
0,
|
||||
500
|
||||
),
|
||||
// 容器尺寸变更后的视觉缓动时长(毫秒),用于降低“跳变感”。
|
||||
resizeInterpolationDurationMs: parseEnvInt(
|
||||
process.env.NEXT_PUBLIC_LABELIMAGE_RESIZE_INTERPOLATION_MS,
|
||||
100,
|
||||
0,
|
||||
400
|
||||
),
|
||||
} as const
|
||||
@@ -13,6 +13,12 @@ interface KeyFrameData {
|
||||
interface BottomToolsState {
|
||||
activeImage: string
|
||||
setActiveImage: (val: string) => void
|
||||
pendingImage: string
|
||||
frameSwitchStatus: "idle" | "preparing"
|
||||
frameSwitchToken: number
|
||||
requestFrameSwitch: (val: string) => number
|
||||
commitFrameSwitch: (val: string, token: number) => void
|
||||
clearPendingFrameSwitch: (token?: number) => void
|
||||
inputNumber: string
|
||||
setInputNumber: (val: string) => void
|
||||
activeImageId: number
|
||||
@@ -36,13 +42,48 @@ const initialBottomToolsState = {
|
||||
inputNumber: "",
|
||||
}
|
||||
|
||||
export const useBottomToolsStore = create<BottomToolsState>((set) => ({
|
||||
export const useBottomToolsStore = create<BottomToolsState>()((set, get) => ({
|
||||
activeImage: initialBottomToolsState.activeImage,
|
||||
setActiveImage: (val: string) =>
|
||||
set((state: BottomToolsState) => ({
|
||||
...state,
|
||||
activeImage: val,
|
||||
pendingImage: "",
|
||||
frameSwitchStatus: "idle",
|
||||
})),
|
||||
pendingImage: "",
|
||||
frameSwitchStatus: "idle",
|
||||
frameSwitchToken: 0,
|
||||
requestFrameSwitch: (val: string): number => {
|
||||
const nextToken = get().frameSwitchToken + 1
|
||||
set((state: BottomToolsState) => ({
|
||||
...state,
|
||||
pendingImage: val,
|
||||
frameSwitchStatus:
|
||||
val && val !== state.activeImage ? "preparing" : "idle",
|
||||
frameSwitchToken: nextToken,
|
||||
}))
|
||||
return nextToken
|
||||
},
|
||||
commitFrameSwitch: (val: string, token: number) =>
|
||||
set((state: BottomToolsState) => {
|
||||
if (state.frameSwitchToken !== token) return state
|
||||
return {
|
||||
...state,
|
||||
activeImage: val,
|
||||
pendingImage: "",
|
||||
frameSwitchStatus: "idle",
|
||||
}
|
||||
}),
|
||||
clearPendingFrameSwitch: (token?: number) =>
|
||||
set((state: BottomToolsState) => {
|
||||
if (token != null && state.frameSwitchToken !== token) return state
|
||||
return {
|
||||
...state,
|
||||
pendingImage: "",
|
||||
frameSwitchStatus: "idle",
|
||||
}
|
||||
}),
|
||||
inputNumber: initialBottomToolsState.inputNumber,
|
||||
setInputNumber: (val: string) =>
|
||||
set((state: BottomToolsState) => ({
|
||||
@@ -63,7 +104,7 @@ export const useBottomToolsStore = create<BottomToolsState>((set) => ({
|
||||
})),
|
||||
keyFrameData: new Map(),
|
||||
setKeyFrameData: (imageId, value) => {
|
||||
const data = useBottomToolsStore.getState().keyFrameData
|
||||
const data = get().keyFrameData
|
||||
data.set(imageId, value)
|
||||
return set((state) => ({
|
||||
...state,
|
||||
@@ -78,15 +119,13 @@ export const useBottomToolsStore = create<BottomToolsState>((set) => ({
|
||||
})),
|
||||
selectedItems: [],
|
||||
setSelectedItems: (id, ctrlKey, shiftKey) => {
|
||||
let arr = [...useBottomToolsStore.getState().selectedItems]
|
||||
let arr = [...get().selectedItems]
|
||||
if ((ctrlKey && shiftKey) || (!ctrlKey && !shiftKey)) arr = []
|
||||
else if (ctrlKey && !shiftKey) {
|
||||
arr.push(id)
|
||||
} else if (!ctrlKey && shiftKey) {
|
||||
const allItems = useBottomToolsStore.getState().allItems
|
||||
const prevId = arr.length
|
||||
? arr[arr.length - 1]
|
||||
: useBottomToolsStore.getState().activeImage
|
||||
const allItems = get().allItems
|
||||
const prevId = arr.length ? arr[arr.length - 1] : get().activeImage
|
||||
const prevIndex = allItems.findIndex((v) => v === prevId)
|
||||
const currentIndex = allItems.findIndex((v) => v === id)
|
||||
arr =
|
||||
|
||||
@@ -50,6 +50,7 @@ interface PaperState {
|
||||
initScope: paper.PaperScope,
|
||||
initGroup: paper.Group
|
||||
) => void
|
||||
setGroup: (group: paper.Group | null) => void
|
||||
setRasterPath: (paperRaster: paper.Path) => void
|
||||
setRasterScale: (id: string, scale: number) => void
|
||||
setRasterSize: (id: string, size: [number, number]) => void
|
||||
@@ -180,6 +181,8 @@ interface PaperState {
|
||||
getItemsById: (id: number) => Array<paper.Path | paper.CompoundPath>
|
||||
setContinuePolygonTarget: (target: ContinuePolygonTarget | null) => void
|
||||
setLoadingData: (flag: boolean) => void
|
||||
resizeGhostRequestToken: number
|
||||
requestResizeGhost: () => void
|
||||
}
|
||||
|
||||
interface PositionStore {
|
||||
@@ -208,6 +211,7 @@ const initialPaperState = {
|
||||
rasterScale: {},
|
||||
rasterSize: {},
|
||||
reciprocalRasterScale: {},
|
||||
resizeGhostRequestToken: 0,
|
||||
}
|
||||
const handleDelete = () => {
|
||||
const group = usePaperStore.getState().group!
|
||||
@@ -529,6 +533,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
rasterScale: initialPaperState.rasterScale,
|
||||
rasterSize: initialPaperState.rasterSize,
|
||||
reciprocalRasterScale: initialPaperState.reciprocalRasterScale,
|
||||
resizeGhostRequestToken: initialPaperState.resizeGhostRequestToken,
|
||||
continuePolygonTarget: null,
|
||||
currentMousePosition: [0, 0],
|
||||
loadingData: false,
|
||||
@@ -544,6 +549,12 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
el: initEl,
|
||||
}))
|
||||
},
|
||||
setGroup: (group) => {
|
||||
set((state: PaperState) => ({
|
||||
...state,
|
||||
group,
|
||||
}))
|
||||
},
|
||||
setRasterPath: (rasterPath) => {
|
||||
set((state: PaperState) => ({
|
||||
...state,
|
||||
@@ -577,6 +588,11 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
...state,
|
||||
loadingData: flag,
|
||||
})),
|
||||
requestResizeGhost: () =>
|
||||
set((state: PaperState) => ({
|
||||
...state,
|
||||
resizeGhostRequestToken: state.resizeGhostRequestToken + 1,
|
||||
})),
|
||||
setContinuePolygonTarget: (target) =>
|
||||
set((state: PaperState) => ({
|
||||
...state,
|
||||
|
||||
Reference in New Issue
Block a user