Skip to content

Commit 5bf9f4d

Browse files
committed
integration relationship arrows in document component
1 parent 356f820 commit 5bf9f4d

File tree

2 files changed

+112
-47
lines changed

2 files changed

+112
-47
lines changed

src/components/Document/index.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import type {
88
import { styled } from "@material-ui/styles"
99
import stringToSequence from "../../string-to-sequence.js"
1010
import Tooltip from "@material-ui/core/Tooltip"
11+
import RelationshipArrows from "../RelationshipArrows"
1112
import Measure from "react-measure"
13+
import colors from "../../colors"
1214

1315
const Container = styled("div")(({ relationshipsOn }) => ({
1416
lineHeight: 1.5,
@@ -93,8 +95,6 @@ export default function Document({
9395
highlightedItems.push(i)
9496
}
9597

96-
console.log(sequenceItemPositionsRef.current)
97-
9898
return (
9999
<Container
100100
relationshipsOn={Boolean(relationships)}
@@ -163,6 +163,21 @@ export default function Document({
163163
)}
164164
</Measure>
165165
))}
166+
<RelationshipArrows
167+
positions={sequenceItemPositionsRef.current}
168+
arrows={[
169+
{ from: "l2", to: "l4", label: "R1" },
170+
{ from: "l1", to: "l4", label: "R2" },
171+
{ from: "l0", to: "l4", label: "R2" },
172+
{ from: "l5", to: "l6", label: "R3" },
173+
{ from: "l7", to: "l6", label: "R3" },
174+
{ from: "l8", to: "l6", label: "R3" },
175+
{ from: "l2", to: "l1", label: "R4" },
176+
{ from: "l4", to: "l10", label: "R5" },
177+
{ from: "l1", to: "l12", label: "R6" },
178+
{ from: "l12", to: "l1", label: "R6" }
179+
].map((a, i) => ({ ...a, color: colors[i % colors.length] }))}
180+
/>
166181
</Container>
167182
)
168183
}

src/components/RelationshipArrows/index.js

Lines changed: 95 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,29 @@ interactively.
1212
*/
1313

1414
import React from "react"
15+
import { styled } from "@material-ui/core/styles"
1516

16-
const ARROW_WIDTH = 2
1717
const X_SEP_DIST = 5
18-
const Y_SEP_DIST = 12
18+
const Y_SEP_DIST = 16
19+
20+
const ArrowLabel = styled("div")({
21+
position: "absolute",
22+
transform: "translate(-50%,0%)",
23+
padding: 1,
24+
paddingLeft: 4,
25+
paddingRight: 4,
26+
fontSize: 11,
27+
color: "#fff",
28+
border: "1px solid rgba(0,0,0,0.2)",
29+
// transition: "transform 120ms",
30+
borderRadius: 4,
31+
fontWeight: "bold",
32+
"&:hover": {
33+
zIndex: 999,
34+
cursor: "pointer",
35+
transform: "translate(-50%, 0%) scale(1.05,1.05)"
36+
}
37+
})
1938

2039
export const RelationshipArrows = ({ positions, arrows, rowHeight = 100 }) => {
2140
const constraintGroups: Array<
@@ -28,6 +47,8 @@ export const RelationshipArrows = ({ positions, arrows, rowHeight = 100 }) => {
2847
for (const arrow of arrows) {
2948
const { from, to, label } = arrow
3049

50+
if (!positions[from] || !positions[to]) return null
51+
3152
const p1 = positions[from].offset
3253
const p2 = positions[to].offset
3354

@@ -55,7 +76,8 @@ export const RelationshipArrows = ({ positions, arrows, rowHeight = 100 }) => {
5576
weight: Math.abs(xDist),
5677
width: Math.abs(p1.left + p1.width / 2 - p2.left - p2.width / 2),
5778
centerX: (p1.left + p2.left + p1.width / 2 + p2.width / 2) / 2,
58-
y
79+
y,
80+
hasLabel: true
5981
},
6082
{
6183
type: "vertical",
@@ -85,7 +107,8 @@ export const RelationshipArrows = ({ positions, arrows, rowHeight = 100 }) => {
85107
weight: Math.abs(xDist),
86108
width: Math.abs(p1.left + p1.width / 2 - p2.left - p2.width / 2),
87109
centerX: (p1.left + p2.left + p1.width / 2 + p2.width / 2) / 2,
88-
y
110+
y,
111+
hasLabel: true
89112
},
90113
{
91114
type: "vertical",
@@ -121,7 +144,8 @@ export const RelationshipArrows = ({ positions, arrows, rowHeight = 100 }) => {
121144
weight: Math.abs(xDist),
122145
width: Math.abs(p1.left + p1.width / 2 - p2.left - p2.width / 2),
123146
centerX: (p1.left + x1 + p1.width / 2) / 2,
124-
y: y1
147+
y: y1,
148+
hasLabel: true
125149
},
126150
{
127151
type: "vertical",
@@ -263,51 +287,77 @@ export const RelationshipArrows = ({ positions, arrows, rowHeight = 100 }) => {
263287
linePoints.push(points)
264288
}
265289

290+
const labelPositions = constraintGroups.map((group, i) => {
291+
const labelConstraintIndex = group.findIndex(c => c.hasLabel)
292+
const p1 = linePoints[i][labelConstraintIndex]
293+
const p2 = linePoints[i][labelConstraintIndex + 1]
294+
return [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2]
295+
})
296+
266297
const svgOffset = { x: 100, y: 100 }
267298

268299
return (
269-
<svg width="600" height="600">
270-
<defs>
271-
{arrows.map((arrow, i) => (
272-
<marker
273-
id={"arrowhead" + i}
274-
markerWidth="5"
275-
markerHeight="5"
276-
refX="0"
277-
refY="2.5"
278-
orient="auto"
279-
>
280-
<polygon fill={arrow.color || "#000"} points="0 0, 6 2.5, 0 5" />
281-
</marker>
300+
<div
301+
style={{
302+
position: "absolute",
303+
left: -svgOffset.x,
304+
top: -svgOffset.y
305+
}}
306+
>
307+
<svg width="600" height="600">
308+
<defs>
309+
{arrows.map((arrow, i) => (
310+
<marker
311+
id={"arrowhead" + i}
312+
markerWidth="5"
313+
markerHeight="5"
314+
refX="0"
315+
refY="2.5"
316+
orient="auto"
317+
>
318+
<polygon fill={arrow.color || "#000"} points="0 0, 6 2.5, 0 5" />
319+
</marker>
320+
))}
321+
</defs>
322+
{linePoints.map((lp, i) => (
323+
<polyline
324+
key={i}
325+
stroke={arrows[i].color || "#000"}
326+
fill="none"
327+
marker-end={`url(#arrowhead${i})`}
328+
stroke-width="2"
329+
points={lp
330+
.map(
331+
([x, y], i) =>
332+
`${svgOffset.x + x},${svgOffset.y +
333+
y -
334+
(i === lp.length - 1 ? 10 : 0)}`
335+
)
336+
.join(" ")}
337+
/>
282338
))}
283-
</defs>
284-
{linePoints.map((lp, i) => (
285-
<polyline
286-
key={i}
287-
stroke={arrows[i].color || "#000"}
288-
fill="none"
289-
marker-end={`url(#arrowhead${i})`}
290-
stroke-width="2"
291-
points={lp
292-
.map(
293-
([x, y], i) =>
294-
`${svgOffset.x + x},${svgOffset.y +
295-
y -
296-
(i === lp.length - 1 ? 10 : 0)}`
297-
)
298-
.join(" ")}
299-
/>
300-
))}
301-
{Object.values(positions).map(p => (
302-
<rect
303-
x={p.offset.left + svgOffset.x}
304-
y={p.offset.top + svgOffset.y}
305-
width={p.offset.width}
306-
height={p.offset.height}
307-
fill="rgba(0,0,0,0.5)"
308-
/>
339+
{Object.values(positions).map(p => (
340+
<rect
341+
x={p.offset.left + svgOffset.x}
342+
y={p.offset.top + svgOffset.y}
343+
width={p.offset.width}
344+
height={p.offset.height}
345+
fill="rgba(0,0,0,0.5)"
346+
/>
347+
))}
348+
</svg>
349+
{arrows.map((arrow, i) => (
350+
<ArrowLabel
351+
style={{
352+
left: svgOffset.x + labelPositions[i][0],
353+
top: svgOffset.y - 7 + labelPositions[i][1],
354+
backgroundColor: arrow.color
355+
}}
356+
>
357+
arrow{i}
358+
</ArrowLabel>
309359
))}
310-
</svg>
360+
</div>
311361
)
312362
}
313363

0 commit comments

Comments
 (0)