Skip to content

Commit 15e7cb8

Browse files
committed
fix: remove & add example
1 parent 2ff08f4 commit 15e7cb8

File tree

5 files changed

+177
-81
lines changed

5 files changed

+177
-81
lines changed

examples/canvas-renderer.fixture.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ export default function CanvasRenderer() {
201201
<h2>Canvas Renderer with Mouse Panning/Zooming</h2>
202202
<p>Drag to pan, scroll to zoom</p>
203203
<div
204-
ref={node => {
204+
ref={(node) => {
205205
// Using a callback ref approach
206206
containerRef.current = node
207207
// Apply the mouse transform ref if available
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { InteractiveGraphics } from "site/components/InteractiveGraphics/InteractiveGraphics"
2+
3+
export default () => {
4+
return (
5+
<InteractiveGraphics
6+
objectLimit={2}
7+
graphics={{
8+
rects: [
9+
{
10+
center: { x: 200, y: 100 },
11+
width: 50,
12+
height: 100,
13+
layer: "layer1",
14+
step: 0,
15+
},
16+
{
17+
center: { x: 250, y: 100 },
18+
width: 50,
19+
height: 100,
20+
layer: "layer1",
21+
step: 1,
22+
},
23+
{
24+
center: { x: 300, y: 100 },
25+
width: 50,
26+
height: 100,
27+
layer: "layer1",
28+
step: 2,
29+
},
30+
],
31+
points: [
32+
{
33+
x: 0,
34+
y: 0,
35+
layer: "layer1",
36+
},
37+
{
38+
x: 50,
39+
y: 0,
40+
layer: "layer2",
41+
},
42+
{
43+
x: 100,
44+
y: 0,
45+
layer: "layer3",
46+
},
47+
],
48+
circles: [
49+
{
50+
center: { x: 400, y: 100 },
51+
radius: 25,
52+
fill: "blue",
53+
stroke: "black",
54+
layer: "layer1",
55+
step: 0,
56+
label: "Circle 1",
57+
},
58+
],
59+
}}
60+
/>
61+
)
62+
}

lib/drawGraphicsToCanvas.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,15 @@ export function drawGraphicsToCanvas(
232232
ctx.lineWidth = line.strokeWidth || 1
233233

234234
if (line.strokeDash) {
235-
if (typeof line.strokeDash === 'string') {
236-
ctx.setLineDash(line.strokeDash.split(",").map(Number).map(n => n * Math.abs(matrix.a)))
235+
if (typeof line.strokeDash === "string") {
236+
ctx.setLineDash(
237+
line.strokeDash
238+
.split(",")
239+
.map(Number)
240+
.map((n) => n * Math.abs(matrix.a)),
241+
)
237242
} else {
238-
ctx.setLineDash(line.strokeDash.map(n => n * Math.abs(matrix.a)))
243+
ctx.setLineDash(line.strokeDash.map((n) => n * Math.abs(matrix.a)))
239244
}
240245
} else {
241246
ctx.setLineDash([])

site/assets/exampleGraphics.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616
],
1717
"lines": [
1818
{
19-
"points": [
20-
{ "x": 0, "y": 0 },
21-
{ "x": 100, "y": 100 }
22-
],
19+
"points": [{ "x": 0, "y": 0 }, { "x": 100, "y": 100 }],
2320
"strokeWidth": 1,
2421
"strokeDash": [10, 5],
2522
"label": "hello"

site/components/InteractiveGraphics/InteractiveGraphics.tsx

Lines changed: 105 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { compose, scale, translate } from "transformation-matrix"
22
import { GraphicsObject } from "../../../lib"
3-
import { useMemo, useState, useEffect } from "react"
3+
import { useMemo, useState } from "react"
44
import useMouseMatrixTransform from "use-mouse-matrix-transform"
55
import { InteractiveState } from "./InteractiveState"
66
import { SuperGrid } from "react-supergrid"
@@ -146,62 +146,94 @@ export const InteractiveGraphics = ({
146146
size,
147147
)
148148

149-
const [visibleObjectCount, setVisibleObjectCount] = useState(0)
150-
const [limitReached, setLimitReached] = useState(false)
151-
152-
const filteredLines = useMemo(() => {
153-
if (!graphics.lines) return []
154-
return graphics.lines.filter(filterLines)
155-
}, [graphics.lines, filterLines])
156-
157-
const filteredPoints = useMemo(() => {
158-
if (!graphics.points) return []
159-
return graphics.points.filter(filterPoints)
160-
}, [graphics.points, filterPoints])
161-
162-
const filteredRects = useMemo(() => {
163-
if (!graphics.rects) return []
164-
return graphics.rects.filter(filterRects)
165-
}, [graphics.rects, filterRects])
166-
167-
const filteredCircles = useMemo(() => {
168-
if (!graphics.circles) return []
169-
return graphics.circles.filter(filterCircles)
170-
}, [graphics.circles, filterCircles])
171-
172-
useEffect(() => {
173-
const totalObjects =
174-
filteredLines.length +
175-
filteredPoints.length +
176-
filteredRects.length +
177-
filteredCircles.length
178-
179-
setVisibleObjectCount(totalObjects)
180-
setLimitReached(!!objectLimit && totalObjects > objectLimit)
181-
}, [filteredLines, filteredPoints, filteredRects, filteredCircles, objectLimit])
182-
183-
const limitObjects = <T,>(objects: T[], currentCount: number): T[] => {
184-
if (!objectLimit || currentCount >= objectLimit) return []
185-
const remaining = objectLimit - currentCount
186-
return objects.slice(0, remaining)
187-
}
188-
189-
const limitedLines = useMemo(() =>
190-
objectLimit ? filteredLines.slice(0, objectLimit) : filteredLines
191-
, [filteredLines, objectLimit])
192-
193-
const limitedPoints = useMemo(() =>
194-
limitObjects(filteredPoints, limitedLines.length)
195-
, [filteredPoints, limitedLines.length, objectLimit])
196-
197-
const limitedRects = useMemo(() =>
198-
limitObjects(filteredRects, limitedLines.length + limitedPoints.length)
199-
, [filteredRects, limitedLines.length, limitedPoints.length, objectLimit])
200-
201-
const limitedCircles = useMemo(() =>
202-
limitObjects(filteredCircles, limitedLines.length + limitedPoints.length + limitedRects.length)
203-
, [filteredCircles, limitedLines.length, limitedPoints.length, limitedRects.length, objectLimit])
149+
const filteredLines = useMemo(
150+
() => graphics.lines?.filter(filterLines) || [],
151+
[graphics.lines, filterLines],
152+
)
153+
154+
const filteredPoints = useMemo(
155+
() => graphics.points?.filter(filterPoints) || [],
156+
[graphics.points, filterPoints],
157+
)
158+
159+
const filteredRects = useMemo(
160+
() => graphics.rects?.filter(filterRects) || [],
161+
[graphics.rects, filterRects],
162+
)
163+
164+
const filteredCircles = useMemo(
165+
() => graphics.circles?.filter(filterCircles) || [],
166+
[graphics.circles, filterCircles],
167+
)
168+
169+
const visibleObjectCount = useMemo(
170+
() =>
171+
filteredLines.length +
172+
filteredPoints.length +
173+
filteredRects.length +
174+
filteredCircles.length,
175+
[filteredLines, filteredPoints, filteredRects, filteredCircles],
176+
)
177+
178+
const limitReached = useMemo(
179+
() => !!objectLimit && visibleObjectCount > objectLimit,
180+
[objectLimit, visibleObjectCount],
181+
)
182+
183+
const { displayedLines, displayedPoints, displayedRects, displayedCircles } =
184+
useMemo(() => {
185+
if (!objectLimit) {
186+
return {
187+
displayedLines: filteredLines,
188+
displayedPoints: filteredPoints,
189+
displayedRects: filteredRects,
190+
displayedCircles: filteredCircles,
191+
}
192+
}
193+
194+
let remaining = objectLimit
195+
const total = visibleObjectCount
196+
197+
const lineCount = Math.min(
198+
filteredLines.length,
199+
Math.floor((remaining * filteredLines.length) / total),
200+
)
201+
remaining -= lineCount
202+
203+
const pointCount = Math.min(
204+
filteredPoints.length,
205+
Math.floor(
206+
(remaining * filteredPoints.length) / (total - filteredLines.length),
207+
),
208+
)
209+
remaining -= pointCount
210+
211+
const rectCount = Math.min(
212+
filteredRects.length,
213+
Math.floor(
214+
(remaining * filteredRects.length) /
215+
(total - filteredLines.length - filteredPoints.length),
216+
),
217+
)
218+
remaining -= rectCount
219+
220+
// Use any remaining slots for circles
221+
const circleCount = Math.min(filteredCircles.length, remaining)
204222

223+
return {
224+
displayedLines: filteredLines.slice(0, lineCount),
225+
displayedPoints: filteredPoints.slice(0, pointCount),
226+
displayedRects: filteredRects.slice(0, rectCount),
227+
displayedCircles: filteredCircles.slice(0, circleCount),
228+
}
229+
}, [
230+
filteredLines,
231+
filteredPoints,
232+
filteredRects,
233+
filteredCircles,
234+
objectLimit,
235+
visibleObjectCount,
236+
])
205237

206238
return (
207239
<div>
@@ -253,7 +285,7 @@ export const InteractiveGraphics = ({
253285
Filter by step
254286
</label>
255287
{limitReached && (
256-
<span style={{ color: 'red', marginLeft: 8 }}>
288+
<span style={{ color: "red", marginLeft: 8 }}>
257289
Showing {objectLimit} of {visibleObjectCount} objects
258290
</span>
259291
)}
@@ -271,35 +303,35 @@ export const InteractiveGraphics = ({
271303
}}
272304
>
273305
<DimensionOverlay transform={realToScreen}>
274-
{limitedLines.map((l, originalIndex) => (
306+
{displayedLines.map((line) => (
275307
<Line
276-
key={originalIndex}
277-
line={l}
278-
index={graphics.lines!.indexOf(l)}
308+
key={`line-${graphics.lines!.indexOf(line)}`}
309+
line={line}
310+
index={graphics.lines!.indexOf(line)}
279311
interactiveState={interactiveState}
280312
/>
281313
))}
282-
{limitedRects.map((r, originalIndex) => (
314+
{displayedRects.map((rect) => (
283315
<Rect
284-
key={originalIndex}
285-
rect={r}
286-
index={graphics.rects!.indexOf(r)}
316+
key={`rect-${graphics.rects!.indexOf(rect)}`}
317+
rect={rect}
318+
index={graphics.rects!.indexOf(rect)}
287319
interactiveState={interactiveState}
288320
/>
289321
))}
290-
{limitedPoints.map((p, originalIndex) => (
322+
{displayedPoints.map((point) => (
291323
<Point
292-
key={originalIndex}
293-
point={p}
294-
index={graphics.points!.indexOf(p)}
324+
key={`point-${graphics.points!.indexOf(point)}`}
325+
point={point}
326+
index={graphics.points!.indexOf(point)}
295327
interactiveState={interactiveState}
296328
/>
297329
))}
298-
{limitedCircles.map((c, originalIndex) => (
330+
{displayedCircles.map((circle) => (
299331
<Circle
300-
key={originalIndex}
301-
circle={c}
302-
index={graphics.circles!.indexOf(c)}
332+
key={`circle-${graphics.circles!.indexOf(circle)}`}
333+
circle={circle}
334+
index={graphics.circles!.indexOf(circle)}
303335
interactiveState={interactiveState}
304336
/>
305337
))}

0 commit comments

Comments
 (0)