mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 21:14:21 +08:00
fix: 平滑分组拖拽跟随动画减少卡顿
This commit is contained in:
@@ -111,6 +111,8 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
|
|||||||
const [pointerDragPosition, setPointerDragPosition] = useState<{ x: number; y: number } | null>(
|
const [pointerDragPosition, setPointerDragPosition] = useState<{ x: number; y: number } | null>(
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
const pointerDragPositionRef = useRef<{ x: number; y: number } | null>(null)
|
||||||
|
const pointerDragRafRef = useRef<number | null>(null)
|
||||||
const draggingStudentIdRef = useRef<number | null>(null)
|
const draggingStudentIdRef = useRef<number | null>(null)
|
||||||
const pointerDragSourceGroupRef = useRef<string | null>(null)
|
const pointerDragSourceGroupRef = useRef<string | null>(null)
|
||||||
const pointerDragTargetGroupRef = useRef<string | null>(null)
|
const pointerDragTargetGroupRef = useRef<string | null>(null)
|
||||||
@@ -155,6 +157,10 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
|
|||||||
xlsxWorkerRef.current = createXlsxWorker()
|
xlsxWorkerRef.current = createXlsxWorker()
|
||||||
return () => {
|
return () => {
|
||||||
xlsxWorkerRef.current?.terminate()
|
xlsxWorkerRef.current?.terminate()
|
||||||
|
if (pointerDragRafRef.current != null) {
|
||||||
|
cancelAnimationFrame(pointerDragRafRef.current)
|
||||||
|
pointerDragRafRef.current = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@@ -503,6 +509,7 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
|
|||||||
pointerDragTargetGroupRef.current = null
|
pointerDragTargetGroupRef.current = null
|
||||||
setPointerDraggingStudentId(studentId)
|
setPointerDraggingStudentId(studentId)
|
||||||
setPointerDragStudentName(studentName)
|
setPointerDragStudentName(studentName)
|
||||||
|
pointerDragPositionRef.current = { x: e.clientX, y: e.clientY }
|
||||||
setPointerDragPosition({ x: e.clientX, y: e.clientY })
|
setPointerDragPosition({ x: e.clientX, y: e.clientY })
|
||||||
setPointerTargetGroup(null)
|
setPointerTargetGroup(null)
|
||||||
e.currentTarget.setPointerCapture(e.pointerId)
|
e.currentTarget.setPointerCapture(e.pointerId)
|
||||||
@@ -513,9 +520,22 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const schedulePointerDragPositionUpdate = (clientX: number, clientY: number) => {
|
||||||
|
pointerDragPositionRef.current = { x: clientX, y: clientY }
|
||||||
|
if (pointerDragRafRef.current != null) return
|
||||||
|
pointerDragRafRef.current = requestAnimationFrame(() => {
|
||||||
|
pointerDragRafRef.current = null
|
||||||
|
if (!pointerDragPositionRef.current) return
|
||||||
|
setPointerDragPosition({
|
||||||
|
x: pointerDragPositionRef.current.x,
|
||||||
|
y: pointerDragPositionRef.current.y,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const trackPointerTarget = (clientX: number, clientY: number) => {
|
const trackPointerTarget = (clientX: number, clientY: number) => {
|
||||||
if (draggingStudentIdRef.current == null) return
|
if (draggingStudentIdRef.current == null) return
|
||||||
setPointerDragPosition({ x: clientX, y: clientY })
|
schedulePointerDragPositionUpdate(clientX, clientY)
|
||||||
const element = document.elementFromPoint(clientX, clientY) as HTMLElement | null
|
const element = document.elementFromPoint(clientX, clientY) as HTMLElement | null
|
||||||
const dropZone = element?.closest("[data-group-drop]") as HTMLElement | null
|
const dropZone = element?.closest("[data-group-drop]") as HTMLElement | null
|
||||||
const targetGroup = dropZone?.dataset.groupDrop ?? null
|
const targetGroup = dropZone?.dataset.groupDrop ?? null
|
||||||
@@ -543,6 +563,11 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
|
|||||||
draggingStudentIdRef.current = null
|
draggingStudentIdRef.current = null
|
||||||
pointerDragSourceGroupRef.current = null
|
pointerDragSourceGroupRef.current = null
|
||||||
pointerDragTargetGroupRef.current = null
|
pointerDragTargetGroupRef.current = null
|
||||||
|
pointerDragPositionRef.current = null
|
||||||
|
if (pointerDragRafRef.current != null) {
|
||||||
|
cancelAnimationFrame(pointerDragRafRef.current)
|
||||||
|
pointerDragRafRef.current = null
|
||||||
|
}
|
||||||
setPointerDraggingStudentId(null)
|
setPointerDraggingStudentId(null)
|
||||||
setPointerDragStudentName("")
|
setPointerDragStudentName("")
|
||||||
setPointerDragPosition(null)
|
setPointerDragPosition(null)
|
||||||
@@ -1509,8 +1534,8 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
left: pointerDragPosition.x + 14,
|
left: 0,
|
||||||
top: pointerDragPosition.y + 14,
|
top: 0,
|
||||||
pointerEvents: "none",
|
pointerEvents: "none",
|
||||||
zIndex: 2100,
|
zIndex: 2100,
|
||||||
border: "1px solid var(--ss-border-color)",
|
border: "1px solid var(--ss-border-color)",
|
||||||
@@ -1524,6 +1549,9 @@ export const StudentManager: React.FC<{ canEdit: boolean }> = ({ canEdit }) => {
|
|||||||
whiteSpace: "nowrap",
|
whiteSpace: "nowrap",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
textOverflow: "ellipsis",
|
textOverflow: "ellipsis",
|
||||||
|
transform: `translate3d(${pointerDragPosition.x + 14}px, ${pointerDragPosition.y + 14}px, 0)`,
|
||||||
|
transition: "transform 90ms linear",
|
||||||
|
willChange: "transform",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{pointerDragStudentName}
|
{pointerDragStudentName}
|
||||||
|
|||||||
Reference in New Issue
Block a user