fix(point): move
This commit is contained in:
@@ -462,6 +462,122 @@ const getPaperSelectionPath = (
|
|||||||
return nearestPath
|
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 trySelectPaperObjectByPoint = (clickPoint: paper.Point) => {
|
||||||
const group = usePaperStore.getState().group
|
const group = usePaperStore.getState().group
|
||||||
if (!group) return false
|
if (!group) return false
|
||||||
@@ -1090,8 +1206,6 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
? baseTolerance / useTopToolsStore.getState().scale
|
? baseTolerance / useTopToolsStore.getState().scale
|
||||||
: 0
|
: 0
|
||||||
|
|
||||||
false && getPanHitTolerance
|
|
||||||
|
|
||||||
const createPanHitOptions = (
|
const createPanHitOptions = (
|
||||||
tolerance: number,
|
tolerance: number,
|
||||||
match: (hit: paper.HitResult) => boolean
|
match: (hit: paper.HitResult) => boolean
|
||||||
@@ -1115,7 +1229,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
if (hoveredCircleInfo) {
|
if (hoveredCircleInfo) {
|
||||||
const pointHit = group.hitTest(
|
const pointHit = group.hitTest(
|
||||||
projectPoint,
|
projectPoint,
|
||||||
createPanHitOptions(0, (hit) => {
|
createPanHitOptions(getPanHitTolerance(), (hit) => {
|
||||||
return (
|
return (
|
||||||
hit.item.data?.type === "pathCircle" &&
|
hit.item.data?.type === "pathCircle" &&
|
||||||
hit.item.data?.id === hoveredCircleInfo.id &&
|
hit.item.data?.id === hoveredCircleInfo.id &&
|
||||||
@@ -1132,7 +1246,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
if (hoveredBufferInfo) {
|
if (hoveredBufferInfo) {
|
||||||
const edgeHit = group.hitTest(
|
const edgeHit = group.hitTest(
|
||||||
projectPoint,
|
projectPoint,
|
||||||
createPanHitOptions(0, (hit) => {
|
createPanHitOptions(getPanHitTolerance(), (hit) => {
|
||||||
return (
|
return (
|
||||||
hit.item.data?.type === "pathBuff" &&
|
hit.item.data?.type === "pathBuff" &&
|
||||||
hit.item.data?.id === hoveredBufferInfo.id &&
|
hit.item.data?.id === hoveredBufferInfo.id &&
|
||||||
@@ -1145,8 +1259,8 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
|
|
||||||
return group.hitTest(
|
return group.hitTest(
|
||||||
projectPoint,
|
projectPoint,
|
||||||
createPanHitOptions(0, (hit) =>
|
createPanHitOptions(getPanHitTolerance(), (hit) =>
|
||||||
["rectangle", "polygon", "brush", "point"].includes(
|
["rectangle", "polygon", "brush", "point", "circle"].includes(
|
||||||
hit.item.data?.type || ""
|
hit.item.data?.type || ""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1197,6 +1311,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
hasExceededPanDragThreshold = false
|
hasExceededPanDragThreshold = false
|
||||||
|
|
||||||
let hitResult = resolvePanHitResult(e.point)
|
let hitResult = resolvePanHitResult(e.point)
|
||||||
|
hitResult = normalizePointPanHitResult(hitResult, point)
|
||||||
console.log("hitResult", hitResult)
|
console.log("hitResult", hitResult)
|
||||||
const hoveredBufferInfo = hoveredBufferPathInfo?.path.parent
|
const hoveredBufferInfo = hoveredBufferPathInfo?.path.parent
|
||||||
? hoveredBufferPathInfo
|
? hoveredBufferPathInfo
|
||||||
@@ -1475,27 +1590,26 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
activePath = hitResult.item as paper.Path
|
activePath = hitResult.item as paper.Path
|
||||||
}
|
}
|
||||||
} else if (hitResult.item.data.type === "point") {
|
} else if (hitResult.item.data.type === "point") {
|
||||||
// 只有点击圆才视为选中
|
if (
|
||||||
if (hitResult.type === "segment") {
|
["segment", "stroke"].includes(hitResult.type) &&
|
||||||
// Path 类型
|
hitResult.item instanceof paper.Path
|
||||||
if (hitResult.item instanceof paper.Path) {
|
) {
|
||||||
if (!hitResult.item.data.selected) {
|
if (!hitResult.item.data.selected) {
|
||||||
hitResult.item.data.selected = true
|
hitResult.item.data.selected = true
|
||||||
// 绘制遮罩
|
// 绘制遮罩
|
||||||
usePaperSupportStore.getState().handleMask(hitResult.item)
|
usePaperSupportStore.getState().handleMask(hitResult.item)
|
||||||
// 绘制点对应的数字
|
// 绘制点对应的数字
|
||||||
usePaperSupportStore
|
usePaperSupportStore
|
||||||
.getState()
|
.getState()
|
||||||
.handleText(hitResult.item as paper.Path)
|
.handleText(hitResult.item as paper.Path)
|
||||||
// 绘制选中边
|
// 绘制选中边
|
||||||
usePaperSupportStore
|
usePaperSupportStore
|
||||||
.getState()
|
.getState()
|
||||||
.handleBufferPaths(hitResult.item)
|
.handleBufferPaths(hitResult.item)
|
||||||
// 绘制选中圆
|
// 绘制选中圆
|
||||||
usePaperSupportStore.getState().handleCircles(hitResult.item)
|
usePaperSupportStore.getState().handleCircles(hitResult.item)
|
||||||
}
|
|
||||||
activePath = hitResult.item as paper.Path
|
|
||||||
}
|
}
|
||||||
|
activePath = hitResult.item as paper.Path
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
hitResult.item.data.type === "pathBuff" ||
|
hitResult.item.data.type === "pathBuff" ||
|
||||||
@@ -1598,21 +1712,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
}
|
}
|
||||||
if (currentPath.data.type === "point") {
|
if (currentPath.data.type === "point") {
|
||||||
usePaperSupportStore.getState().handleText(currentPath)
|
usePaperSupportStore.getState().handleText(currentPath)
|
||||||
let circles = usePaperStore.getState().group!.getItems({
|
syncPointCirclesWithPath(currentPath)
|
||||||
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,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
usePaperSupportStore.getState().handleBufferPaths(currentPath)
|
usePaperSupportStore.getState().handleBufferPaths(currentPath)
|
||||||
usePaperSupportStore.getState().handleCircles(currentPath)
|
usePaperSupportStore.getState().handleCircles(currentPath)
|
||||||
}
|
}
|
||||||
@@ -1677,15 +1777,9 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
activePath.insert(hitIndex + 1, hitResult.location.point)
|
activePath.insert(hitIndex + 1, hitResult.location.point)
|
||||||
activePath?.data?.type === "point" &&
|
if (activePath?.data?.type === "point") {
|
||||||
usePaperStore
|
syncPointCirclesWithPath(activePath)
|
||||||
.getState()
|
}
|
||||||
.getPointCircle(
|
|
||||||
hitResult.location.point,
|
|
||||||
hitIndex + 1,
|
|
||||||
activePath.data.id,
|
|
||||||
activePath.data.blankColor
|
|
||||||
)
|
|
||||||
activePath.bringToFront()
|
activePath.bringToFront()
|
||||||
usePaperSupportStore.getState().handleBufferPaths(activePath)
|
usePaperSupportStore.getState().handleBufferPaths(activePath)
|
||||||
usePaperSupportStore.getState().handleCircles(activePath)
|
usePaperSupportStore.getState().handleCircles(activePath)
|
||||||
@@ -1699,21 +1793,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
if (activePath?.data?.type === "point") {
|
if (activePath?.data?.type === "point") {
|
||||||
// 绘制点对应的数字
|
// 绘制点对应的数字
|
||||||
usePaperSupportStore.getState().handleText(activePath)
|
usePaperSupportStore.getState().handleText(activePath)
|
||||||
let circles = usePaperStore.getState().group!.getItems({
|
syncPointCirclesWithPath(activePath)
|
||||||
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,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
usePaperSupportStore.getState().handleBufferPaths(activePath)
|
usePaperSupportStore.getState().handleBufferPaths(activePath)
|
||||||
usePaperSupportStore.getState().handleCircles(activePath)
|
usePaperSupportStore.getState().handleCircles(activePath)
|
||||||
}
|
}
|
||||||
@@ -1807,39 +1887,7 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
usePaperSupportStore.getState().handleMask(hitResult.item)
|
usePaperSupportStore.getState().handleMask(hitResult.item)
|
||||||
}
|
}
|
||||||
if (activePath?.data?.type === "point") {
|
if (activePath?.data?.type === "point") {
|
||||||
let paths = usePaperStore.getState().group!.getItems({
|
syncPointCirclesWithPath(activePath)
|
||||||
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
|
|
||||||
})
|
|
||||||
|
|
||||||
// paths.forEach((child) => {
|
// paths.forEach((child) => {
|
||||||
// if (
|
// if (
|
||||||
@@ -2083,27 +2131,11 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
]!.position.y = point!.y
|
]!.position.y = point!.y
|
||||||
usePaperSupportStore.getState().handleMask(path)
|
usePaperSupportStore.getState().handleMask(path)
|
||||||
} else if (path.data.type === "point") {
|
} else if (path.data.type === "point") {
|
||||||
let circles = usePaperStore.getState().group!.getItems({
|
const circles = syncPointCirclesWithPath(path)
|
||||||
data: {
|
|
||||||
id: path.data.id,
|
|
||||||
type: "circle",
|
|
||||||
},
|
|
||||||
}) as paper.Path[]
|
|
||||||
|
|
||||||
// let index = path.segments.length - hitIndex - 1
|
if (circles[hitIndex]) {
|
||||||
// let index = hitIndex;
|
circles[hitIndex].position.x = point!.x
|
||||||
|
circles[hitIndex].position.y = point!.y
|
||||||
// 移动点
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
// 移动路径
|
// 移动路径
|
||||||
path.segments[hitIndex].point.x = point!.x
|
path.segments[hitIndex].point.x = point!.x
|
||||||
@@ -2315,45 +2347,12 @@ export const usePaperStore = create<PaperState>((set) => ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handlePointIntersectRaster = (path: paper.Path) => {
|
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) => {
|
path.segments = path.segments.filter((segment) => {
|
||||||
return usePaperStore
|
return usePaperStore
|
||||||
.getState()
|
.getState()
|
||||||
.rasterPath!.bounds.contains(segment.point)
|
.rasterPath!.bounds.contains(segment.point)
|
||||||
})
|
})
|
||||||
|
syncPointCirclesWithPath(path)
|
||||||
// 去除超出图片边界的部分 end
|
// 去除超出图片边界的部分 end
|
||||||
usePaperSupportStore.getState().handleMask(path)
|
usePaperSupportStore.getState().handleMask(path)
|
||||||
usePaperSupportStore.getState().handleBufferPaths(path)
|
usePaperSupportStore.getState().handleBufferPaths(path)
|
||||||
|
|||||||
Reference in New Issue
Block a user