{ "$schema": "https://vega.github.io/schema/vega/v4.json", "width": 700, "height": 400, "padding": { "top": 25, "left": 0, "right": 0, "bottom": 0 }, "autosize": "none", "signals": [ { "name": "hover", "value": null, "on": [ { "events": "symbol:mouseover", "update": "datum" }, { "events": "symbol:mouseout", "update": "null" } ] }, { "name": "title", "value": "", "update": "hover ? hover.name : '' " }, { "name": "cx", "update": "width / 2" }, { "name": "cy", "update": "height / 2" }, { "name": "nodeRadius", "value": 10, "bind": { "input": "range", "min": 1, "max": 50, "step": 1 } }, { "name": "nodeCharge", "value": -70, "bind": { "input": "range", "min": -100, "max": 10, "step": 1 } }, { "name": "linkDistance", "value": 70, "bind": { "input": "range", "min": 5, "max": 100, "step": 1 } }, { "name": "static", "value": false, "bind": { "input": "checkbox" } }, { "description": "State variable for active node fix status.", "name": "fix", "value": false, "on": [ { "events": "symbol:mouseout[!event.buttons], window:mouseup", "update": "false" }, { "events": "symbol:mouseover", "update": "fix || true" }, { "events": "[symbol:mousedown, window:mouseup] > window:mousemove!", "update": "xy()", "force": true } ] }, { "description": "Graph node most recently interacted with.", "name": "node", "value": null, "on": [ { "events": "symbol:mouseover", "update": "fix === true ? item() : node" } ] }, { "description": "Flag to restart Force simulation upon data changes.", "name": "restart", "value": false, "on": [ { "events": { "signal": "fix" }, "update": "fix && fix.length" } ] } ], "data": [ { "name": "node-data", "url": "/relations_zeroed", "format": { "type": "json", "property": "nodes" } }, { "name": "link-data", "url": "/relations_zeroed", "format": { "type": "json", "property": "links" } } ], "scales": [ { "name": "color", "type": "ordinal", "domain": { "data": "node-data", "field": "group" }, "range": { "scheme": "category20c" } } ], "marks": [ { "name": "nodes-group", "type": "group", "zindex": 1, "from": { "data": "node-data" }, "marks": [ { "name": "nodes", "type": "symbol", "encode": { "enter": { "fill": { "scale": "color", "field": {"parent": "group"} }, "stroke": { "value": "white" } }, "update": { "size": { "signal": "2 * nodeRadius * nodeRadius" }, "cursor": { "value": "pointer" } } } }, { "type": "text", "interactive": false, "encode": { "enter": { "fill": { "value": "black" }, "fontSize": { "value": 12 }, "align": { "value": "center" }, "text": { "field": {"parent": "name"} }, "y": { "value": -10 } } } } ], "on": [ { "trigger": "fix", "modify": "node", "values": "fix === true ? {fx: node.x, fy: node.y} : {fx: fix[0], fy: fix[1]}" }, { "trigger": "!fix", "modify": "node", "values": "{fx: null, fy: null}" } ], "transform": [ { "type": "force", "iterations": 300, "restart": { "signal": "restart" }, "static": { "signal": "static" }, "signal": "force", "forces": [ { "force": "center", "x": { "signal": "cx" }, "y": { "signal": "cy" } }, { "force": "collide", "radius": { "signal": "nodeRadius" } }, { "force": "nbody", "strength": { "signal": "nodeCharge" } }, { "force": "link", "links": "link-data", "distance": { "signal": "linkDistance" } } ] } ] }, { "type": "path", "from": { "data": "link-data" }, "interactive": false, "encode": { "update": { "stroke": { "value": "#ccc" }, "strokeWidth": { "value": 1 } } }, "transform": [ { "type": "linkpath", "require": { "signal": "force" }, "shape": "line", "sourceX": "datum.source.x", "sourceY": "datum.source.y", "targetX": "datum.target.x", "targetY": "datum.target.y" } ] }, { "type": "text", "interactive": false, "encode": { "enter": { "x": { "signal": "width", "offset": -5 }, "y": { "value": 0 }, "fill": { "value": "black" }, "fontSize": { "value": 20 }, "align": { "value": "right" } }, "update": { "text": { "signal": "title" } } } } ] }