updated to d3v4, modern js, and prettier formatted
an iteration on Force-Directed SVG Icons from @syntagmatic
Replaces the circles in the force-directed graph with some SVG icons.
border: no | |
license: MIT |
updated to d3v4, modern js, and prettier formatted
an iteration on Force-Directed SVG Icons from @syntagmatic
Replaces the circles in the force-directed graph with some SVG icons.
<!DOCTYPE html> | |
<meta charset='utf-8'> | |
<style> | |
.links line { | |
stroke: #999; | |
stroke-opacity: 0.6; | |
} | |
.nodes { | |
stroke: #fff; | |
stroke-width: 1.5px; | |
} | |
</style> | |
<body> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js'></script> | |
<script src='vis.js'></script> |
# safe | |
lebab --replace vis.js --transform arrow | |
lebab --replace vis.js --transform for-of | |
lebab --replace vis.js --transform for-each | |
lebab --replace vis.js --transform arg-rest | |
lebab --replace vis.js --transform arg-spread | |
lebab --replace vis.js --transform obj-method | |
lebab --replace vis.js --transform obj-shorthand | |
lebab --replace vis.js --transform multi-var | |
# unsafe | |
lebab --replace vis.js --transform let | |
lebab --replace vis.js --transform template |
{ | |
"nodes":[ | |
{"name":"Myriel","group":1}, | |
{"name":"Napoleon","group":1}, | |
{"name":"Mlle.Baptistine","group":1}, | |
{"name":"Mme.Magloire","group":1}, | |
{"name":"CountessdeLo","group":1}, | |
{"name":"Geborand","group":1}, | |
{"name":"Champtercier","group":1}, | |
{"name":"Cravatte","group":1}, | |
{"name":"Count","group":1}, | |
{"name":"OldMan","group":1}, | |
{"name":"Labarre","group":2}, | |
{"name":"Valjean","group":2}, | |
{"name":"Marguerite","group":3}, | |
{"name":"Mme.deR","group":2}, | |
{"name":"Isabeau","group":2}, | |
{"name":"Gervais","group":2}, | |
{"name":"Tholomyes","group":3}, | |
{"name":"Listolier","group":3}, | |
{"name":"Fameuil","group":3}, | |
{"name":"Blacheville","group":3}, | |
{"name":"Favourite","group":3}, | |
{"name":"Dahlia","group":3}, | |
{"name":"Zephine","group":3}, | |
{"name":"Fantine","group":3}, | |
{"name":"Mme.Thenardier","group":4}, | |
{"name":"Thenardier","group":4}, | |
{"name":"Cosette","group":5}, | |
{"name":"Javert","group":4}, | |
{"name":"Fauchelevent","group":0}, | |
{"name":"Bamatabois","group":2}, | |
{"name":"Perpetue","group":3}, | |
{"name":"Simplice","group":2}, | |
{"name":"Scaufflaire","group":2}, | |
{"name":"Woman1","group":2}, | |
{"name":"Judge","group":2}, | |
{"name":"Champmathieu","group":2}, | |
{"name":"Brevet","group":2}, | |
{"name":"Chenildieu","group":2}, | |
{"name":"Cochepaille","group":2}, | |
{"name":"Pontmercy","group":4}, | |
{"name":"Boulatruelle","group":6}, | |
{"name":"Eponine","group":4}, | |
{"name":"Anzelma","group":4}, | |
{"name":"Woman2","group":5}, | |
{"name":"MotherInnocent","group":0}, | |
{"name":"Gribier","group":0}, | |
{"name":"Jondrette","group":7}, | |
{"name":"Mme.Burgon","group":7}, | |
{"name":"Gavroche","group":8}, | |
{"name":"Gillenormand","group":5}, | |
{"name":"Magnon","group":5}, | |
{"name":"Mlle.Gillenormand","group":5}, | |
{"name":"Mme.Pontmercy","group":5}, | |
{"name":"Mlle.Vaubois","group":5}, | |
{"name":"Lt.Gillenormand","group":5}, | |
{"name":"Marius","group":8}, | |
{"name":"BaronessT","group":5}, | |
{"name":"Mabeuf","group":8}, | |
{"name":"Enjolras","group":8}, | |
{"name":"Combeferre","group":8}, | |
{"name":"Prouvaire","group":8}, | |
{"name":"Feuilly","group":8}, | |
{"name":"Courfeyrac","group":8}, | |
{"name":"Bahorel","group":8}, | |
{"name":"Bossuet","group":8}, | |
{"name":"Joly","group":8}, | |
{"name":"Grantaire","group":8}, | |
{"name":"MotherPlutarch","group":9}, | |
{"name":"Gueulemer","group":4}, | |
{"name":"Babet","group":4}, | |
{"name":"Claquesous","group":4}, | |
{"name":"Montparnasse","group":4}, | |
{"name":"Toussaint","group":5}, | |
{"name":"Child1","group":10}, | |
{"name":"Child2","group":10}, | |
{"name":"Brujon","group":4}, | |
{"name":"Mme.Hucheloup","group":8} | |
], | |
"links":[ | |
{"source":1,"target":0,"value":1}, | |
{"source":2,"target":0,"value":8}, | |
{"source":3,"target":0,"value":10}, | |
{"source":3,"target":2,"value":6}, | |
{"source":4,"target":0,"value":1}, | |
{"source":5,"target":0,"value":1}, | |
{"source":6,"target":0,"value":1}, | |
{"source":7,"target":0,"value":1}, | |
{"source":8,"target":0,"value":2}, | |
{"source":9,"target":0,"value":1}, | |
{"source":11,"target":10,"value":1}, | |
{"source":11,"target":3,"value":3}, | |
{"source":11,"target":2,"value":3}, | |
{"source":11,"target":0,"value":5}, | |
{"source":12,"target":11,"value":1}, | |
{"source":13,"target":11,"value":1}, | |
{"source":14,"target":11,"value":1}, | |
{"source":15,"target":11,"value":1}, | |
{"source":17,"target":16,"value":4}, | |
{"source":18,"target":16,"value":4}, | |
{"source":18,"target":17,"value":4}, | |
{"source":19,"target":16,"value":4}, | |
{"source":19,"target":17,"value":4}, | |
{"source":19,"target":18,"value":4}, | |
{"source":20,"target":16,"value":3}, | |
{"source":20,"target":17,"value":3}, | |
{"source":20,"target":18,"value":3}, | |
{"source":20,"target":19,"value":4}, | |
{"source":21,"target":16,"value":3}, | |
{"source":21,"target":17,"value":3}, | |
{"source":21,"target":18,"value":3}, | |
{"source":21,"target":19,"value":3}, | |
{"source":21,"target":20,"value":5}, | |
{"source":22,"target":16,"value":3}, | |
{"source":22,"target":17,"value":3}, | |
{"source":22,"target":18,"value":3}, | |
{"source":22,"target":19,"value":3}, | |
{"source":22,"target":20,"value":4}, | |
{"source":22,"target":21,"value":4}, | |
{"source":23,"target":16,"value":3}, | |
{"source":23,"target":17,"value":3}, | |
{"source":23,"target":18,"value":3}, | |
{"source":23,"target":19,"value":3}, | |
{"source":23,"target":20,"value":4}, | |
{"source":23,"target":21,"value":4}, | |
{"source":23,"target":22,"value":4}, | |
{"source":23,"target":12,"value":2}, | |
{"source":23,"target":11,"value":9}, | |
{"source":24,"target":23,"value":2}, | |
{"source":24,"target":11,"value":7}, | |
{"source":25,"target":24,"value":13}, | |
{"source":25,"target":23,"value":1}, | |
{"source":25,"target":11,"value":12}, | |
{"source":26,"target":24,"value":4}, | |
{"source":26,"target":11,"value":31}, | |
{"source":26,"target":16,"value":1}, | |
{"source":26,"target":25,"value":1}, | |
{"source":27,"target":11,"value":17}, | |
{"source":27,"target":23,"value":5}, | |
{"source":27,"target":25,"value":5}, | |
{"source":27,"target":24,"value":1}, | |
{"source":27,"target":26,"value":1}, | |
{"source":28,"target":11,"value":8}, | |
{"source":28,"target":27,"value":1}, | |
{"source":29,"target":23,"value":1}, | |
{"source":29,"target":27,"value":1}, | |
{"source":29,"target":11,"value":2}, | |
{"source":30,"target":23,"value":1}, | |
{"source":31,"target":30,"value":2}, | |
{"source":31,"target":11,"value":3}, | |
{"source":31,"target":23,"value":2}, | |
{"source":31,"target":27,"value":1}, | |
{"source":32,"target":11,"value":1}, | |
{"source":33,"target":11,"value":2}, | |
{"source":33,"target":27,"value":1}, | |
{"source":34,"target":11,"value":3}, | |
{"source":34,"target":29,"value":2}, | |
{"source":35,"target":11,"value":3}, | |
{"source":35,"target":34,"value":3}, | |
{"source":35,"target":29,"value":2}, | |
{"source":36,"target":34,"value":2}, | |
{"source":36,"target":35,"value":2}, | |
{"source":36,"target":11,"value":2}, | |
{"source":36,"target":29,"value":1}, | |
{"source":37,"target":34,"value":2}, | |
{"source":37,"target":35,"value":2}, | |
{"source":37,"target":36,"value":2}, | |
{"source":37,"target":11,"value":2}, | |
{"source":37,"target":29,"value":1}, | |
{"source":38,"target":34,"value":2}, | |
{"source":38,"target":35,"value":2}, | |
{"source":38,"target":36,"value":2}, | |
{"source":38,"target":37,"value":2}, | |
{"source":38,"target":11,"value":2}, | |
{"source":38,"target":29,"value":1}, | |
{"source":39,"target":25,"value":1}, | |
{"source":40,"target":25,"value":1}, | |
{"source":41,"target":24,"value":2}, | |
{"source":41,"target":25,"value":3}, | |
{"source":42,"target":41,"value":2}, | |
{"source":42,"target":25,"value":2}, | |
{"source":42,"target":24,"value":1}, | |
{"source":43,"target":11,"value":3}, | |
{"source":43,"target":26,"value":1}, | |
{"source":43,"target":27,"value":1}, | |
{"source":44,"target":28,"value":3}, | |
{"source":44,"target":11,"value":1}, | |
{"source":45,"target":28,"value":2}, | |
{"source":47,"target":46,"value":1}, | |
{"source":48,"target":47,"value":2}, | |
{"source":48,"target":25,"value":1}, | |
{"source":48,"target":27,"value":1}, | |
{"source":48,"target":11,"value":1}, | |
{"source":49,"target":26,"value":3}, | |
{"source":49,"target":11,"value":2}, | |
{"source":50,"target":49,"value":1}, | |
{"source":50,"target":24,"value":1}, | |
{"source":51,"target":49,"value":9}, | |
{"source":51,"target":26,"value":2}, | |
{"source":51,"target":11,"value":2}, | |
{"source":52,"target":51,"value":1}, | |
{"source":52,"target":39,"value":1}, | |
{"source":53,"target":51,"value":1}, | |
{"source":54,"target":51,"value":2}, | |
{"source":54,"target":49,"value":1}, | |
{"source":54,"target":26,"value":1}, | |
{"source":55,"target":51,"value":6}, | |
{"source":55,"target":49,"value":12}, | |
{"source":55,"target":39,"value":1}, | |
{"source":55,"target":54,"value":1}, | |
{"source":55,"target":26,"value":21}, | |
{"source":55,"target":11,"value":19}, | |
{"source":55,"target":16,"value":1}, | |
{"source":55,"target":25,"value":2}, | |
{"source":55,"target":41,"value":5}, | |
{"source":55,"target":48,"value":4}, | |
{"source":56,"target":49,"value":1}, | |
{"source":56,"target":55,"value":1}, | |
{"source":57,"target":55,"value":1}, | |
{"source":57,"target":41,"value":1}, | |
{"source":57,"target":48,"value":1}, | |
{"source":58,"target":55,"value":7}, | |
{"source":58,"target":48,"value":7}, | |
{"source":58,"target":27,"value":6}, | |
{"source":58,"target":57,"value":1}, | |
{"source":58,"target":11,"value":4}, | |
{"source":59,"target":58,"value":15}, | |
{"source":59,"target":55,"value":5}, | |
{"source":59,"target":48,"value":6}, | |
{"source":59,"target":57,"value":2}, | |
{"source":60,"target":48,"value":1}, | |
{"source":60,"target":58,"value":4}, | |
{"source":60,"target":59,"value":2}, | |
{"source":61,"target":48,"value":2}, | |
{"source":61,"target":58,"value":6}, | |
{"source":61,"target":60,"value":2}, | |
{"source":61,"target":59,"value":5}, | |
{"source":61,"target":57,"value":1}, | |
{"source":61,"target":55,"value":1}, | |
{"source":62,"target":55,"value":9}, | |
{"source":62,"target":58,"value":17}, | |
{"source":62,"target":59,"value":13}, | |
{"source":62,"target":48,"value":7}, | |
{"source":62,"target":57,"value":2}, | |
{"source":62,"target":41,"value":1}, | |
{"source":62,"target":61,"value":6}, | |
{"source":62,"target":60,"value":3}, | |
{"source":63,"target":59,"value":5}, | |
{"source":63,"target":48,"value":5}, | |
{"source":63,"target":62,"value":6}, | |
{"source":63,"target":57,"value":2}, | |
{"source":63,"target":58,"value":4}, | |
{"source":63,"target":61,"value":3}, | |
{"source":63,"target":60,"value":2}, | |
{"source":63,"target":55,"value":1}, | |
{"source":64,"target":55,"value":5}, | |
{"source":64,"target":62,"value":12}, | |
{"source":64,"target":48,"value":5}, | |
{"source":64,"target":63,"value":4}, | |
{"source":64,"target":58,"value":10}, | |
{"source":64,"target":61,"value":6}, | |
{"source":64,"target":60,"value":2}, | |
{"source":64,"target":59,"value":9}, | |
{"source":64,"target":57,"value":1}, | |
{"source":64,"target":11,"value":1}, | |
{"source":65,"target":63,"value":5}, | |
{"source":65,"target":64,"value":7}, | |
{"source":65,"target":48,"value":3}, | |
{"source":65,"target":62,"value":5}, | |
{"source":65,"target":58,"value":5}, | |
{"source":65,"target":61,"value":5}, | |
{"source":65,"target":60,"value":2}, | |
{"source":65,"target":59,"value":5}, | |
{"source":65,"target":57,"value":1}, | |
{"source":65,"target":55,"value":2}, | |
{"source":66,"target":64,"value":3}, | |
{"source":66,"target":58,"value":3}, | |
{"source":66,"target":59,"value":1}, | |
{"source":66,"target":62,"value":2}, | |
{"source":66,"target":65,"value":2}, | |
{"source":66,"target":48,"value":1}, | |
{"source":66,"target":63,"value":1}, | |
{"source":66,"target":61,"value":1}, | |
{"source":66,"target":60,"value":1}, | |
{"source":67,"target":57,"value":3}, | |
{"source":68,"target":25,"value":5}, | |
{"source":68,"target":11,"value":1}, | |
{"source":68,"target":24,"value":1}, | |
{"source":68,"target":27,"value":1}, | |
{"source":68,"target":48,"value":1}, | |
{"source":68,"target":41,"value":1}, | |
{"source":69,"target":25,"value":6}, | |
{"source":69,"target":68,"value":6}, | |
{"source":69,"target":11,"value":1}, | |
{"source":69,"target":24,"value":1}, | |
{"source":69,"target":27,"value":2}, | |
{"source":69,"target":48,"value":1}, | |
{"source":69,"target":41,"value":1}, | |
{"source":70,"target":25,"value":4}, | |
{"source":70,"target":69,"value":4}, | |
{"source":70,"target":68,"value":4}, | |
{"source":70,"target":11,"value":1}, | |
{"source":70,"target":24,"value":1}, | |
{"source":70,"target":27,"value":1}, | |
{"source":70,"target":41,"value":1}, | |
{"source":70,"target":58,"value":1}, | |
{"source":71,"target":27,"value":1}, | |
{"source":71,"target":69,"value":2}, | |
{"source":71,"target":68,"value":2}, | |
{"source":71,"target":70,"value":2}, | |
{"source":71,"target":11,"value":1}, | |
{"source":71,"target":48,"value":1}, | |
{"source":71,"target":41,"value":1}, | |
{"source":71,"target":25,"value":1}, | |
{"source":72,"target":26,"value":2}, | |
{"source":72,"target":27,"value":1}, | |
{"source":72,"target":11,"value":1}, | |
{"source":73,"target":48,"value":2}, | |
{"source":74,"target":48,"value":2}, | |
{"source":74,"target":73,"value":3}, | |
{"source":75,"target":69,"value":3}, | |
{"source":75,"target":68,"value":3}, | |
{"source":75,"target":25,"value":3}, | |
{"source":75,"target":48,"value":1}, | |
{"source":75,"target":41,"value":1}, | |
{"source":75,"target":70,"value":1}, | |
{"source":75,"target":71,"value":1}, | |
{"source":76,"target":64,"value":1}, | |
{"source":76,"target":65,"value":1}, | |
{"source":76,"target":66,"value":1}, | |
{"source":76,"target":63,"value":1}, | |
{"source":76,"target":62,"value":1}, | |
{"source":76,"target":48,"value":1}, | |
{"source":76,"target":58,"value":1} | |
] | |
} |
const logos = { | |
star: | |
'M14.615,4.928c0.487-0.986,1.284-0.986,1.771,0l2.249,4.554c0.486,0.986,1.775,1.923,2.864,2.081l5.024,0.73c1.089,0.158,1.335,0.916,0.547,1.684l-3.636,3.544c-0.788,0.769-1.28,2.283-1.095,3.368l0.859,5.004c0.186,1.085-0.459,1.553-1.433,1.041l-4.495-2.363c-0.974-0.512-2.567-0.512-3.541,0l-4.495,2.363c-0.974,0.512-1.618,0.044-1.432-1.041l0.858-5.004c0.186-1.085-0.307-2.6-1.094-3.368L3.93,13.977c-0.788-0.768-0.542-1.525,0.547-1.684l5.026-0.73c1.088-0.158,2.377-1.095,2.864-2.081L14.615,4.928z', | |
apple: | |
'M24.32,10.85c-1.743,1.233-2.615,2.719-2.615,4.455c0,2.079,1.078,3.673,3.232,4.786c-0.578,1.677-1.416,3.134-2.514,4.375c-1.097,1.241-2.098,1.862-3.004,1.862c-0.427,0-1.009-0.143-1.748-0.423l-0.354-0.138c-0.725-0.281-1.363-0.423-1.92-0.423c-0.525,0-1.1,0.11-1.725,0.331l-0.445,0.16l-0.56,0.229c-0.441,0.176-0.888,0.264-1.337,0.264c-1.059,0-2.228-0.872-3.507-2.616c-1.843-2.498-2.764-5.221-2.764-8.167c0-2.095,0.574-3.781,1.725-5.061c1.149-1.279,2.673-1.92,4.568-1.92c0.709,0,1.371,0.13,1.988,0.389l0.423,0.172l0.445,0.183c0.396,0.167,0.716,0.251,0.959,0.251c0.312,0,0.659-0.072,1.04-0.217l0.582-0.229l0.435-0.16c0.693-0.251,1.459-0.377,2.297-0.377C21.512,8.576,23.109,9.334,24.32,10.85zM19.615,3.287c0.021,0.267,0.033,0.473,0.033,0.617c0,1.317-0.479,2.473-1.438,3.467s-2.075,1.49-3.347,1.49c-0.038-0.297-0.058-0.51-0.058-0.639c0-1.12,0.445-2.171,1.337-3.153c0.891-0.982,1.922-1.558,3.096-1.725C19.32,3.329,19.447,3.311,19.615,3.287z', | |
glasses: | |
'M14.075,9.531c0,0-2.705-1.438-5.158-1.438c-2.453,0-4.862,0.593-4.862,0.593L3.971,9.869c0,0,0.19,0.19,0.528,0.53c0.338,0.336,0.486,3.741,1.838,5.094c1.353,1.354,4.82,1.396,5.963,0.676c1.14-0.718,2.241-3.466,2.241-4.693c0-0.38,0-0.676,0-0.676c0.274-0.275,1.615-0.303,1.917,0c0,0,0,0.296,0,0.676c0,1.227,1.101,3.975,2.241,4.693c1.144,0.72,4.611,0.678,5.963-0.676c1.355-1.353,1.501-4.757,1.839-5.094c0.338-0.34,0.528-0.53,0.528-0.53l-0.084-1.183c0,0-2.408-0.593-4.862-0.593c-2.453,0-5.158,1.438-5.158,1.438C16.319,9.292,14.737,9.32,14.075,9.531z' | |
} | |
const groupLogo = { | |
1: logos.star, | |
2: logos.apple | |
} | |
const width = 960 | |
const height = 500 | |
const svg = d3 | |
.select('body') | |
.append('svg') | |
.attr('width', width) | |
.attr('height', height) | |
const color = d3.scaleOrdinal(d3.schemeCategory20) | |
const simulation = d3 | |
.forceSimulation() | |
.force('link', d3.forceLink().id(d => d.id)) | |
.force('charge', d3.forceManyBody()) | |
.force('center', d3.forceCenter(width / 2, height / 2)) | |
d3.json('miserables.json', (error, graph) => { | |
// add an id to each node | |
graph.nodes.forEach((node, i) => { | |
node.id = i | |
}) | |
const linkG = svg | |
.append('g') | |
.attr('class', 'links') | |
.selectAll('line') | |
.data(graph.links) | |
.enter() | |
.append('line') | |
.style('stroke-width', d => Math.sqrt(d.value)) | |
const nodeG = svg | |
.append('g') | |
.attr('class', 'nodes') | |
.selectAll('path') | |
.data(graph.nodes) | |
.enter() | |
.append('path') | |
.attr('d', d => { | |
if (d.group in groupLogo) return groupLogo[d.group] | |
return logos.glasses | |
}) | |
.attr('transform', 'scale(0.75)') | |
.style('fill', d => color(d.group)) | |
.call( | |
d3 | |
.drag() | |
.on('start', dragstarted) | |
.on('drag', dragged) | |
.on('end', dragended) | |
) | |
nodeG.append('title').text(d => d.name) | |
simulation.nodes(graph.nodes).on('tick', ticked) | |
simulation.force('link').links(graph.links) | |
function ticked() { | |
linkG | |
.attr('x1', d => d.source.x) | |
.attr('y1', d => d.source.y) | |
.attr('x2', d => d.target.x) | |
.attr('y2', d => d.target.y) | |
nodeG.attr('transform', d => `translate(${d.x - 12},${d.y - 12})`) | |
} | |
function dragstarted(d) { | |
if (!d3.event.active) simulation.alphaTarget(0.3).restart() | |
d.fx = d.x | |
d.fy = d.y | |
} | |
function dragged(d) { | |
d.fx = d3.event.x | |
d.fy = d3.event.y | |
} | |
function dragended(d) { | |
if (!d3.event.active) simulation.alphaTarget(0) | |
d.fx = null | |
d.fy = null | |
} | |
}) |