Assets/vega.force.directed.layout.json
{ "data": [ { "name": "node-data", "values": [] }, { "name": "link-data", "values": [] }, { "name": "adj-nodes", "source": "link-data", "transform": [ { "type": "filter", "expr": "datum.src === hoverIndex || datum.tgt === hoverIndex" } ] }, { "name": "adjacentIndices", "source": "adj-nodes", "transform": [ { "type": "formula", "as": "adj", "expr": "datum.src === hoverIndex ? datum.tgt : datum.src" }, { "type": "project", "fields": [ "adj" ], "as": [ "adj" ] } ] } ], "marks": [ { "from": { "data": "node-data" }, "type": "symbol", "encode": { "enter": { "fill": { "scale": "color", "field": "group" }, "stroke": { "value": "white" } }, "update": { "cursor": { "value": "pointer" }, "size": { "signal": "(hoverIndex === datum.index || indata('adjacentIndices', 'adj', datum.index)) ? 2.5 * nodeRadius * nodeRadius : 2 * nodeRadius * nodeRadius" }, "fill": { "signal": "hoverIndex === datum.index || indata('adjacentIndices', 'adj', datum.index) ? 'red' : scale('color', datum.group)" }, "tooltip": { "signal": "{ name: datum.name }" } } }, "name": "nodes", "on": [ { "modify": "node", "trigger": "fix", "values": "fix === true ? {fx: node.x, fy: node.y} : {fx: fix[0], fy: fix[1]}" }, { "modify": "node", "trigger": "!fix", "values": "{fx: null, fy: null}" } ], "transform": [ { "signal": "force", "type": "force", "forces": [ { "force": "center", "x": { "signal": "cx" }, "y": { "signal": "cy" } }, { "force": "collide", "radius": { "signal": "nodeRadius" } }, { "force": "nbody", "strength": { "signal": "nodeCharge" } }, { "force": "link", "distance": { "signal": "linkDistance" }, "links": "link-data" } ], "iterations": 300, "restart": { "signal": "restart" }, "static": { "signal": "static" } } ], "zindex": 1 }, { "from": { "data": "link-data" }, "type": "path", "encode": { "update": { "stroke": { "value": "#ccc" }, "strokeWidth": { "signal": "datum.src === hoverIndex || datum.tgt === hoverIndex ? 2 : 0.5" } } }, "interactive": false, "transform": [ { "type": "linkpath", "require": { "signal": "force" }, "shape": "line", "sourceX": "datum.source.x", "sourceY": "datum.source.y", "targetX": "datum.target.x", "targetY": "datum.target.y" } ] } ], "scales": [ { "domain": { "data": "node-data", "field": "group" }, "name": "color", "type": "ordinal", "range": { "scheme": "category20c" } } ], "signals": [ { "name": "hoverIndex", "value": -1, "on": [ { "events": "symbol:mouseover", "update": "datum.index" }, { "events": "symbol:mouseout", "update": "-1" } ] }, { "name": "cx", "update": "width / 2" }, { "name": "cy", "update": "height / 2" }, { "name": "nodeRadius", "bind": { "input": "range", "max": 50, "min": 1, "step": 1 }, "value": 8 }, { "name": "nodeCharge", "bind": { "input": "range", "max": 10, "min": -100, "step": 1 }, "value": -30 }, { "name": "linkDistance", "bind": { "input": "range", "max": 100, "min": 5, "step": 1 }, "value": 30 }, { "name": "static", "bind": { "input": "checkbox" }, "value": true }, { "description": "State variable for active node fix status.", "name": "fix", "on": [ { "events": "symbol:pointerout[!event.buttons], window:pointerup", "update": "false" }, { "events": "symbol:pointerover", "update": "fix || true" }, { "events": "[symbol:pointerdown, window:pointerup] > window:pointermove!", "force": true, "update": "xy()" } ], "value": false }, { "description": "Graph node most recently interacted with.", "name": "node", "on": [ { "events": "symbol:pointerover", "update": "fix === true ? item() : node" } ] }, { "description": "Flag to restart Force simulation upon data changes.", "name": "restart", "on": [ { "events": { "signal": "fix" }, "update": "fix && fix.length" } ], "value": false } ], "$schema": "https://vega.github.io/schema/vega/v5.json", "autosize": "none", "description": "A node-link diagram with force-directed layout, depicting character co-occurrence in the novel Les Misérables.", "height": 800, "padding": 0, "width": 800 } |