fix(point): move
This commit is contained in:
@@ -462,6 +462,122 @@ const getPaperSelectionPath = (
|
||||
return nearestPath
|
||||
}
|
||||
|
||||
const getNearestPaperPathSegmentIndex = (
|
||||
path: paper.Path,
|
||||
localPoint: paper.Point
|
||||
) => {
|
||||
let nearestIndex = 0
|
||||
let nearestDistance = Infinity
|
||||
|
||||
path.segments.forEach((segment, index) => {
|
||||
const distance = segment.point.getDistance(localPoint)
|
||||
if (distance < nearestDistance) {
|
||||
nearestDistance = distance
|
||||
nearestIndex = index
|
||||
}
|
||||
})
|
||||
|
||||
return nearestIndex
|
||||
}
|
||||
|
||||
const normalizePointPanHitResult = (
|
||||
hitResult: paper.HitResult | null,
|
||||
localPoint: paper.Point
|
||||
) => {
|
||||
if (!hitResult?.item?.data?.id || hitResult.item.data?.type !== "circle") {
|
||||
return hitResult
|
||||
}
|
||||
|
||||
const selectedPath = getPaperSelectionPath(hitResult.item.data.id, localPoint)
|
||||
if (
|
||||
!(selectedPath instanceof paper.Path) ||
|
||||
selectedPath.data?.type !== "point" ||
|
||||
!selectedPath.segments.length
|
||||
) {
|
||||
return hitResult
|
||||
}
|
||||
|
||||
const segmentIndex = getNearestPaperPathSegmentIndex(selectedPath, localPoint)
|
||||
|
||||
return {
|
||||
...hitResult,
|
||||
item: selectedPath,
|
||||
type: "segment",
|
||||
segment: selectedPath.segments[segmentIndex],
|
||||
} as paper.HitResult
|
||||
}
|
||||
|
||||
const getPointCirclesById = (id: number) =>
|
||||
(usePaperStore.getState().group?.getItems({
|
||||
data: {
|
||||
id,
|
||||
type: "circle",
|
||||
},
|
||||
}) as paper.Path.Circle[]) || []
|
||||
|
||||
const createPointCircleForPath = (
|
||||
path: paper.Path,
|
||||
point: paper.Point,
|
||||
index: number
|
||||
) => {
|
||||
const circle = usePaperStore
|
||||
.getState()
|
||||
.getPointCircle(point, index, path.data.id, path.data.blankColor)
|
||||
|
||||
circle.data = Object.assign({}, circle.data, {
|
||||
id: path.data.id,
|
||||
imageId: path.data.imageId,
|
||||
operationId: path.data.operationId,
|
||||
text: index + 1,
|
||||
fillColor: path.data.blankColor,
|
||||
strokeColor: path.data.strokeColor,
|
||||
})
|
||||
circle.fillColor = path.data.blankColor || circle.fillColor || null
|
||||
circle.strokeColor = path.data.strokeColor || circle.strokeColor || null
|
||||
|
||||
return circle
|
||||
}
|
||||
|
||||
const syncPointCirclesWithPath = (path: paper.Path) => {
|
||||
if (path.data?.type !== "point" || !path.data?.id) return []
|
||||
|
||||
const unusedCircles = getPointCirclesById(path.data.id).slice()
|
||||
const orderedCircles = path.segments.map((segment, index) => {
|
||||
const matchedCircleIndex = unusedCircles.findIndex((circle) => {
|
||||
return (
|
||||
circle.position.getDistance(segment.point) <= 0.01 ||
|
||||
circle.contains(segment.point)
|
||||
)
|
||||
})
|
||||
|
||||
const circle =
|
||||
matchedCircleIndex >= 0
|
||||
? unusedCircles.splice(matchedCircleIndex, 1)[0]
|
||||
: createPointCircleForPath(path, segment.point, index)
|
||||
|
||||
circle.position.x = segment.point.x
|
||||
circle.position.y = segment.point.y
|
||||
circle.data = Object.assign({}, circle.data, {
|
||||
id: path.data.id,
|
||||
imageId: path.data.imageId,
|
||||
operationId: path.data.operationId,
|
||||
text: index + 1,
|
||||
fillColor: path.data.blankColor,
|
||||
strokeColor: path.data.strokeColor,
|
||||
})
|
||||
circle.fillColor = path.data.blankColor || circle.fillColor || null
|
||||
circle.strokeColor = path.data.strokeColor || circle.strokeColor || null
|
||||
|
||||
return circle
|
||||
})
|
||||
|
||||
unusedCircles.forEach((circle) => {
|
||||
circle.remove()
|
||||
})
|
||||
|
||||
return orderedCircles
|
||||
}
|
||||
|
||||
const trySelectPaperObjectByPoint = (clickPoint: paper.Point) => {
|
||||
const group = usePaperStore.getState().group
|
||||
if (!group) return false
|
||||
@@ -1090,8 +1206,6 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
? baseTolerance / useTopToolsStore.getState().scale
|
||||
: 0
|
||||
|
||||
false && getPanHitTolerance
|
||||
|
||||
const createPanHitOptions = (
|
||||
tolerance: number,
|
||||
match: (hit: paper.HitResult) => boolean
|
||||
@@ -1115,7 +1229,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
if (hoveredCircleInfo) {
|
||||
const pointHit = group.hitTest(
|
||||
projectPoint,
|
||||
createPanHitOptions(0, (hit) => {
|
||||
createPanHitOptions(getPanHitTolerance(), (hit) => {
|
||||
return (
|
||||
hit.item.data?.type === "pathCircle" &&
|
||||
hit.item.data?.id === hoveredCircleInfo.id &&
|
||||
@@ -1132,7 +1246,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
if (hoveredBufferInfo) {
|
||||
const edgeHit = group.hitTest(
|
||||
projectPoint,
|
||||
createPanHitOptions(0, (hit) => {
|
||||
createPanHitOptions(getPanHitTolerance(), (hit) => {
|
||||
return (
|
||||
hit.item.data?.type === "pathBuff" &&
|
||||
hit.item.data?.id === hoveredBufferInfo.id &&
|
||||
@@ -1145,8 +1259,8 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
|
||||
return group.hitTest(
|
||||
projectPoint,
|
||||
createPanHitOptions(0, (hit) =>
|
||||
["rectangle", "polygon", "brush", "point"].includes(
|
||||
createPanHitOptions(getPanHitTolerance(), (hit) =>
|
||||
["rectangle", "polygon", "brush", "point", "circle"].includes(
|
||||
hit.item.data?.type || ""
|
||||
)
|
||||
)
|
||||
@@ -1197,6 +1311,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
hasExceededPanDragThreshold = false
|
||||
|
||||
let hitResult = resolvePanHitResult(e.point)
|
||||
hitResult = normalizePointPanHitResult(hitResult, point)
|
||||
console.log("hitResult", hitResult)
|
||||
const hoveredBufferInfo = hoveredBufferPathInfo?.path.parent
|
||||
? hoveredBufferPathInfo
|
||||
@@ -1475,27 +1590,26 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
activePath = hitResult.item as paper.Path
|
||||
}
|
||||
} else if (hitResult.item.data.type === "point") {
|
||||
// 只有点击圆才视为选中
|
||||
if (hitResult.type === "segment") {
|
||||
// Path 类型
|
||||
if (hitResult.item instanceof paper.Path) {
|
||||
if (!hitResult.item.data.selected) {
|
||||
hitResult.item.data.selected = true
|
||||
// 绘制遮罩
|
||||
usePaperSupportStore.getState().handleMask(hitResult.item)
|
||||
// 绘制点对应的数字
|
||||
usePaperSupportStore
|
||||
.getState()
|
||||
.handleText(hitResult.item as paper.Path)
|
||||
// 绘制选中边
|
||||
usePaperSupportStore
|
||||
.getState()
|
||||
.handleBufferPaths(hitResult.item)
|
||||
// 绘制选中圆
|
||||
usePaperSupportStore.getState().handleCircles(hitResult.item)
|
||||
}
|
||||
activePath = hitResult.item as paper.Path
|
||||
if (
|
||||
["segment", "stroke"].includes(hitResult.type) &&
|
||||
hitResult.item instanceof paper.Path
|
||||
) {
|
||||
if (!hitResult.item.data.selected) {
|
||||
hitResult.item.data.selected = true
|
||||
// 绘制遮罩
|
||||
usePaperSupportStore.getState().handleMask(hitResult.item)
|
||||
// 绘制点对应的数字
|
||||
usePaperSupportStore
|
||||
.getState()
|
||||
.handleText(hitResult.item as paper.Path)
|
||||
// 绘制选中边
|
||||
usePaperSupportStore
|
||||
.getState()
|
||||
.handleBufferPaths(hitResult.item)
|
||||
// 绘制选中圆
|
||||
usePaperSupportStore.getState().handleCircles(hitResult.item)
|
||||
}
|
||||
activePath = hitResult.item as paper.Path
|
||||
}
|
||||
} else if (
|
||||
hitResult.item.data.type === "pathBuff" ||
|
||||
@@ -1598,21 +1712,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
}
|
||||
if (currentPath.data.type === "point") {
|
||||
usePaperSupportStore.getState().handleText(currentPath)
|
||||
let circles = usePaperStore.getState().group!.getItems({
|
||||
data: {
|
||||
id: currentPath.data.id,
|
||||
type: "circle",
|
||||
},
|
||||
}) as paper.Path[]
|
||||
|
||||
currentPath.segments.forEach((segment, index) => {
|
||||
let findIndex = circles.findIndex((circle) => {
|
||||
return circle.contains(segment.point)
|
||||
})
|
||||
circles[index].data = Object.assign({}, circles[index]?.data, {
|
||||
text: findIndex + 1,
|
||||
})
|
||||
})
|
||||
syncPointCirclesWithPath(currentPath)
|
||||
usePaperSupportStore.getState().handleBufferPaths(currentPath)
|
||||
usePaperSupportStore.getState().handleCircles(currentPath)
|
||||
}
|
||||
@@ -1677,15 +1777,9 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
}
|
||||
} else {
|
||||
activePath.insert(hitIndex + 1, hitResult.location.point)
|
||||
activePath?.data?.type === "point" &&
|
||||
usePaperStore
|
||||
.getState()
|
||||
.getPointCircle(
|
||||
hitResult.location.point,
|
||||
hitIndex + 1,
|
||||
activePath.data.id,
|
||||
activePath.data.blankColor
|
||||
)
|
||||
if (activePath?.data?.type === "point") {
|
||||
syncPointCirclesWithPath(activePath)
|
||||
}
|
||||
activePath.bringToFront()
|
||||
usePaperSupportStore.getState().handleBufferPaths(activePath)
|
||||
usePaperSupportStore.getState().handleCircles(activePath)
|
||||
@@ -1699,21 +1793,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
if (activePath?.data?.type === "point") {
|
||||
// 绘制点对应的数字
|
||||
usePaperSupportStore.getState().handleText(activePath)
|
||||
let circles = usePaperStore.getState().group!.getItems({
|
||||
data: {
|
||||
id: activePath.data.id,
|
||||
type: "circle",
|
||||
},
|
||||
}) as paper.Path[]
|
||||
|
||||
activePath.segments.forEach((segment, index) => {
|
||||
let findIndex = circles.findIndex((circle) => {
|
||||
return circle.contains(segment.point)
|
||||
})
|
||||
circles[index].data = Object.assign({}, circles[index]?.data, {
|
||||
text: findIndex + 1,
|
||||
})
|
||||
})
|
||||
syncPointCirclesWithPath(activePath)
|
||||
usePaperSupportStore.getState().handleBufferPaths(activePath)
|
||||
usePaperSupportStore.getState().handleCircles(activePath)
|
||||
}
|
||||
@@ -1807,39 +1887,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
usePaperSupportStore.getState().handleMask(hitResult.item)
|
||||
}
|
||||
if (activePath?.data?.type === "point") {
|
||||
let paths = usePaperStore.getState().group!.getItems({
|
||||
data: {
|
||||
id: activePath.data.id,
|
||||
// text: activePath.segments.length - hitIndex + 1,
|
||||
type: "circle",
|
||||
},
|
||||
}) as paper.Path[]
|
||||
|
||||
// paths = paths.filter((item) => {
|
||||
// if (item.data.text === hitIndex + 1) item.remove();
|
||||
// return item.data.text !== hitIndex + 1;
|
||||
// });
|
||||
paths = paths.filter((circle) => {
|
||||
let findIndex = activePath.segments.findIndex((segment) => {
|
||||
return circle.contains(segment.point)
|
||||
})
|
||||
if (findIndex === -1) {
|
||||
circle.remove()
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
// 1. 对数组按照 text 属性进行排序
|
||||
let sortedArr = paths
|
||||
.slice()
|
||||
.sort((a, b) => a.data.text - b.data.text)
|
||||
|
||||
// 2. 重新赋值 text 属性为从 1 开始的连续自然数
|
||||
sortedArr.forEach((item, index) => {
|
||||
item.data.text = index + 1
|
||||
})
|
||||
syncPointCirclesWithPath(activePath)
|
||||
|
||||
// paths.forEach((child) => {
|
||||
// if (
|
||||
@@ -2083,27 +2131,11 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
]!.position.y = point!.y
|
||||
usePaperSupportStore.getState().handleMask(path)
|
||||
} else if (path.data.type === "point") {
|
||||
let circles = usePaperStore.getState().group!.getItems({
|
||||
data: {
|
||||
id: path.data.id,
|
||||
type: "circle",
|
||||
},
|
||||
}) as paper.Path[]
|
||||
const circles = syncPointCirclesWithPath(path)
|
||||
|
||||
// let index = path.segments.length - hitIndex - 1
|
||||
// let index = hitIndex;
|
||||
|
||||
// 移动点
|
||||
if (circles && circles.length) {
|
||||
// let circle = circles.find(
|
||||
// (item) => item.data.text === index + 1
|
||||
// );
|
||||
|
||||
let circle = circles.find((circle) => {
|
||||
return circle.contains(path.segments[hitIndex].point)
|
||||
})
|
||||
circle!.position.x = point!.x
|
||||
circle!.position.y = point!.y
|
||||
if (circles[hitIndex]) {
|
||||
circles[hitIndex].position.x = point!.x
|
||||
circles[hitIndex].position.y = point!.y
|
||||
}
|
||||
// 移动路径
|
||||
path.segments[hitIndex].point.x = point!.x
|
||||
@@ -2315,45 +2347,12 @@ export const usePaperStore = create<PaperState>((set) => ({
|
||||
}
|
||||
|
||||
const handlePointIntersectRaster = (path: paper.Path) => {
|
||||
let circles = usePaperStore.getState().group!.getItems({
|
||||
data: {
|
||||
id: path.data.id,
|
||||
type: "circle",
|
||||
},
|
||||
}) as paper.Path[]
|
||||
// 去除超出图片边界的部分
|
||||
let newCircles = circles.filter((circle) => {
|
||||
if (
|
||||
!usePaperStore
|
||||
.getState()
|
||||
.rasterPath!.bounds.contains(circle.bounds.center)
|
||||
) {
|
||||
circle.remove()
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
// 1. 对数组按照 text 属性进行排序
|
||||
let sortedArr = newCircles
|
||||
.slice()
|
||||
.sort((a, b) => a.data.text - b.data.text)
|
||||
|
||||
// 2. 重新赋值 text 属性为从 1 开始的连续自然数
|
||||
sortedArr.forEach((item, index) => {
|
||||
item.data.text = index + 1
|
||||
})
|
||||
|
||||
// newCircles.forEach((circle, circleIndex) => {
|
||||
// // 重新设置显示数字
|
||||
// circle.data.text = circleIndex + 1;
|
||||
// });
|
||||
path.segments = path.segments.filter((segment) => {
|
||||
return usePaperStore
|
||||
.getState()
|
||||
.rasterPath!.bounds.contains(segment.point)
|
||||
})
|
||||
syncPointCirclesWithPath(path)
|
||||
// 去除超出图片边界的部分 end
|
||||
usePaperSupportStore.getState().handleMask(path)
|
||||
usePaperSupportStore.getState().handleBufferPaths(path)
|
||||
|
||||
Reference in New Issue
Block a user