Skip to content

Commit b0d61d8

Browse files
Added Sankey Diagram
1 parent 1657fcf commit b0d61d8

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package demo.components
2+
3+
import scala.scalajs.js
4+
import japgolly.scalajs.react._
5+
import japgolly.scalajs.react.vdom.all.key
6+
import japgolly.scalajs.react.vdom.svg.all._
7+
import paths.high.Sankey
8+
9+
10+
object sankey {
11+
case class Sector(id: String)
12+
case class SLink(start: String, end: String, weight: Double)
13+
case class Flow(sectors: Seq[Seq[Sector]], links: Seq[SLink])
14+
15+
private def right(p: js.Array[Double]) = s"translate(${ p(0) + 7 }, ${ p(1) })"
16+
private def left(p: js.Array[Double]) = s"translate(${ p(0) - 7 }, ${ p(1) })"
17+
private val palette = List("#707B82", "#7881C2", "#3E90F0")
18+
19+
val SankeyDiagram = ReactComponentB[Flow]("Sankey Diagram")
20+
.render(flow => {
21+
val sankey = Sankey[Sector, SLink](
22+
nodes = flow.sectors,
23+
links = flow.links,
24+
nodeaccessor = _.id,
25+
linkaccessor = identity,
26+
width = 420,
27+
height = 360,
28+
gutter = 15,
29+
rectWidth = 10
30+
)
31+
32+
val rects = sankey.rectangles map { r =>
33+
val firstHalf = r.group <= flow.sectors.length / 2
34+
35+
g(
36+
path(d := r.curve.path.print, fill := palette(r.group), stroke := "none", opacity := 0.7),
37+
if (firstHalf) text(transform := right(r.curve.centroid), textAnchor := "start", r.item.id)
38+
else text(transform := left(r.curve.centroid), textAnchor := "end", r.item.id)
39+
)
40+
}
41+
val flows = sankey.curvedRectangles map { r =>
42+
path(d := r.curve.path.print, fill := "#acd1e9", stroke := "none", opacity := 0.7)
43+
}
44+
45+
svg(width := 460, height := 400,
46+
g(transform := "translate(30,30)",
47+
flows,
48+
rects
49+
)
50+
)
51+
})
52+
.build
53+
}

src/main/scala/demo/components/toplevel.scala

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import radar._
1111
import tree._
1212
import bar._
1313
import graph._
14+
import sankey._
1415

1516

1617
object toplevel {
@@ -63,6 +64,36 @@ object toplevel {
6364

6465
Family(characters = characters.toList, links = links.toList)
6566
}
67+
val flow = Flow(
68+
sectors = List(
69+
List(
70+
Sector("Energy"),
71+
Sector("Agriculture"),
72+
Sector("Minerals")
73+
),
74+
List(
75+
Sector("Transportation"),
76+
Sector("Harvest"),
77+
Sector("Fuel")
78+
),
79+
List(
80+
Sector("Road"),
81+
Sector("Chemicals")
82+
)
83+
),
84+
links = List(
85+
SLink(start = "Energy", end = "Harvest", weight = 10),
86+
SLink(start = "Energy", end = "Fuel", weight = 30),
87+
SLink(start = "Agriculture", end = "Road", weight = 10),
88+
SLink(start = "Agriculture", end = "Transportation", weight = 10),
89+
SLink(start = "Agriculture", end = "Harvest", weight = 10),
90+
SLink(start = "Minerals", end = "Fuel", weight = 30),
91+
SLink(start = "Transportation", end = "Chemicals", weight = 20),
92+
SLink(start = "Harvest", end = "Chemicals", weight = 10),
93+
SLink(start = "Fuel", end = "Road", weight = 30),
94+
SLink(start = "Minerals", end = "Chemicals", weight = 25)
95+
)
96+
)
6697

6798
val TopLevel = ReactComponentB[Unit]("Top level component")
6899
.render(_ =>
@@ -97,7 +128,12 @@ object toplevel {
97128
id = Some("graph"),
98129
title = "Graph Chart",
99130
text = "A preliminary example of force-directed graph."
100-
), GraphChart(randomGraph(30, 0.15)))
131+
), GraphChart(randomGraph(30, 0.15))),
132+
Panel(PanelContent(
133+
id = Some("sankey"),
134+
title = "Sankey Diagram",
135+
text = "Displays flow among entities."
136+
), SankeyDiagram(flow))
101137
)
102138
)
103139
)

0 commit comments

Comments
 (0)