From 64a0f27f06f2d8f02972e2198308f795f5d76aa2 Mon Sep 17 00:00:00 2001 From: Administrator Date: Thu, 14 May 2026 06:46:04 +0800 Subject: [PATCH] fix: apply objectLimit globally Closes #42 --- .../InteractiveGraphics.tsx | 120 ++++++++++-------- site/utils/applyObjectLimit.ts | 39 ++++++ tests/apply-object-limit.test.ts | 48 +++++++ 3 files changed, 157 insertions(+), 50 deletions(-) create mode 100644 site/utils/applyObjectLimit.ts create mode 100644 tests/apply-object-limit.test.ts diff --git a/site/components/InteractiveGraphics/InteractiveGraphics.tsx b/site/components/InteractiveGraphics/InteractiveGraphics.tsx index de014e1..e7d84a4 100644 --- a/site/components/InteractiveGraphics/InteractiveGraphics.tsx +++ b/site/components/InteractiveGraphics/InteractiveGraphics.tsx @@ -1,6 +1,7 @@ import useResizeObserver from "@react-hook/resize-observer" import { useCallback, useEffect, useMemo, useState } from "react" import { SuperGrid } from "react-supergrid" +import { applyObjectLimit } from "site/utils/applyObjectLimit" import { getGraphicsBounds } from "site/utils/getGraphicsBounds" import { getMaxStep } from "site/utils/getMaxStep" import { sortRectsByArea } from "site/utils/sortRectsByArea" @@ -421,65 +422,78 @@ export const InteractiveGraphics = ({ filterLayerAndStep, }) - const filterAndLimit = ( + const filterObjects = ( objects: T[] | undefined, filterFn: (obj: T) => boolean, ): (T & { originalIndex: number })[] => { if (!objects) return [] - const filtered = objects + return objects .map((obj, index) => ({ ...obj, originalIndex: index })) .filter(filterFn) - return objectLimit ? filtered.slice(-objectLimit) : filtered } - const filteredLines = useMemo( - () => - filterAndLimit(graphics.lines, filterLines).sort( - (a, b) => - (a.zIndex ?? 0) - (b.zIndex ?? 0) || - a.originalIndex - b.originalIndex, - ), - [graphics.lines, filterLines, objectLimit], - ) - const filteredInfiniteLines = useMemo( - () => filterAndLimit(graphics.infiniteLines, filterLayerAndStep), - [graphics.infiniteLines, filterLayerAndStep, objectLimit], - ) - const filteredRects = useMemo( - () => sortRectsByArea(filterAndLimit(graphics.rects, filterRects)), - [graphics.rects, filterRects, objectLimit], - ) - const filteredPolygons = useMemo( - () => filterAndLimit(graphics.polygons, filterPolygons), - [graphics.polygons, filterPolygons, objectLimit], - ) - const filteredPoints = useMemo( - () => filterAndLimit(graphics.points, filterPoints), - [graphics.points, filterPoints, objectLimit], - ) - const filteredCircles = useMemo( - () => filterAndLimit(graphics.circles, filterCircles), - [graphics.circles, filterCircles, objectLimit], - ) - const filteredTexts = useMemo( - () => filterAndLimit(graphics.texts, filterTexts), - [graphics.texts, filterTexts, objectLimit], - ) - const filteredArrows = useMemo( - () => filterAndLimit(graphics.arrows, filterArrows), - [graphics.arrows, filterArrows, objectLimit], - ) + const visibleObjects = useMemo(() => { + const lines = filterObjects(graphics.lines, filterLines).sort( + (a, b) => + (a.zIndex ?? 0) - (b.zIndex ?? 0) || a.originalIndex - b.originalIndex, + ) + const infiniteLines = filterObjects( + graphics.infiniteLines, + filterLayerAndStep, + ) + const rects = sortRectsByArea(filterObjects(graphics.rects, filterRects)) + const polygons = filterObjects(graphics.polygons, filterPolygons) + const points = filterObjects(graphics.points, filterPoints) + const circles = filterObjects(graphics.circles, filterCircles) + const texts = filterObjects(graphics.texts, filterTexts) + const arrows = filterObjects(graphics.arrows, filterArrows) + + return applyObjectLimit( + { + arrows, + infiniteLines, + lines, + rects, + polygons, + circles, + texts, + points, + }, + objectLimit, + ) + }, [ + graphics.lines, + graphics.infiniteLines, + graphics.rects, + graphics.polygons, + graphics.points, + graphics.circles, + graphics.texts, + graphics.arrows, + filterLines, + filterLayerAndStep, + filterRects, + filterPolygons, + filterPoints, + filterCircles, + filterTexts, + filterArrows, + objectLimit, + ]) - const totalFilteredObjects = - filteredInfiniteLines.length + - filteredLines.length + - filteredRects.length + - filteredPolygons.length + - filteredPoints.length + - filteredCircles.length + - filteredTexts.length + - filteredArrows.length - const isLimitReached = objectLimit && totalFilteredObjects > objectLimit + const { + arrows: filteredArrows, + infiniteLines: filteredInfiniteLines, + lines: filteredLines, + rects: filteredRects, + polygons: filteredPolygons, + circles: filteredCircles, + texts: filteredTexts, + points: filteredPoints, + } = visibleObjects.limitedGroups + + const totalFilteredObjects = visibleObjects.totalObjectCount + const isLimitReached = visibleObjects.isLimited return (
@@ -560,6 +574,12 @@ export const InteractiveGraphics = ({ )}
)} + {maxStep <= 0 && isLimitReached && ( + + Display limited to {objectLimit} objects. Received:{" "} + {totalFilteredObjects}. + + )}