feat(circle): change size
This commit is contained in:
@@ -1022,16 +1022,12 @@ const PaperContainer = (
|
||||
parent: usePaperStore.getState().group,
|
||||
strokeScaling: false,
|
||||
})
|
||||
if (Math.abs(path.area) < useTopToolsStore.getState().checkSize) {
|
||||
path.remove()
|
||||
if (hollows[index]) {
|
||||
path.data.isHollowPolygon = true
|
||||
innerPaths.push(path)
|
||||
} else {
|
||||
if (hollows[index]) {
|
||||
path.data.isHollowPolygon = true
|
||||
innerPaths.push(path)
|
||||
} else {
|
||||
path.fillColor = new paper.Color(fillColor)
|
||||
outerPaths.push(path)
|
||||
}
|
||||
path.fillColor = new paper.Color(fillColor)
|
||||
outerPaths.push(path)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -92,7 +92,12 @@ import { useKeyboardStore } from "../useKeyBoardStore"
|
||||
import { usePaperStore } from "../usePaperStore"
|
||||
import { useRightToolsStore } from "../useRightToolsStore"
|
||||
import { useIntervalStore, useLabelTimeStore } from "../useTimerStore"
|
||||
import { useTopToolsStore } from "../useTopToolsStore"
|
||||
import {
|
||||
DEFAULT_NODE_SIZE,
|
||||
NODE_SIZE_MAX,
|
||||
NODE_SIZE_MIN,
|
||||
useTopToolsStore,
|
||||
} from "../useTopToolsStore"
|
||||
import { getSubAttrStatus } from "../util"
|
||||
import { safeClone } from "../utils/clone"
|
||||
import { labelTypeMap, TaskStatusEnum } from "../utils/constants"
|
||||
@@ -222,13 +227,14 @@ const TopTools = (
|
||||
setAssistToolEnabled,
|
||||
assistToolSize,
|
||||
setAssistToolSize,
|
||||
nodeSize,
|
||||
setNodeSize,
|
||||
needBackup,
|
||||
setNeedBackup,
|
||||
checkSize,
|
||||
setCheckSize,
|
||||
magnetFlag,
|
||||
setMagnetFlag,
|
||||
} = useTopToolsStore()
|
||||
const [nodeSizeInput, setNodeSizeInput] = useState<number | string>(nodeSize)
|
||||
|
||||
const { pathGroupMap } = useRightToolsStore()
|
||||
const isAutoSave = useIntervalStore((state) => state.isAutoSave)
|
||||
@@ -247,6 +253,11 @@ const TopTools = (
|
||||
].filter(Boolean).length
|
||||
}, [projectDetail, showDescList, showGroupList, showObjectList, showTaskList])
|
||||
|
||||
useEffect(() => {
|
||||
setNodeSizeInput(nodeSize)
|
||||
usePaperStore.getState().refreshNodeVisualSize()
|
||||
}, [nodeSize])
|
||||
|
||||
const toggleRightPanel = useCallback(
|
||||
(visible: boolean, setter: (val: boolean) => void) => {
|
||||
const nextVisible = !visible
|
||||
@@ -2188,23 +2199,39 @@ const TopTools = (
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex justify="space-between" align="center" px="xs" gap="xs">
|
||||
<NumberInput
|
||||
value={checkSize}
|
||||
w={50}
|
||||
min={1}
|
||||
size="xs"
|
||||
radius="sm"
|
||||
hideControls
|
||||
onChange={(v) => {
|
||||
if (v) setCheckSize(Number(v))
|
||||
}}
|
||||
onFocus={() => {
|
||||
useKeyEventStore.getState().setFocusInput(true)
|
||||
}}
|
||||
onBlur={() => {
|
||||
useKeyEventStore.getState().setFocusInput(false)
|
||||
}}
|
||||
/>
|
||||
<Tooltip label={`节点直径范围 ${NODE_SIZE_MIN}-${NODE_SIZE_MAX}`}>
|
||||
<Flex align="center" gap={4}>
|
||||
<Text span size="xs" style={{ minWidth: "fit-content" }}>
|
||||
节点
|
||||
</Text>
|
||||
<NumberInput
|
||||
value={nodeSizeInput}
|
||||
w={50}
|
||||
min={NODE_SIZE_MIN}
|
||||
max={NODE_SIZE_MAX}
|
||||
step={1}
|
||||
allowDecimal={false}
|
||||
size="xs"
|
||||
radius="sm"
|
||||
hideControls
|
||||
onChange={(value) => {
|
||||
setNodeSizeInput(value)
|
||||
}}
|
||||
onFocus={() => {
|
||||
useKeyEventStore.getState().setFocusInput(true)
|
||||
}}
|
||||
onBlur={(event) => {
|
||||
useKeyEventStore.getState().setFocusInput(false)
|
||||
const rawValue = event.currentTarget.value.trim()
|
||||
const nextValue =
|
||||
rawValue === "" ? DEFAULT_NODE_SIZE : Number(rawValue)
|
||||
setNodeSize(
|
||||
Number.isFinite(nextValue) ? nextValue : DEFAULT_NODE_SIZE
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
{renderEditIcon}
|
||||
<Button
|
||||
w="fit-content"
|
||||
|
||||
@@ -18,7 +18,7 @@ import { useKeyboardStore } from "./useKeyBoardStore"
|
||||
import { useOtherToolsStore } from "./useOtherToolsStore"
|
||||
import { usePaperSupportStore } from "./usePaperSupportStore"
|
||||
import { useRightToolsStore } from "./useRightToolsStore"
|
||||
import { useTopToolsStore } from "./useTopToolsStore"
|
||||
import { DEFAULT_NODE_SIZE, useTopToolsStore } from "./useTopToolsStore"
|
||||
import { safeClone } from "./utils/clone"
|
||||
|
||||
interface ContinuePolygonTarget {
|
||||
@@ -183,6 +183,7 @@ interface PaperState {
|
||||
setContinuePolygonTarget: (target: ContinuePolygonTarget | null) => void
|
||||
beginContinuePolygonDraft: () => boolean
|
||||
setLoadingData: (flag: boolean) => void
|
||||
refreshNodeVisualSize: () => void
|
||||
resizeGhostRequestToken: number
|
||||
requestResizeGhost: () => void
|
||||
}
|
||||
@@ -328,6 +329,7 @@ const PAPER_CONTEXT_HIT_TYPES = [
|
||||
"pathBuff",
|
||||
"pathCircle",
|
||||
] as const
|
||||
const LEGACY_PAPER_NODE_DIAMETER = 6
|
||||
|
||||
const isPaperObjectType = (type: unknown) =>
|
||||
typeof type === "string" &&
|
||||
@@ -339,6 +341,39 @@ const isPaperContextHitType = (type: unknown) =>
|
||||
type as (typeof PAPER_CONTEXT_HIT_TYPES)[number]
|
||||
)
|
||||
|
||||
const getPaperNodeDiameter = () => {
|
||||
const configuredDiameter = useTopToolsStore.getState().nodeSize
|
||||
return Number.isFinite(configuredDiameter)
|
||||
? Math.round(configuredDiameter)
|
||||
: DEFAULT_NODE_SIZE
|
||||
}
|
||||
|
||||
const getPaperNodeRadius = () => getPaperNodeDiameter() / 2
|
||||
|
||||
const getPaperNodeScaleFactor = () => {
|
||||
const currentScaling = usePaperStore.getState().group?.scaling.x || 1
|
||||
const newScale = useTopToolsStore.getState().scale / currentScaling
|
||||
return newScale / currentScaling
|
||||
}
|
||||
|
||||
const syncPaperCircleDiameter = (circle: paper.Path) => {
|
||||
const nextDiameter = getPaperNodeDiameter()
|
||||
const currentDiameter =
|
||||
Number(circle.data?.diameter) || LEGACY_PAPER_NODE_DIAMETER
|
||||
|
||||
if (
|
||||
Number.isFinite(currentDiameter) &&
|
||||
currentDiameter > 0 &&
|
||||
Math.abs(currentDiameter - nextDiameter) > 0.001
|
||||
) {
|
||||
circle.scale(nextDiameter / currentDiameter)
|
||||
}
|
||||
|
||||
circle.data = Object.assign({}, circle.data, {
|
||||
diameter: nextDiameter,
|
||||
})
|
||||
}
|
||||
|
||||
const getPaperCursorByMode = (
|
||||
mode: PaperState["mode"] = usePaperStore.getState().mode
|
||||
) => {
|
||||
@@ -529,6 +564,7 @@ const createPointCircleForPath = (
|
||||
imageId: path.data.imageId,
|
||||
operationId: path.data.operationId,
|
||||
text: index + 1,
|
||||
diameter: getPaperNodeDiameter(),
|
||||
fillColor: path.data.blankColor,
|
||||
strokeColor: path.data.strokeColor,
|
||||
})
|
||||
@@ -562,6 +598,7 @@ const syncPointCirclesWithPath = (path: paper.Path) => {
|
||||
imageId: path.data.imageId,
|
||||
operationId: path.data.operationId,
|
||||
text: index + 1,
|
||||
diameter: getPaperNodeDiameter(),
|
||||
fillColor: path.data.blankColor,
|
||||
strokeColor: path.data.strokeColor,
|
||||
})
|
||||
@@ -1014,6 +1051,19 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
...state,
|
||||
loadingData: flag,
|
||||
})),
|
||||
refreshNodeVisualSize: () => {
|
||||
const group = usePaperStore.getState().group
|
||||
if (!group) return
|
||||
;(
|
||||
group.getItems({
|
||||
match: (item: paper.Item) =>
|
||||
item instanceof paper.Path &&
|
||||
["circle", "pathCircle"].includes(item.data?.type || ""),
|
||||
}) as paper.Path[]
|
||||
).forEach((circle) => {
|
||||
syncPaperCircleDiameter(circle)
|
||||
})
|
||||
},
|
||||
requestResizeGhost: () =>
|
||||
set((state: PaperState) => ({
|
||||
...state,
|
||||
@@ -5427,6 +5477,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
const newScale = useTopToolsStore.getState().scale / currentScaling
|
||||
myCircle.scale(newScale / currentScaling)
|
||||
myCircle.data = Object.assign({ type: "circle", ...option }, data)
|
||||
syncPaperCircleDiameter(myCircle)
|
||||
myCircle.onMouseDown = (e: { event: MouseEvent; point: paper.Point }) => {
|
||||
if (e.event && e.event.button === 2) {
|
||||
if (
|
||||
@@ -5844,6 +5895,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
id: number,
|
||||
color: any
|
||||
) => {
|
||||
const nodeDiameter = getPaperNodeDiameter()
|
||||
let circle: paper.Path.Circle = new paper.Path.Circle(
|
||||
Object.assign(
|
||||
{ parent: usePaperStore.getState().group!, center: point },
|
||||
@@ -5851,12 +5903,13 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
fillColor: color,
|
||||
// center: point,
|
||||
strokeColor: usePaperStore.getState().toolOption?.strokeColor,
|
||||
radius: 3,
|
||||
radius: getPaperNodeRadius(),
|
||||
strokeScaling: false,
|
||||
},
|
||||
{
|
||||
data: {
|
||||
type: "circle",
|
||||
diameter: nodeDiameter,
|
||||
fillColor: color,
|
||||
strokeColor: usePaperStore.getState().toolOption?.strokeColor,
|
||||
imageId: useBottomToolsStore.getState().activeImage,
|
||||
@@ -5868,9 +5921,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
}
|
||||
)
|
||||
)
|
||||
const currentScaling = usePaperStore.getState().group!.scaling.x
|
||||
const newScale = useTopToolsStore.getState().scale / currentScaling
|
||||
circle.scale(newScale / currentScaling)
|
||||
circle.scale(getPaperNodeScaleFactor())
|
||||
circle.onMouseDown = (e: { event: MouseEvent; point: paper.Point }) => {
|
||||
if (e.event && e.event.button === 2) {
|
||||
if (
|
||||
@@ -6051,8 +6102,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
id: number,
|
||||
color: any
|
||||
) => {
|
||||
const currentScaling = usePaperStore.getState().group!.scaling.x
|
||||
const newScale = useTopToolsStore.getState().scale / currentScaling
|
||||
const nodeDiameter = getPaperNodeDiameter()
|
||||
let circle: paper.Path.Circle = new paper.Path.Circle(
|
||||
Object.assign(
|
||||
{ parent: usePaperStore.getState().group!, center: point },
|
||||
@@ -6060,15 +6110,16 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
fillColor: color,
|
||||
// center: point,
|
||||
strokeColor: "#FFF",
|
||||
radius: 3,
|
||||
strokeWidth: 2,
|
||||
radius: getPaperNodeRadius(),
|
||||
strokeScaling: false,
|
||||
},
|
||||
{
|
||||
data: { index, type: "pathCircle", id },
|
||||
data: { index, type: "pathCircle", id, diameter: nodeDiameter },
|
||||
}
|
||||
)
|
||||
)
|
||||
circle.scale(newScale / currentScaling)
|
||||
circle.scale(getPaperNodeScaleFactor())
|
||||
circle.onMouseEnter = (_e: any) => {
|
||||
hoveredPathCircleInfo = {
|
||||
id,
|
||||
|
||||
@@ -6,6 +6,17 @@ import { useObjectStore } from "./store"
|
||||
import { useBottomToolsStore } from "./useBottomToolsStore"
|
||||
import { safeClone } from "./utils/clone"
|
||||
|
||||
export const NODE_SIZE_MIN = 6
|
||||
export const NODE_SIZE_MAX = 24
|
||||
export const DEFAULT_NODE_SIZE = 10
|
||||
|
||||
const clampNodeSize = (value: number) => {
|
||||
const nextValue = Number.isFinite(value)
|
||||
? Math.round(value)
|
||||
: DEFAULT_NODE_SIZE
|
||||
return Math.min(NODE_SIZE_MAX, Math.max(NODE_SIZE_MIN, nextValue))
|
||||
}
|
||||
|
||||
interface TopToolsState {
|
||||
// 标注页面是否仅查看
|
||||
isView: boolean
|
||||
@@ -34,6 +45,8 @@ interface TopToolsState {
|
||||
setAssistToolEnabled: (val: boolean) => void
|
||||
assistToolSize: number
|
||||
setAssistToolSize: (val: number) => void
|
||||
nodeSize: number
|
||||
setNodeSize: (val: number) => void
|
||||
showTags: boolean
|
||||
setShowTags: (val: boolean) => void
|
||||
showTagsConfigs: string[]
|
||||
@@ -94,6 +107,7 @@ const initialTopToolsState = {
|
||||
crosshairStatus: "hidden" as "hidden" | "line" | "carve",
|
||||
assistToolEnabled: false,
|
||||
assistToolSize: 10,
|
||||
nodeSize: DEFAULT_NODE_SIZE,
|
||||
drawOption: "default" as "default" | "intersect" | "unite",
|
||||
saveCurrentScale: false,
|
||||
scale: 1,
|
||||
@@ -183,6 +197,12 @@ export const useTopToolsStore = create<TopToolsState>()(
|
||||
...state,
|
||||
assistToolSize: Math.max(1, val),
|
||||
})),
|
||||
nodeSize: initialTopToolsState.nodeSize,
|
||||
setNodeSize: (val) =>
|
||||
set((state: TopToolsState) => ({
|
||||
...state,
|
||||
nodeSize: clampNodeSize(val),
|
||||
})),
|
||||
showTags: false,
|
||||
setShowTags: (val) =>
|
||||
set((state: TopToolsState) => ({
|
||||
|
||||
Reference in New Issue
Block a user