Skip to content

Commit e8e331e

Browse files
committed
Cyclic graph is up with backtrack calculation of coordinates of misaligned vertices
1 parent c8b1425 commit e8e331e

File tree

5 files changed

+126
-57
lines changed

5 files changed

+126
-57
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "reactjs-graphs",
3-
"version": "1.0.4",
3+
"version": "1.1.0",
44
"description": "Create branched graphs in ReactJS",
55
"main": "build/index.js",
66
"scripts": {

source/Graph.js

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ export default class Graph extends React.Component {
1111
super(props)
1212
this.state = {
1313
list: [],
14+
backtrackList: [],
1415
vertexCoordinates: {}
1516
}
1617

1718
props.vertices.forEach((vertex, index) => {
1819
this.state.list.push({ name: vertex.label, next: [] })
20+
this.state.backtrackList.push({ name: vertex.label, prev: [] })
1921
})
2022

2123
props.edges.map(edge => {
@@ -24,12 +26,14 @@ export default class Graph extends React.Component {
2426

2527
let mainIndex = 1
2628

27-
let totalYAllowed = props.height
29+
let totalYAllowed = props.orientation === "horizontal" ? props.height : props.width
2830
let vertexGap = props.vertexGap
2931

3032
let horizontalMin = 0, horizontalMax = 0
3133
let verticalMin = props.height/2, verticalMax = props.height/2
3234

35+
console.log(this.state.list)
36+
3337
this.state.list.map(mainVertex => {
3438

3539
const edgesTo = mainVertex.next
@@ -55,6 +59,8 @@ export default class Graph extends React.Component {
5559

5660
for(let i=0;i<edgesTo.length;i++) {
5761

62+
this.state.backtrackList.find(obj => obj.name == edgesTo[i]).prev.push(mainVertex.name)
63+
5864
const childVertex = edgesTo[i]
5965

6066
const childY = (i + 1)*partitionLength
@@ -97,10 +103,10 @@ export default class Graph extends React.Component {
97103
if(vertex.label in this.state.vertexCoordinates) {
98104
// ok
99105
} else {
100-
if(flag) throw new Error("Initializing the graph with multiple vertices? Only 1 vertex is supported for now")
106+
if(flag) throw new Error(`Initializing the graph with multiple vertices (${vertex.label})? Only 1 vertex is supported for now`)
101107
// this is the first vertex which was not registered in the for-loop above
102108
flag = true
103-
if(this.props.orientation === 'horizontal') {
109+
if(props.orientation === 'horizontal') {
104110
this.state.vertexCoordinates[vertex.label] = {
105111
x: 0,
106112
y: totalYAllowed/2
@@ -114,15 +120,40 @@ export default class Graph extends React.Component {
114120
}
115121
})
116122

117-
console.log(this.state.vertexCoordinates)
123+
console.log(this.state.backtrackList)
118124

119125
console.log(verticalMin, verticalMax)
120126
console.log(horizontalMin, horizontalMax)
121127

128+
this.state.backtrackList.forEach(mainVertex => {
129+
// this is for correcting positions of multiple vertices joined to single vertex
130+
const edgeTo = mainVertex.prev
131+
if(edgeTo.length < 2) return
132+
133+
//debugger
134+
135+
//const { y:oldY } = this.state.vertexCoordinates[mainVertex.name]
136+
137+
let sumY = 0
138+
139+
edgeTo.forEach(vertex => {
140+
sumY += this.state.vertexCoordinates[vertex].y
141+
})
142+
143+
sumY /= edgeTo.length
144+
145+
this.state.vertexCoordinates[mainVertex.name].y = sumY
146+
147+
})
148+
122149
//this.state.horizontalShift = -(horizontalMin + horizontalMax)/2
123150
this.state.verticalShift = ((verticalMin + verticalMax) - (props.height))/2
124151
this.state.horizontalShift = ((horizontalMin + horizontalMax) - (props.width))/2
125-
152+
153+
if(!props.perfectlyCenter) {
154+
if(props.orientation === "vertical") this.state.horizontalShift = 0
155+
else this.state.verticalShift = 0
156+
}
126157
}
127158

128159
getEdges(edgeProps) {
@@ -140,7 +171,7 @@ export default class Graph extends React.Component {
140171
const { x, y } = vertexCoordinates[edgesTo[i]]
141172
elems.push(<Edge
142173
key={vertex + edgesTo[i]}
143-
points={[parentX, parentY, (parentX + x)/2, (parentY + y + (Math.floor(Math.random()*20) - 10))/2, x, y]}
174+
points={[parentX, parentY, (parentX + x + (Math.floor(Math.random()*20) - 10) )/2, (parentY + y + (Math.floor(Math.random()*20) - 10))/2, x, y]}
144175
{...edgeProps}
145176
/>)
146177
}
@@ -151,26 +182,29 @@ export default class Graph extends React.Component {
151182
render() {
152183
const { vertexCoordinates, horizontalShift, verticalShift } = this.state
153184

154-
const { vertexStroke, vertexStrokeWidth, inactiveVertexFill, activeVertexFill, vertexRadius } = this.props
155-
const vertexProps = { vertexStroke, vertexStrokeWidth, inactiveVertexFill, activeVertexFill, vertexRadius }
185+
const { labelFontSize, vertexStroke, vertexStrokeWidth, inactiveVertexFill, activeVertexFill, vertexRadius } = this.props
186+
const vertexProps = { labelFontSize, vertexStroke, vertexStrokeWidth, inactiveVertexFill, activeVertexFill, vertexRadius }
156187

157188
const { edgeStroke, edgeWidth } = this.props
158189
const edgeProps = { edgeStroke, edgeWidth }
159190

160-
const { vertices, width, height } = this.props
191+
const { vertices, width, height, orientation } = this.props
161192

162193
return (
163194
<Stage width={width} height={height}>
164195
<Layer>
165196
<Group ref={k => this.group = k} offsetX={horizontalShift} offsetY={verticalShift}>
166-
{this.getEdges(edgeProps)}
197+
198+
{this.getEdges(edgeProps)}
167199
{vertices.map((vertex, index) => {
168200
return <Vertex
169201
key={index}
170202
x={vertexCoordinates[vertex.label].x}
171203
y={vertexCoordinates[vertex.label].y}
172204
label={vertex.label}
205+
orientation={orientation}
173206
onClick={_ => vertex.onClick(vertex.label, index, vertex.extras)}
207+
disabled={vertex.disabled}
174208
{...vertexProps}
175209
/>
176210
})
@@ -186,10 +220,12 @@ Graph.propTypes = {
186220
orientation: PropTypes.oneOf(['horizontal', 'vertical']).isRequired,
187221
width: PropTypes.number.isRequired,
188222
height: PropTypes.number.isRequired,
189-
vertexGap: PropTypes.number.isRequired
223+
vertexGap: PropTypes.number.isRequired,
224+
perfectlyCenter: PropTypes.bool.isRequired
190225
}
191226

192227
Graph.defaultProps = {
193228
orientation: 'horizontal',
194-
vertexGap: 100
229+
vertexGap: 100,
230+
perfectlyCenter: false
195231
}

source/Vertex.js

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react'
2-
import { Circle, Text } from 'react-konva'
2+
import { Circle, Text, Group } from 'react-konva'
33
import PropTypes from 'prop-types'
44

55
export default class Vertex extends React.Component {
@@ -10,55 +10,79 @@ export default class Vertex extends React.Component {
1010
this.mouseOutVertex = this.mouseOutVertex.bind(this)
1111
this.state = {
1212
vertexFill: props.inactiveVertexFill,
13-
textOffsetX: 0
13+
textOffsetX: 0,
14+
textOffsetY: 0,
15+
showTextNode: true
1416
}
1517
}
1618

1719
componentDidMount() {
1820
this.setState({
19-
textOffsetX: this.text.width() / 2
21+
textOffsetX: this.text.width() / 2,
22+
textOffsetY: this.text.height() / 2,
23+
showTextNode: !this.props.disabled
2024
})
2125
}
2226

27+
shouldComponentUpdate(nextProps, nextState) {
28+
return this.state != nextState
29+
}
30+
2331
mouseOutVertex() {
2432
document.body.style.cursor = 'default'
25-
this.setState({
26-
vertexFill: this.props.inactiveVertexFill
27-
})
33+
34+
if(this.props.disabled) {
35+
// disabled vertex
36+
this.setState({
37+
showTextNode: false
38+
})
39+
} else {
40+
this.setState({
41+
vertexFill: this.props.inactiveVertexFill
42+
})
43+
}
2844
}
2945

3046
mouseInVertex() {
3147
document.body.style.cursor = 'pointer'
32-
this.setState({
33-
vertexFill: this.props.activeVertexFill
34-
})
48+
if(this.props.disabled) {
49+
this.setState({
50+
showTextNode: true
51+
})
52+
} else {
53+
this.setState({
54+
vertexFill: this.props.activeVertexFill
55+
})
56+
}
3557
}
3658

3759
render() {
3860

39-
const { x, y, label, onClick, vertexStroke, vertexStrokeWidth, vertexRadius } = this.props
40-
const { vertexFill, textOffsetX } = this.state
61+
const { disabled, x, y, label, onClick, vertexStroke, vertexStrokeWidth, vertexRadius, orientation, labelFontSize } = this.props
62+
const { vertexFill, textOffsetX, textOffsetY, showTextNode } = this.state
4163

4264
return (
43-
<>
44-
<Text
65+
<Group>
66+
{showTextNode ? <Text
4567
ref={node => this.text = node }
46-
x={x}
47-
y={y-30}
68+
x={orientation === "horizontal" ? x : x - textOffsetX - vertexRadius - vertexStrokeWidth - 5 }
69+
y={orientation === "horizontal" ? y - textOffsetY * 2 - vertexRadius - vertexStrokeWidth : y - textOffsetY }
4870
offsetX={textOffsetX}
49-
text={label} />
71+
fontSize={labelFontSize}
72+
text={label} /> : null }
5073
<Circle
5174
x={x}
5275
onClick={onClick}
5376
onMouseEnter={this.mouseInVertex}
5477
onMouseLeave={this.mouseOutVertex}
5578
y={y}
56-
stroke={vertexStroke}
79+
filter
80+
stroke={!disabled ? vertexStroke : "gray" }
5781
strokeWidth={vertexStrokeWidth}
58-
fill={vertexFill}
82+
fill={!disabled ? vertexFill : "gray" }
5983
radius={vertexRadius}
6084
/>
61-
</>
85+
</Group>
6286
)
6387
}
6488
}
@@ -70,13 +94,15 @@ Vertex.propTypes = {
7094
vertexStrokeWidth: PropTypes.number.isRequired,
7195
inactiveVertexFill: PropTypes.string.isRequired,
7296
activeVertexFill: PropTypes.string.isRequired,
73-
vertexRadius: PropTypes.number.isRequired
97+
vertexRadius: PropTypes.number.isRequired,
98+
labelFontSize: PropTypes.number.isRequired
7499
}
75100

76101
Vertex.defaultProps ={
77102
vertexStroke: "#df6766",
78103
vertexStrokeWidth: 3,
79104
inactiveVertexFill: "white",
80105
activeVertexFill: "#df6766",
81-
vertexRadius: 10
106+
vertexRadius: 10,
107+
labelFontSize: 12
82108
}

source/index.js

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,39 @@ const onClick = (label, index, extras) => {
77
}
88

99
const vertices = [
10-
{ label: "Here it begins", onClick, extras: "Some helper data" },
1110
{ label: "HTML", onClick },
1211
{ label: "CSS", onClick },
13-
{ label: "Sass", onClick },
14-
{ label: "JavaScript", onClick },
15-
{ label: "Bootstrap", onClick },
16-
{ label: "jQuery", onClick },
17-
{ label: "ReactJS", onClick },
18-
{ label: "Jest", onClick },
19-
{ label: "Angular", onClick },
20-
{ label: "Vue", onClick },
21-
{ label: "Redux", onClick },
22-
{ label: "React Material", onClick },
23-
{ label: "Vuetify", onClick },
12+
{ label: "Sass", onClick, disabled: false },
13+
{ label: "JavaScript", onClick, disabled: false },
14+
// { label: "Bootstrap", onClick, disabled: false },
15+
// { label: "jQuery", onClick, disabled: false },
16+
{ label: "React.js", onClick, disabled: false },
17+
{ label: "Angular", onClick, disabled: false },
18+
{ label: "Vue", onClick, disabled: false },
19+
// { label: "Redux", onClick, disabled: false },
20+
// { label: "Vuetify", onClick, disabled: false },
21+
{ label: "Node.js", },
22+
//{ label: "GitHub", },
23+
/*{ label: "MongoDB", },
24+
{ label: "MySQL", },
25+
{ label: "PHP", },
26+
{ label: "nginx", },
27+
{ label: "Apache", },*/
2428
]
2529

2630
const edges = [
27-
["Here it begins", "HTML"],
2831
["HTML", "CSS"],
2932
["CSS", "JavaScript"],
3033
["CSS", "Sass"],
31-
["JavaScript", "jQuery"],
32-
["jQuery", "Bootstrap"],
33-
["jQuery", "ReactJS"],
34-
["jQuery", "Angular"],
35-
["jQuery", "Vue"],
36-
["ReactJS", "Redux"],
37-
["Redux", "React Material"],
38-
["React Material", "Jest"],
39-
["Vue", "Vuetify"],
34+
["Sass", "Vue"],
35+
["JavaScript", "React.js"],
36+
["JavaScript", "Angular"],
37+
["JavaScript", "Vue"],
38+
["Angular", "Node.js"],
39+
["React.js", "Node.js"],
40+
["Vue", "Node.js"],
41+
//["React.js", "Redux"],
42+
//["Vue", "Vuetify"],
4043
]
4144

4245

@@ -49,5 +52,8 @@ ReactDOM.render(<Graph
4952
vertexStroke="#df6766"
5053
edgeStroke="#ebb2b2"
5154
edgeWidth={2}
52-
vertexRadius={10}
55+
vertexRadius={15}
56+
vertexGap={200}
57+
labelFontSize={20}
58+
perfectlyCenter={true}
5359
/>, document.getElementById('root'))

source/konva.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const Konva = require("../node_modules/konva/src/Core")
33
require("../node_modules/konva/src/shapes/Circle")
44
require("../node_modules/konva/src/shapes/Line")
55
require("../node_modules/konva/src/shapes/Text")
6+
require("../node_modules/konva/src/shapes/Text")
67

78
require("../node_modules/konva/src/Animation")
89

0 commit comments

Comments
 (0)