Skip to main content

Position Glyphs

Rather than rotating the bars, we can instead translate them horizontally based on the link type.

This requires only a small change to the specification.


{

"x": 50,
"y": 50,

Construct the network from a hard-coded link-table.


"data": [
{
"name": "links",
"values": [
{"source": 0, "target": 5, "type": "B"},
{"source": 1, "target": 4, "type": "B"},
{"source": 3, "target": 2, "type": "B"},

{"source": 1, "target": 0, "type": "Y"},
{"source": 1, "target": 4, "type": "Y"},
{"source": 3, "target": 2, "type": "Y"},
{"source": 4, "target": 0, "type": "Y"},
{"source": 5, "target": 4, "type": "Y"},

{"source": 1, "target": 0, "type": "G"},
{"source": 1, "target": 3, "type": "G"},
{"source": 3, "target": 2, "type": "G"},
{"source": 3, "target": 5, "type": "G"},
{"source": 5, "target": 4, "type": "G"},

{"source": 3, "target": 2, "type": "P"},
{"source": 3, "target": 5, "type": "P"},
{"source": 5, "target": 1, "type": "P"},
{"source": 5, "target": 4, "type": "P"}
]
}
],

"networks": [
{
"name": "network",
"links": "links",
"directed": true,
"source_node": [ "id", "source" ],
"target_node": [ "id", "target" ],

}
],


Define an ordering that orders the nodes based on their id...


"orderings": [
{
"name": "nodeOrder",
"data": "network.nodes",
"orderBy": [{"field": "id"}],
"allowTies": false
}
],

...and use this ordering to create a table.


"tables": [
{
"name": "adjacencyMatrix",
"data": "network.links",
"rowOrder": { "order": "nodeOrder", "field": "source" },
"colOrder": { "order": "nodeOrder", "field": "target" },
"symmetric": true
}
],

Define scale to map from edge type to color.


"scales": [
{
"name": "color",
"type": "ordinal",
"domain": ["B", "Y", "G", "P"]
"range": ["#0000ff","#ffc300","#4daf4a","#ff00ff"],
}
],

This block defines what we want to draw for each element of the table.


"vis": [
{
"table": "adjacencyMatrix",

Label the rows and columns...


"rowLabels": { "field": "source.id", "align": "right", "dx": -10 },
"colLabels": { "field": "target.id", "dx": 20 },

...and draw lines between each cell.


"rowLines": {"stroke": "black"},
"colLines": {"stroke": "black"},

Define scale for the x-position of each bar.

Defining it here, rather than at the top-level, allows it to be scaled relative to the width of the table cell.


"scales": [
{
"name": "innerPos",
"type": "ordinal",
"range": [0, 1, 2, 3],
"rangeMapFunction": "datum * bounds.width/ 4",
"domain": ["B", "Y", "G", "P"]
}
],

This block defines what to draw for each data element inside the parent block:

i.e., for each edge in this table cell.


"vis": [
{
"entries": "entry.data",

We draw a bar, sized relative to the table cell, with a color and x-position determined by the link type.


"mark": {
"type": "rect",

"y": 0,
"x": {"field": "type", "scale": "innerPos"}

"width": {"expression": "bounds.width/4"},
"height": {"expression": "bounds.height"},

"fill": {"scale": "color", "field": "type"},
}
}

]
}
]

}