D3: Efficient visualization of a complex directed acyclic graph (project dependencies) - d3.js

I am currently exploring a large proprietary code base with many individual projects and interdependencies. To get a better overview, I would like to create a graphical representation of the dependencies, which are represented by a directed acyclic graph. The hope is, to finally better understand dependency clusters and (with knowledge about the individual project's contents) to aid restructuring of projects and dependencies.
Currently, I am using D3 for the visualization. Below is the full code of my current attempt (with project names replaced by a dummy). As you can see, it still looks pretty messy. Some order can be seen when hovering over project nodes.
I already looked at (but did not try out, yet) d3-dag, which might be promising but only contains examples with rather small data sets.
I also thought about something like a graph using hierarchical edge bundling, but there is not really a hierarchy here.
Does anybody have a recommendation for a better approach than the currently used force simulation layout?
<!DOCTYPE html>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<style>
#controls {
position: fixed;
left: 0px;
width: 20%;
top: 0px;
height: 10%;
}
#chart {
position: fixed;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
}
path.link {
fill: none;
stroke: #c5c5c5;
stroke-width: 1.0px;
}
circle {
fill: #ccc;
stroke: #fff;
stroke-width: 1.5px;
}
text {
fill: #000000;
font: 11px sans-serif;
pointer-events: none;
}
.ingoing {
stroke: #237690!important;
stroke-width: 1.5px!important;
}
.outgoing {
stroke: #FA1209!important;
stroke-width: 1.5px!important;
}
.selected {
stroke: #000000!important;
stroke-width: 1.5px!important;
}
</style>
<body>
<div id="chart"></div>
<div id="controls">
<input type="checkbox" id="cb_hierarchical" checked="True" onclick='redraw();'>Order by dependency chain<br>
<input type="checkbox" id="cb_curved" checked="True" onclick='redraw();'>Curved Lines<br>
</div>
<script>
graph = JSON.parse('{"directed": true, "graph": [], "nodes": [{"id": 0, "name": "Project", "level": 7}, {"id": 1, "name": "Project", "level": 2}, {"id": 2, "name": "Project", "level": 12}, {"id": 3, "name": "Project", "level": 12}, {"id": 4, "name": "Project", "level": 3}, {"id": 5, "name": "Project", "level": 3}, {"id": 6, "name": "Project", "level": 8}, {"id": 7, "name": "Project", "level": 9}, {"id": 8, "name": "Project", "level": 1}, {"id": 9, "name": "Project", "level": 5}, {"id": 10, "name": "Project", "level": 12}, {"id": 11, "name": "Project", "level": 8}, {"id": 12, "name": "Project", "level": 10}, {"id": 13, "name": "Project", "level": 4}, {"id": 14, "name": "Project", "level": 3}, {"id": 15, "name": "Project", "level": 6}, {"id": 16, "name": "Project", "level": 7}, {"id": 17, "name": "Project", "level": 3}, {"id": 18, "name": "Project", "level": 9}, {"id": 19, "name": "Project", "level": 9}, {"id": 20, "name": "Project", "level": 7}, {"id": 21, "name": "Project", "level": 13}, {"id": 22, "name": "Project", "level": 7}, {"id": 23, "name": "Project", "level": 8}, {"id": 24, "name": "Project", "level": 3}, {"id": 25, "name": "Project", "level": 0}, {"id": 26, "name": "Project", "level": 6}, {"id": 27, "name": "Project", "level": 7}, {"id": 28, "name": "Project", "level": 15}, {"id": 29, "name": "Project", "level": 8}, {"id": 30, "name": "Project", "level": 9}, {"id": 31, "name": "Project", "level": 3}, {"id": 32, "name": "Project", "level": 8}, {"id": 33, "name": "Project", "level": 3}, {"id": 34, "name": "Project", "level": 2}, {"id": 35, "name": "Project", "level": 12}, {"id": 36, "name": "Project", "level": 8}, {"id": 37, "name": "Project", "level": 6}, {"id": 38, "name": "Project", "level": 8}, {"id": 39, "name": "Project", "level": 8}, {"id": 40, "name": "Project", "level": 6}, {"id": 41, "name": "Project", "level": 8}, {"id": 42, "name": "Project", "level": 8}, {"id": 43, "name": "Project", "level": 5}, {"id": 44, "name": "Project", "level": 15}, {"id": 45, "name": "Project", "level": 1}, {"id": 46, "name": "Project", "level": 12}, {"id": 47, "name": "Project", "level": 8}, {"id": 48, "name": "Project", "level": 7}, {"id": 49, "name": "Project", "level": 1}, {"id": 50, "name": "Project", "level": 14}, {"id": 51, "name": "Project", "level": 1}, {"id": 52, "name": "Project", "level": 6}, {"id": 53, "name": "Project", "level": 15}, {"id": 54, "name": "Project", "level": 15}, {"id": 55, "name": "Project", "level": 9}, {"id": 56, "name": "Project", "level": 4}, {"id": 57, "name": "Project", "level": 8}, {"id": 58, "name": "Project", "level": 1}, {"id": 59, "name": "Project", "level": 1}, {"id": 60, "name": "Project", "level": 15}, {"id": 61, "name": "Project", "level": 7}, {"id": 62, "name": "Project", "level": 8}, {"id": 63, "name": "Project", "level": 7}, {"id": 64, "name": "Project", "level": 3}, {"id": 65, "name": "Project", "level": 7}, {"id": 66, "name": "Project", "level": 1}, {"id": 67, "name": "Project", "level": 14}, {"id": 68, "name": "Project", "level": 5}, {"id": 69, "name": "Project", "level": 8}, {"id": 70, "name": "Project", "level": 7}, {"id": 71, "name": "Project", "level": 7}, {"id": 72, "name": "Project", "level": 5}, {"id": 73, "name": "Project", "level": 6}, {"id": 74, "name": "Project", "level": 2}, {"id": 75, "name": "Project", "level": 7}, {"id": 76, "name": "Project", "level": 4}, {"id": 77, "name": "Project", "level": 3}, {"id": 78, "name": "Project", "level": 8}, {"id": 79, "name": "Project", "level": 4}, {"id": 80, "name": "Project", "level": 3}, {"id": 81, "name": "Project", "level": 2}, {"id": 82, "name": "Project", "level": 16}, {"id": 83, "name": "Project", "level": 13}, {"id": 84, "name": "Project", "level": 12}, {"id": 85, "name": "Project", "level": 11}, {"id": 86, "name": "Project", "level": 3}, {"id": 87, "name": "Project", "level": 9}, {"id": 88, "name": "Project", "level": 2}, {"id": 89, "name": "Project", "level": 6}, {"id": 90, "name": "Project", "level": 5}, {"id": 91, "name": "Project", "level": 3}, {"id": 92, "name": "Project", "level": 5}, {"id": 93, "name": "Project", "level": 5}, {"id": 94, "name": "Project", "level": 4}, {"id": 95, "name": "Project", "level": 1}, {"id": 96, "name": "Project", "level": 13}, {"id": 97, "name": "Project", "level": 8}, {"id": 98, "name": "Project", "level": 5}, {"id": 99, "name": "Project", "level": 4}, {"id": 100, "name": "Project", "level": 6}, {"id": 101, "name": "Project", "level": 8}, {"id": 102, "name": "Project", "level": 11}, {"id": 103, "name": "Project", "level": 5}, {"id": 104, "name": "Project", "level": 10}], "links": [{"source": 0, "target": 57}, {"source": 0, "target": 36}, {"source": 0, "target": 23}, {"source": 0, "target": 82}, {"source": 0, "target": 39}, {"source": 0, "target": 18}, {"source": 0, "target": 41}, {"source": 0, "target": 6}, {"source": 0, "target": 85}, {"source": 0, "target": 60}, {"source": 1, "target": 50}, {"source": 1, "target": 4}, {"source": 1, "target": 77}, {"source": 1, "target": 85}, {"source": 1, "target": 75}, {"source": 1, "target": 14}, {"source": 2, "target": 50}, {"source": 2, "target": 83}, {"source": 2, "target": 67}, {"source": 3, "target": 50}, {"source": 3, "target": 67}, {"source": 3, "target": 21}, {"source": 4, "target": 50}, {"source": 4, "target": 7}, {"source": 4, "target": 20}, {"source": 5, "target": 75}, {"source": 5, "target": 60}, {"source": 5, "target": 85}, {"source": 6, "target": 104}, {"source": 7, "target": 50}, {"source": 7, "target": 12}, {"source": 7, "target": 85}, {"source": 8, "target": 50}, {"source": 8, "target": 35}, {"source": 8, "target": 91}, {"source": 8, "target": 96}, {"source": 8, "target": 26}, {"source": 8, "target": 68}, {"source": 9, "target": 101}, {"source": 9, "target": 7}, {"source": 9, "target": 62}, {"source": 12, "target": 85}, {"source": 12, "target": 102}, {"source": 13, "target": 22}, {"source": 13, "target": 52}, {"source": 13, "target": 27}, {"source": 13, "target": 47}, {"source": 13, "target": 30}, {"source": 13, "target": 43}, {"source": 13, "target": 60}, {"source": 13, "target": 61}, {"source": 13, "target": 62}, {"source": 13, "target": 92}, {"source": 13, "target": 7}, {"source": 13, "target": 9}, {"source": 13, "target": 70}, {"source": 13, "target": 68}, {"source": 13, "target": 12}, {"source": 13, "target": 37}, {"source": 13, "target": 73}, {"source": 13, "target": 15}, {"source": 13, "target": 16}, {"source": 13, "target": 100}, {"source": 13, "target": 101}, {"source": 13, "target": 20}, {"source": 13, "target": 103}, {"source": 14, "target": 75}, {"source": 14, "target": 50}, {"source": 14, "target": 85}, {"source": 14, "target": 56}, {"source": 14, "target": 98}, {"source": 15, "target": 70}, {"source": 15, "target": 22}, {"source": 15, "target": 7}, {"source": 16, "target": 85}, {"source": 16, "target": 101}, {"source": 17, "target": 50}, {"source": 17, "target": 85}, {"source": 18, "target": 35}, {"source": 25, "target": 30}, {"source": 25, "target": 51}, {"source": 25, "target": 80}, {"source": 25, "target": 4}, {"source": 25, "target": 95}, {"source": 25, "target": 13}, {"source": 25, "target": 59}, {"source": 25, "target": 77}, {"source": 25, "target": 1}, {"source": 25, "target": 75}, {"source": 25, "target": 8}, {"source": 25, "target": 64}, {"source": 25, "target": 14}, {"source": 25, "target": 49}, {"source": 25, "target": 33}, {"source": 25, "target": 58}, {"source": 25, "target": 66}, {"source": 25, "target": 45}, {"source": 20, "target": 85}, {"source": 20, "target": 7}, {"source": 21, "target": 67}, {"source": 22, "target": 85}, {"source": 24, "target": 50}, {"source": 24, "target": 85}, {"source": 26, "target": 30}, {"source": 26, "target": 50}, {"source": 26, "target": 35}, {"source": 26, "target": 0}, {"source": 26, "target": 63}, {"source": 26, "target": 48}, {"source": 26, "target": 75}, {"source": 26, "target": 65}, {"source": 27, "target": 101}, {"source": 29, "target": 50}, {"source": 29, "target": 60}, {"source": 29, "target": 87}, {"source": 29, "target": 19}, {"source": 30, "target": 60}, {"source": 30, "target": 44}, {"source": 30, "target": 85}, {"source": 30, "target": 21}, {"source": 30, "target": 53}, {"source": 32, "target": 50}, {"source": 32, "target": 60}, {"source": 32, "target": 18}, {"source": 32, "target": 19}, {"source": 33, "target": 99}, {"source": 33, "target": 48}, {"source": 33, "target": 26}, {"source": 33, "target": 75}, {"source": 33, "target": 98}, {"source": 33, "target": 68}, {"source": 33, "target": 79}, {"source": 34, "target": 75}, {"source": 34, "target": 17}, {"source": 34, "target": 33}, {"source": 37, "target": 27}, {"source": 37, "target": 70}, {"source": 37, "target": 101}, {"source": 38, "target": 67}, {"source": 38, "target": 96}, {"source": 40, "target": 67}, {"source": 41, "target": 82}, {"source": 66, "target": 75}, {"source": 66, "target": 74}, {"source": 66, "target": 88}, {"source": 45, "target": 81}, {"source": 47, "target": 30}, {"source": 47, "target": 67}, {"source": 47, "target": 46}, {"source": 47, "target": 96}, {"source": 48, "target": 32}, {"source": 48, "target": 18}, {"source": 48, "target": 29}, {"source": 49, "target": 50}, {"source": 49, "target": 60}, {"source": 49, "target": 85}, {"source": 49, "target": 5}, {"source": 50, "target": 60}, {"source": 50, "target": 44}, {"source": 50, "target": 54}, {"source": 50, "target": 53}, {"source": 51, "target": 75}, {"source": 51, "target": 65}, {"source": 51, "target": 34}, {"source": 51, "target": 33}, {"source": 52, "target": 7}, {"source": 52, "target": 101}, {"source": 56, "target": 75}, {"source": 56, "target": 65}, {"source": 56, "target": 98}, {"source": 58, "target": 75}, {"source": 58, "target": 17}, {"source": 58, "target": 33}, {"source": 59, "target": 50}, {"source": 59, "target": 35}, {"source": 59, "target": 1}, {"source": 59, "target": 31}, {"source": 59, "target": 85}, {"source": 59, "target": 72}, {"source": 59, "target": 75}, {"source": 59, "target": 14}, {"source": 59, "target": 67}, {"source": 60, "target": 82}, {"source": 62, "target": 50}, {"source": 62, "target": 60}, {"source": 62, "target": 85}, {"source": 62, "target": 55}, {"source": 63, "target": 87}, {"source": 63, "target": 36}, {"source": 63, "target": 69}, {"source": 63, "target": 23}, {"source": 63, "target": 82}, {"source": 63, "target": 60}, {"source": 63, "target": 41}, {"source": 63, "target": 85}, {"source": 63, "target": 97}, {"source": 63, "target": 11}, {"source": 64, "target": 15}, {"source": 64, "target": 16}, {"source": 64, "target": 22}, {"source": 64, "target": 52}, {"source": 64, "target": 100}, {"source": 64, "target": 101}, {"source": 64, "target": 85}, {"source": 64, "target": 9}, {"source": 64, "target": 62}, {"source": 64, "target": 94}, {"source": 65, "target": 42}, {"source": 67, "target": 28}, {"source": 68, "target": 50}, {"source": 68, "target": 60}, {"source": 70, "target": 50}, {"source": 70, "target": 62}, {"source": 70, "target": 84}, {"source": 70, "target": 85}, {"source": 70, "target": 7}, {"source": 70, "target": 47}, {"source": 71, "target": 38}, {"source": 71, "target": 67}, {"source": 71, "target": 78}, {"source": 72, "target": 30}, {"source": 73, "target": 50}, {"source": 73, "target": 16}, {"source": 73, "target": 22}, {"source": 73, "target": 60}, {"source": 73, "target": 61}, {"source": 73, "target": 85}, {"source": 73, "target": 20}, {"source": 74, "target": 30}, {"source": 74, "target": 50}, {"source": 74, "target": 80}, {"source": 74, "target": 35}, {"source": 74, "target": 24}, {"source": 74, "target": 14}, {"source": 74, "target": 13}, {"source": 74, "target": 77}, {"source": 74, "target": 5}, {"source": 74, "target": 91}, {"source": 74, "target": 62}, {"source": 74, "target": 64}, {"source": 74, "target": 72}, {"source": 74, "target": 86}, {"source": 74, "target": 103}, {"source": 74, "target": 26}, {"source": 74, "target": 101}, {"source": 74, "target": 31}, {"source": 74, "target": 75}, {"source": 75, "target": 85}, {"source": 76, "target": 90}, {"source": 76, "target": 67}, {"source": 77, "target": 50}, {"source": 77, "target": 76}, {"source": 77, "target": 85}, {"source": 77, "target": 42}, {"source": 80, "target": 50}, {"source": 80, "target": 85}, {"source": 83, "target": 50}, {"source": 84, "target": 96}, {"source": 85, "target": 50}, {"source": 85, "target": 35}, {"source": 85, "target": 21}, {"source": 85, "target": 82}, {"source": 85, "target": 60}, {"source": 85, "target": 83}, {"source": 85, "target": 2}, {"source": 85, "target": 46}, {"source": 85, "target": 84}, {"source": 85, "target": 3}, {"source": 85, "target": 10}, {"source": 86, "target": 13}, {"source": 86, "target": 37}, {"source": 87, "target": 104}, {"source": 88, "target": 85}, {"source": 89, "target": 50}, {"source": 89, "target": 71}, {"source": 90, "target": 50}, {"source": 91, "target": 67}, {"source": 92, "target": 50}, {"source": 92, "target": 85}, {"source": 93, "target": 67}, {"source": 94, "target": 85}, {"source": 94, "target": 52}, {"source": 94, "target": 62}, {"source": 95, "target": 50}, {"source": 95, "target": 85}, {"source": 95, "target": 68}, {"source": 43, "target": 16}, {"source": 43, "target": 22}, {"source": 43, "target": 37}, {"source": 43, "target": 101}, {"source": 43, "target": 85}, {"source": 43, "target": 20}, {"source": 96, "target": 67}, {"source": 97, "target": 104}, {"source": 98, "target": 75}, {"source": 98, "target": 65}, {"source": 98, "target": 26}, {"source": 98, "target": 89}, {"source": 98, "target": 40}, {"source": 99, "target": 50}, {"source": 99, "target": 67}, {"source": 99, "target": 93}, {"source": 99, "target": 72}, {"source": 100, "target": 50}, {"source": 101, "target": 7}, {"source": 103, "target": 30}, {"source": 103, "target": 15}, {"source": 103, "target": 22}, {"source": 103, "target": 52}, {"source": 103, "target": 60}, {"source": 103, "target": 61}, {"source": 103, "target": 100}, {"source": 103, "target": 35}, {"source": 103, "target": 73}, {"source": 103, "target": 20}, {"source": 103, "target": 70}, {"source": 103, "target": 7}], "multigraph": false}')
var cb_hierarchical = document.getElementById("cb_hierarchical");
var cb_curved = document.getElementById("cb_curved");
var chartDiv = document.getElementById("chart");
var svg = d3.select(chartDiv).append("svg");
var linkedByIndex = {};
var num_links = {};
var num_links_incoming = {};
graph.links.forEach(function(d) {
linkedByIndex[d.source + "," + d.target] = 1;
num_links[d.target] = (num_links[d.target] != undefined ? num_links[d.target] + 1 : 1)
num_links[d.source] = (num_links[d.source] != undefined ? num_links[d.source] + 1 : 1)
num_links_incoming[d.target] = (num_links_incoming[d.target] != undefined ? num_links_incoming[d.target] + 1 : 1)
d.distance = graph.nodes[d.target].level - graph.nodes[d.source].level;
});
const maxlevel = graph.nodes.reduce(function(currentValue, node) {
return Math.max(node.level, currentValue);
}, 0);
var maxlinks = Object.values(num_links).reduce(function(currentValue, entry) {
return Math.max(entry, currentValue);
}, 0);
var white_background = svg.append("svg:defs")
.append("filter")
.attr("x", 0)
.attr("y", 0)
.attr("width", 1)
.attr("height", 1)
.attr("id", "white_background");
white_background
.append("feFlood")
.attr("flood-color", "white");
white_background
.append("feComposite")
.attr("in", "SourceGraphic")
var simulation = d3.forceSimulation(graph.nodes)
.on('tick', tick);
// add the links
var path = svg.selectAll("path")
.data(graph.links)
.enter().append("svg:path")
.attr("class", "link");
// define the nodes
var node = svg.selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.on("mouseover", highlight(true))
.on("mouseout", highlight(false))
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
// add the node-circles
var circle = node.append("circle")
.attr("z", 0);
// add the text to nodes
var title = node.append("text")
.attr("x", 12)
.attr("z", 5)
.attr("dy", ".35em")
.attr("filter", "url(#white_background)")
.text(function(d) {
return d.name;
});
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;
}
function tick(e) {
var width = chartDiv.clientWidth;
var height = chartDiv.clientHeight;
node
.attr("cx", function(d) {
return d.x = Math.max(d.radius, Math.min(width - d.radius - 75, d.x));
})
.attr("cy", function(d) {
return d.y = Math.max(d.radius, Math.min(height - d.radius, d.y));
})
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
path.attr("d", function(d) {
if (cb_curved.checked) {
return "M" + d.source.x + "," + d.source.y + "C" + d.target.x + "," + d.source.y + "," + d.source.x + "," + d.target.y + "," + d.target.x + "," + d.target.y;
} else {
return "M" + d.source.x + "," + d.source.y + "L" + d.target.x + "," + d.target.y;
}
});
}
function highlight(active) {
return function(d, i) {
path.classed("ingoing", function(link) {
return active && link.target === d;
});
path.classed("outgoing", function(link) {
return active && link.source === d;
});
node.classed("ingoing", function(node) {
return active && linkedByIndex[node.id + "," + d.id];
});
node.classed("outgoing", function(node) {
return active && linkedByIndex[d.id + "," + node.id];
});
node.classed("selected", function(node) {
return active && d.id === node.id;
});
circle.classed("ingoing", function(node) {
return active && linkedByIndex[node.id + "," + d.id];
});
circle.classed("outgoing", function(node) {
return active && linkedByIndex[d.id + "," + node.id];
});
circle.classed("selected", function(node) {
return active && d.id === node.id;
});
title.classed("ingoing", function(node) {
return active && linkedByIndex[node.id + "," + d.id];
});
title.classed("outgoing", function(node) {
return active && linkedByIndex[d.id + "," + node.id];
});
title.classed("selected", function(node) {
return active && d.id === node.id;
});
};
}
function redraw() {
var width = chartDiv.clientWidth;
var height = chartDiv.clientHeight;
svg.attr("width", width).attr("height", height);
const radius = 25;
const charge = 10;
const link_strength = .75;
graph.nodes.forEach(function(d) {
d.radius = radius * Math.atan((num_links[d.id] != undefined ? num_links[d.id] : 0) / maxlinks * 2 * Math.PI);
});
graph.nodes.forEach(function(d) {
d.radius_inc = radius * Math.atan((num_links_incoming[d.id] != undefined ? num_links_incoming[d.id] : 0) / maxlinks * 2 * Math.PI);
});
circle.attr('r', function(d) {
return d.radius;
});
var leveldist = width / (maxlevel + 1);
if (cb_hierarchical.checked) {
simulation
.force('x', d3.forceX()
.x(function(d) {
return (d.level + 0.5) * leveldist;
})
.strength(2.))
.force('y', d3.forceY()
.y(height / 2)
.strength(0.025));
} else {
simulation
.force('x', d3.forceX()
.x(width / 2)
.strength(0.05))
.force('y', d3.forceY()
.y(height / 2)
.strength(0.05));
}
simulation.force('link', d3.forceLink()
.links(graph.links)
.strength(function(d) {
return link_strength / d.target.radius_inc;
})
.distance(function(d) {
return d.distance * leveldist
}))
.force('charge', d3.forceManyBody()
.strength(function(d) {
return -charge * d.radius;
}))
.force('collision', d3.forceCollide()
.radius(function(d) {
return d.radius;
}))
.alphaTarget(0.3)
.restart();
}
redraw();
d3.select(window).on("resize", redraw)
</script>
</body>
</html>

Using the comments by #Coola, I extended my recent attempts with a Sankey diagram, added padding and zooming capabilities and the possibility to switch between the different visualization modes. Furthermore, I added some link drawing style, to the force simulation approach, that tries to resemble bundling of electrical wires to prevent the mess.
Posting this as an answer instead of editing the original question as the change is rather huge and contains significant progress. Hope, this is OK.
Still, things are a bit messy as you can see. Thus, I would still be happy to see more ideas.
Currently, I do have the feeling that the Hierarchical Edge bundling is best-suited for this problem. To be able to create such a graph, I introduced an artificial hierarchy indirectly via the shortest path between the main project and its dependants.
Hierarchical Edge Bundling
Force Layout
Sankey Diagram
Unfortunately, the full code is too large to be posted.

Use the networkX library, first create a networkX graph and then call the layout function, I used spectral_layout as I feel it is a better way to visualize DAGs. The layout function will return a dictionary of node names with x,y positions. I did this in python, converted the dictionary to json and passed over the json to D3.

Related

Drag and drop object on a SVG element in d3.js

I have an object (the skier on the image) that I want to be able to drag and drop on the line (the slope). My goal is to drag the skier up the slope, calculate the energy the skier has at that point, and when I drop him, he descends down the slope and then I calculate his speed based on the energy he had where he was the dropped.
I have managed to generate the line path but I don't know how I can limit the drag and drop area to to the line path that I have generated. I have tried to find relevant d3.drag() but I cannot find what I am looking. Some ideas how I can accomplish this?
Here is all my code:
const skierIconSvg = "skier.svg";
const margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
const svg = d3.select('body').append('svg')
.attr("width", width)
.attr("height", height)
const data = [
{"x": 1, "y": 100},
{"x": 2, "y": 99},
{"x": 3, "y": 98},
{"x": 4, "y": 97},
{"x": 5, "y": 96},
{"x": 6, "y": 95},
{"x": 7, "y": 94},
{"x": 8, "y": 93},
{"x": 9, "y": 92},
{"x": 10, "y": 91},
{"x": 11, "y": 90},
{"x": 12, "y": 89},
{"x": 13, "y": 88},
{"x": 14, "y": 87},
{"x": 15, "y": 86},
{"x": 16, "y": 85},
{"x": 17, "y": 84},
{"x": 18, "y": 83},
{"x": 19, "y": 82},
{"x": 20, "y": 81},
{"x": 21, "y": 80},
{"x": 22, "y": 79},
{"x": 23, "y": 78},
{"x": 24, "y": 77},
{"x": 25, "y": 76},
{"x": 26, "y": 75},
{"x": 27, "y": 74},
{"x": 28, "y": 73},
{"x": 29, "y": 72},
{"x": 30, "y": 71},
{"x": 31, "y": 70},
{"x": 32, "y": 69},
{"x": 33, "y": 68},
{"x": 34, "y": 67},
{"x": 35, "y": 66},
{"x": 36, "y": 65},
{"x": 37, "y": 64},
{"x": 38, "y": 63},
{"x": 39, "y": 62},
{"x": 40, "y": 61},
{"x": 41, "y": 60},
{"x": 42, "y": 59},
{"x": 43, "y": 58},
{"x": 44, "y": 57},
{"x": 45, "y": 56},
{"x": 46, "y": 55},
{"x": 47, "y": 54},
{"x": 48, "y": 53},
{"x": 49, "y": 52},
{"x": 50, "y": 51},
{"x": 51, "y": 50},
{"x": 52, "y": 49},
{"x": 53, "y": 48},
{"x": 54, "y": 47},
{"x": 55, "y": 46},
{"x": 56, "y": 45},
{"x": 57, "y": 44},
{"x": 58, "y": 43},
{"x": 59, "y": 42},
{"x": 60, "y": 41},
{"x": 61, "y": 40},
{"x": 62, "y": 39},
{"x": 63, "y": 38},
{"x": 64, "y": 37},
{"x": 65, "y": 36},
{"x": 66, "y": 35},
{"x": 67, "y": 34},
{"x": 68, "y": 33},
{"x": 69, "y": 32},
{"x": 70, "y": 31},
{"x": 71, "y": 30},
{"x": 72, "y": 29},
{"x": 73, "y": 28},
{"x": 74, "y": 27},
{"x": 75, "y": 26},
{"x": 76, "y": 25},
{"x": 77, "y": 24},
{"x": 78, "y": 23},
{"x": 79, "y": 22},
{"x": 80, "y": 21},
{"x": 81, "y": 20},
{"x": 82, "y": 19},
{"x": 83, "y": 18},
{"x": 84, "y": 17},
{"x": 85, "y": 16},
{"x": 86, "y": 15},
{"x": 87, "y": 14},
{"x": 88, "y": 13},
{"x": 89, "y": 12},
{"x": 90, "y": 11},
{"x": 91, "y": 10},
{"x": 92, "y": 9},
{"x": 93, "y": 8},
{"x": 94, "y": 7},
{"x": 95, "y": 6},
{"x": 96, "y": 5},
{"x": 97, "y": 4},
{"x": 98, "y": 3},
{"x": 99, "y": 2},
{"x": 100, "y": 1},
];
const xScale = d3.scaleLinear()
.domain([d3.min(data, function(d) { return d.x; }), d3.max(data, function(d) { return d.x; }) ])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return d.y; }) ])
.range([height, 0]);
const linje = d3.line()
.x(d => xScale(d.x))
.y(d => yScale(d.y))
const gLinje = svg.append("g")
const loypegenerator = gLinje.append("path")
.attr("d", linje(data))
.attr("stroke", "blue")
.attr("stroke-width", 1)
.attr("class", "loypeprofil")
.attr("fill", "none")
const newG = svg.append("g")
const nyLoypegenerator = newG.append("path")
.attr("d", linje(data))
.attr("stroke", "none")
.attr("stroke-width", 1)
.attr("class", "loypeprofil")
.attr("fill", "none")
// This finds the x coordinate on the G element using d3.mouse
nyLoypegenerator.append("rect")
.attr("height", height)
.attr("width", width)
.attr("fill", "none")
.attr("pointer-events", "all")
.on("mousemove", () => {
const x = d3.mouse(g.node())[1];
const hoveredX = yScale.invert(x)
console.log(hoveredX)
});
// Here I append the skier object
const skier = newG.append("image")
.attr("id", "skier")
.attr("href", skierIconSvg)
.attr("x", 130)
.attr("y", 150)
.attr("width", 100)
.attr("height", 100)
.call(d3
.drag()
.on('start', start)
.on('drag', dragged));
function start() {
let current = d3.select(this)
deltaX = current.attr("x") - d3.event.x;
deltaY = current.attr("y") - d3.event.y;
};
function dragged() {
d3.select(this)
.attr("x", d3.mouse(newG.node())[0])
.attr("y", d3.mouse(newG.node())[1])
};

Vega-lite heatmap add text to a variable

"data": {
"values": [
{"x": 0, "y": 0, "z": 0},
{"x": 1, "y": 0, "z": 1},
{"x": 2, "y": 0, "z": 5},
{"x": 2, "y": 0, "z": 10},
{"x": 4, "y": 0, "z": 16},
{"x": 0, "y": 1, "z": 1},
{"x": 1, "y": 1, "z": 2},
{"x": 2, "y": 1, "z": 5},
{"x": 3, "y": 1, "z": 10},
{"x": 5, "y": 1, "z": 26}
]},
How to add text to a variable, so like "AVG:"?
Vega Editor
You can use a calculate transform to create specifically-formatted text to display in a text mark. For example (vega editor):
{
"data": {
"values": [
{"x": 0, "y": 0, "z": 0},
{"x": 1, "y": 0, "z": 1},
{"x": 2, "y": 0, "z": 5},
{"x": 2, "y": 0, "z": 10},
{"x": 4, "y": 0, "z": 16},
{"x": 0, "y": 1, "z": 1},
{"x": 1, "y": 1, "z": 2},
{"x": 2, "y": 1, "z": 5},
{"x": 3, "y": 1, "z": 10},
{"x": 5, "y": 1, "z": 26}
]
},
"transform": [
{
"aggregate": [{"op": "mean", "field": "z", "as": "z"}],
"groupby": ["x", "y"]
},
{"calculate": "'avg: ' + datum.z", "as": "z"}
],
"mark": "text",
"encoding": {
"x": {"field": "x", "type": "ordinal"},
"y": {"field": "y", "type": "ordinal"},
"text": {"field": "z", "type": "nominal"}
},
"width": 300,
"height": 100
}

MongoDB Too slow at find by id query, for just 100000 items?

I have a collection with 100000(999996) documents and I'm using Laravel for integration,
When I want to find a document by its id, it take too long to respond. (something like >80ms)
I'm wondering why it must take too long for just 100k items?
and _id field is indexed.
what configurations I should set for better performance.
be aware I have some embeds in my document that embedded by Laravel model.
example of one of the documents:
{
"_id": ObjectId("5d88a2857c254f0256737f43"),
"name": "blcy",
"coach": null,
"line_up": 1,
"sponsor_id": "5d131dd37c254f1d007d01f0",
"last_online": ISODate("2019-09-23T10:46:29.000Z"),
"stadium": 1,
"active_stadium": 1,
"doctor": 1,
"active_doctor": 1,
"trainer": 1,
"coach_assistant": 1,
"active_coach_assistant": 1,
"fitness_coach": 1,
"active_fitness_coach": 1,
"leader": 1,
"active_leader": 1,
"executive_manager": 1,
"active_executive_manager": 1,
"strategy": 1,
"attack_tactic": 1,
"defence_tactic": 1,
"ticket_price": 5,
"user_id": "5d88a2847c254f0256737f42",
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"kit": {
"bg_color": 10,
"fg_color": 20,
"fg": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f44")
},
"logo": {
"bg_color": 10,
"fg_color": 20,
"fg": 1,
"bg": 11,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f45")
},
"players": [
{
"name": "بردیا رادمان",
"player_number": 7,
"age": 22,
"post": "G",
"talent": 2,
"shoot": 6,
"pass": 2,
"speed": 5,
"strength": 5,
"readiness": 100,
"technique": 6,
"head": 6,
"real_power": 83,
"power": 30,
"level": 2,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f46"),
"in_lineup": true,
"position": "G"
},
{
"name": "سعید قاضی",
"player_number": 1,
"age": 19,
"post": "G",
"talent": 5,
"shoot": 2,
"pass": 2,
"speed": 6,
"strength": 5,
"readiness": 100,
"technique": 6,
"head": 2,
"real_power": 69,
"power": 23,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f47")
},
{
"name": "علیرضا چلبی",
"player_number": 47,
"age": 19,
"post": "G",
"talent": 4,
"shoot": 4,
"pass": 3,
"speed": 4,
"strength": 3,
"readiness": 100,
"technique": 4,
"head": 3,
"real_power": 60,
"power": 21,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f48")
},
{
"name": "آذین اوستا",
"player_number": 52,
"age": 25,
"post": "G",
"talent": 4,
"shoot": 5,
"pass": 6,
"speed": 2,
"strength": 6,
"readiness": 100,
"technique": 2,
"head": 4,
"real_power": 91,
"power": 25,
"level": 2,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f49")
},
{
"name": "یاسین صفوی",
"player_number": 28,
"age": 20,
"post": "D",
"talent": 4,
"shoot": 5,
"pass": 4,
"speed": 3,
"strength": 4,
"readiness": 100,
"technique": 3,
"head": 4,
"real_power": 68,
"power": 23,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f4a"),
"in_lineup": true,
"position": "D"
},
{
"name": "خشایار نوبخت",
"player_number": 36,
"age": 17,
"post": "D",
"talent": 2,
"shoot": 6,
"pass": 5,
"speed": 3,
"strength": 5,
"readiness": 100,
"technique": 3,
"head": 3,
"real_power": 75,
"power": 25,
"level": 2,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f4b"),
"in_lineup": true,
"position": "D"
},
{
"name": "شجاع سحاب",
"player_number": 18,
"age": 23,
"post": "D",
"talent": 3,
"shoot": 4,
"pass": 2,
"speed": 2,
"strength": 3,
"readiness": 100,
"technique": 5,
"head": 4,
"real_power": 53,
"power": 20,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f4c"),
"in_lineup": true,
"position": "D"
},
{
"name": "رها فهمیده",
"player_number": 10,
"age": 26,
"post": "D",
"talent": 3,
"shoot": 5,
"pass": 5,
"speed": 3,
"strength": 5,
"readiness": 100,
"technique": 5,
"head": 3,
"real_power": 76,
"power": 26,
"level": 2,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f4d"),
"in_lineup": true,
"position": "D"
},
{
"name": "آذین عبدالکریمی",
"player_number": 32,
"age": 18,
"post": "D",
"talent": 2,
"shoot": 6,
"pass": 4,
"speed": 2,
"strength": 2,
"readiness": 100,
"technique": 6,
"head": 5,
"real_power": 59,
"power": 25,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f4e"),
"in_lineup": true,
"position": "D"
},
{
"name": "محمدرضا طالقانی",
"player_number": 22,
"age": 26,
"post": "D",
"talent": 5,
"shoot": 3,
"pass": 3,
"speed": 3,
"strength": 4,
"readiness": 100,
"technique": 6,
"head": 2,
"real_power": 60,
"power": 21,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f4f")
},
{
"name": "پارسا دستغیب",
"player_number": 9,
"age": 19,
"post": "D",
"talent": 1,
"shoot": 6,
"pass": 2,
"speed": 4,
"strength": 3,
"readiness": 100,
"technique": 6,
"head": 2,
"real_power": 58,
"power": 23,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f50")
},
{
"name": "فرشید پناهیان",
"player_number": 33,
"age": 26,
"post": "M",
"talent": 2,
"shoot": 2,
"pass": 6,
"speed": 2,
"strength": 4,
"readiness": 100,
"technique": 3,
"head": 6,
"real_power": 72,
"power": 23,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f51"),
"in_lineup": true,
"position": "M"
},
{
"name": "سپهر واعظ",
"player_number": 8,
"age": 26,
"post": "M",
"talent": 4,
"shoot": 4,
"pass": 3,
"speed": 3,
"strength": 2,
"readiness": 100,
"technique": 6,
"head": 6,
"real_power": 72,
"power": 24,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f52"),
"in_lineup": true,
"position": "M"
},
{
"name": "امیررضا کوشکی",
"player_number": 3,
"age": 26,
"post": "M",
"talent": 5,
"shoot": 4,
"pass": 2,
"speed": 6,
"strength": 3,
"readiness": 100,
"technique": 3,
"head": 4,
"real_power": 62,
"power": 22,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f53"),
"in_lineup": true,
"position": "M"
},
{
"name": "پدرام جنتی",
"player_number": 29,
"age": 24,
"post": "M",
"talent": 3,
"shoot": 2,
"pass": 4,
"speed": 5,
"strength": 4,
"readiness": 100,
"technique": 2,
"head": 4,
"real_power": 63,
"power": 21,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f54")
},
{
"name": "محمد علی‌آبادی",
"player_number": 13,
"age": 17,
"post": "M",
"talent": 1,
"shoot": 2,
"pass": 5,
"speed": 3,
"strength": 3,
"readiness": 100,
"technique": 4,
"head": 4,
"real_power": 68,
"power": 21,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f55")
},
{
"name": "سهیل فانی",
"player_number": 19,
"age": 25,
"post": "M",
"talent": 1,
"shoot": 2,
"pass": 3,
"speed": 4,
"strength": 4,
"readiness": 100,
"technique": 4,
"head": 5,
"real_power": 65,
"power": 22,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f56")
},
{
"name": "شهرام گنجی",
"player_number": 24,
"age": 17,
"post": "S",
"talent": 4,
"shoot": 6,
"pass": 3,
"speed": 6,
"strength": 2,
"readiness": 100,
"technique": 2,
"head": 2,
"real_power": 69,
"power": 21,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f57"),
"in_lineup": true,
"position": "S"
},
{
"name": "امیرمحمد سرافراز",
"player_number": 2,
"age": 21,
"post": "S",
"talent": 4,
"shoot": 6,
"pass": 2,
"speed": 5,
"strength": 4,
"readiness": 100,
"technique": 5,
"head": 5,
"real_power": 90,
"power": 27,
"level": 2,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f58"),
"in_lineup": true,
"position": "S"
},
{
"name": "فربد ارسباران",
"player_number": 20,
"age": 25,
"post": "S",
"talent": 2,
"shoot": 2,
"pass": 2,
"speed": 5,
"strength": 3,
"readiness": 100,
"technique": 4,
"head": 4,
"real_power": 65,
"power": 20,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f59")
},
{
"name": "فرشید الهام",
"player_number": 21,
"age": 24,
"post": "S",
"talent": 2,
"shoot": 4,
"pass": 3,
"speed": 6,
"strength": 2,
"readiness": 100,
"technique": 3,
"head": 6,
"real_power": 78,
"power": 24,
"level": 2,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f5a")
},
{
"name": "ساسان طریقت",
"player_number": 35,
"age": 17,
"post": "S",
"talent": 5,
"shoot": 2,
"pass": 5,
"speed": 4,
"strength": 2,
"readiness": 100,
"technique": 5,
"head": 6,
"real_power": 74,
"power": 24,
"level": 1,
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f5b")
}
],
"league_id": "5d88a2857c254f0256737f5d",
"league_name": "league-0-1",
"transactions": [
{
"amount": 120000,
"type": "coin",
"cash": 0,
"coin": 120000,
"description": "1",
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f5e")
},
{
"amount": 100,
"type": "cash",
"cash": 100,
"coin": 120000,
"description": "1",
"updated_at": ISODate("2019-09-23T10:46:29.000Z"),
"created_at": ISODate("2019-09-23T10:46:29.000Z"),
"_id": ObjectId("5d88a2857c254f0256737f5f")
}
],
"cash": 100,
"coin": 120000,
"fixtures": [
{
"league_name": "league-0-1",
"home_id": "5d88a2857c254f025673800f",
"guest_id": "5d88a2857c254f0256737f43",
"week_day": 1,
"weather_type": "sunny",
"home_goal": 0,
"guest_goal": 0,
"friendly": false,
"fixture_id": "5d89dff87c254f36ee3ae9ab",
"updated_at": ISODate("2019-09-24T09:20:56.000Z"),
"created_at": ISODate("2019-09-24T09:20:56.000Z"),
"_id": ObjectId("5d89dff87c254f36ee3ae9ad")
},
{
"league_name": "league-0-1",
"home_id": "5d88a2857c254f0256737f61",
"guest_id": "5d88a2857c254f0256737f43",
"week_day": 2,
"weather_type": "rainy",
"home_goal": 0,
"guest_goal": 0,
"friendly": false,
"fixture_id": "5d89dff87c254f36ee3ae9c0",
"updated_at": ISODate("2019-09-24T09:20:56.000Z"),
"created_at": ISODate("2019-09-24T09:20:56.000Z"),
"_id": ObjectId("5d89dff87c254f36ee3ae9c2")
},
{
"league_name": "league-0-1",
"home_id": "5d88a2857c254f0256737f43",
"guest_id": "5d88a2857c254f0256737f7e",
"week_day": 3,
"weather_type": "sunny",
"home_goal": 0,
"guest_goal": 0,
"friendly": false,
"fixture_id": "5d89dff87c254f36ee3ae9c6",
"updated_at": ISODate("2019-09-24T09:20:56.000Z"),
"created_at": ISODate("2019-09-24T09:20:56.000Z"),
"_id": ObjectId("5d89dff87c254f36ee3ae9c7")
},
{
"league_name": "league-0-1",
"home_id": "5d88a2857c254f0256737f9b",
"guest_id": "5d88a2857c254f0256737f43",
"week_day": 4,
"weather_type": "sunny",
"home_goal": 0,
"guest_goal": 0,
"friendly": false,
"fixture_id": "5d89dff87c254f36ee3ae9d5",
"updated_at": ISODate("2019-09-24T09:20:56.000Z"),
"created_at": ISODate("2019-09-24T09:20:56.000Z"),
"_id": ObjectId("5d89dff87c254f36ee3ae9d7")
},
{
"league_name": "league-0-1",
"home_id": "5d88a2857c254f0256737f43",
"guest_id": "5d88a2857c254f0256737fb8",
"week_day": 5,
"weather_type": "rainy",
"home_goal": null,
"guest_goal": null,
"friendly": false,
"fixture_id": "5d89dff87c254f36ee3ae9e1",
"updated_at": ISODate("2019-09-24T09:20:57.000Z"),
"created_at": ISODate("2019-09-24T09:20:57.000Z"),
"_id": ObjectId("5d89dff97c254f36ee3ae9e2")
},
{
"league_name": "league-0-1",
"home_id": "5d88a2857c254f0256737fd5",
"guest_id": "5d88a2857c254f0256737f43",
"week_day": 6,
"weather_type": "sunny",
"home_goal": null,
"guest_goal": null,
"friendly": false,
"fixture_id": "5d89dff97c254f36ee3ae9ea",
"updated_at": ISODate("2019-09-24T09:20:57.000Z"),
"created_at": ISODate("2019-09-24T09:20:57.000Z"),
"_id": ObjectId("5d89dff97c254f36ee3ae9ec")
},
{
"league_name": "league-0-1",
"home_id": "5d88a2857c254f0256737f43",
"guest_id": "5d88a2857c254f0256737ff2",
"week_day": 7,
"weather_type": "sunny",
"home_goal": null,
"guest_goal": null,
"friendly": false,
"fixture_id": "5d89dff97c254f36ee3ae9fc",
"updated_at": ISODate("2019-09-24T09:20:57.000Z"),
"created_at": ISODate("2019-09-24T09:20:57.000Z"),
"_id": ObjectId("5d89dff97c254f36ee3ae9fd")
}
]
}
Finding a team like this:
$team = Team::find($team['team_id']);
EDITED:
chunk methods and also cant help me cause i just want to find one document not getting all documents in one row.
Thanks.

Label only 10 N in D3 graph nodes

I have a force-directed graph in D3.js similar to this example.
With the data source for nodes having an additional key:value called connect. I only want to display node labels that have the top 10 count by the connect value. How should I go about it?
Thank you!
The associated sample data source this as below.
{
"nodes": [
{"name": "Myriel", "company": 1, "connect":10},
{"name": "Napoleon", "company": 1, "connect":1},
{"name": "Mlle.Baptistine", "company": 1, "connect":3},
{"name": "Mme.Magloire", "company": 1, "connect":3},
{"name": "CountessdeLo", "company": 1, "connect":1},
{"name": "Geborand", "company": 1, "connect":1},
{"name": "Champtercier", "company": 1, "connect":1},
{"name": "Cravatte", "company": 1, "connect":1},
{"name": "Count", "company": 1, "connect":1},
{"name": "OldMan", "company": 1, "connect":1},
{"name": "Labarre", "company": 2, "connect":1},
{"name": "Valjean", "company": 2, "connect":1},
{"name": "Marguerite", "company": 3, "connect":3},
{"name": "Mme.deR", "company": 2, "connect":1},
{"name": "Isabeau", "company": 2, "connect":1},
{"name": "Gervais", "company": 2, "connect":1},
{"name": "Tholomyes", "company": 3, "connect":1},
{"name": "Listolier", "company": 3, "connect":1},
{"name": "Fameuil", "company": 3, "connect":1},
{"name": "Blacheville", "company": 3, "connect":1},
{"name": "Favourite", "company": 3, "connect":1},
{"name": "Dahlia", "company": 3, "connect":1},
{"name": "Zephine", "company": 3, "connect":1},
{"name": "Fantine", "company": 3, "connect":1},
{"name": "Mme.Thenardier", "company": 4, "connect":1},
{"name": "Thenardier", "company": 4, "connect":1},
{"name": "Cosette", "company": 5, "connect":1},
{"name": "Javert", "company": 4, "connect":1},
{"name": "Fauchelevent", "company": 0, "connect":1},
{"name": "Bamatabois", "company": 2, "connect":1},
{"name": "Perpetue", "company": 3, "connect":1},
{"name": "Simplice", "company": 2, "connect":1},
{"name": "Scaufflaire", "company": 2, "connect":1},
{"name": "Woman1", "company": 2, "connect":1},
{"name": "Judge", "company": 2, "connect":1},
{"name": "Champmathieu", "company": 2, "connect":1},
{"name": "Brevet", "company": 2, "connect":1},
{"name": "Chenildieu", "company": 2, "connect":1},
{"name": "Cochepaille", "company": 2, "connect":1},
{"name": "Pontmercy", "company": 4, "connect":1},
{"name": "Boulatruelle", "company": 6, "connect":1},
{"name": "Eponine", "company": 4, "connect":1},
{"name": "Anzelma", "company": 4, "connect":1},
{"name": "Woman2", "company": 5, "connect":1},
{"name": "MotherInnocent", "company": 0, "connect":1},
{"name": "Gribier", "company": 0, "connect":1},
{"name": "Jondrette", "company": 7, "connect":1},
{"name": "Mme.Burgon", "company": 7, "connect":1},
{"name": "Gavroche", "company": 8, "connect":1},
{"name": "Gillenormand", "company": 5, "connect":1},
{"name": "Magnon", "company": 5, "connect":1},
{"name": "Mlle.Gillenormand", "company": 5, "connect":5},
{"name": "Mme.Pontmercy", "company": 5, "connect":1},
{"name": "Mlle.Vaubois", "company": 5, "connect":1},
{"name": "Lt.Gillenormand", "company": 5, "connect":1},
{"name": "Marius", "company": 8, "connect":1},
{"name": "BaronessT", "company": 5, "connect":1},
{"name": "Mabeuf", "company": 8, "connect":1},
{"name": "Enjolras", "company": 8, "connect":1},
{"name": "Combeferre", "company": 8, "connect":1},
{"name": "Prouvaire", "company": 8, "connect":1},
{"name": "Feuilly", "company": 8, "connect":1},
{"name": "Courfeyrac", "company": 8, "connect":1},
{"name": "Bahorel", "company": 8, "connect":1},
{"name": "Bossuet", "company": 8, "connect":1},
{"name": "Joly", "company": 8, "connect":1},
{"name": "Grantaire", "company": 8, "connect":1},
{"name": "MotherPlutarch", "company": 9, "connect":1},
{"name": "Gueulemer", "company": 4, "connect":1},
{"name": "Babet", "company": 4, "connect":1},
{"name": "Claquesous", "company": 4, "connect":1},
{"name": "Montparnasse", "company": 4, "connect":1},
{"name": "Toussaint", "company": 5, "connect":1},
{"name": "Child1", "company": 10, "connect":1},
{"name": "Child2", "company": 10, "connect":1},
{"name": "Brujon", "company": 4, "connect":1},
{"name": "Mme.Hucheloup", "company": 8, "connect":1}
],
"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}
]
}
Here is a modified version of Mike Bostock's example which only displays labels of top 10 nodes:
var width = 960,
height = 500
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.gravity(0.05)
.distance(100)
.charge(-100)
.size([width, height]);
var json = {"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}]};
// Let's add a random "connect" value to nodes:
json.nodes = json.nodes
.map(n => { n.connect = Math.floor(Math.random() * 100) + 1; return n; })
// Let's get a list of the top 10 nodes based on the value of "connect":
// By the way, the sort would modify the nodes order of the json (which is
// important to draw the force layout) and thus we create a deep copy of the
// nodes to sort them:
var top10nodes = JSON.parse(JSON.stringify(json.nodes))
.sort( function(a, b) { return b.connect - a.connect; })
.slice(0, 9)
.map(n => n.name);
// And we include a "top10" boolean on each node to able to later filter them
// when drawing the label:
json.nodes = json.nodes.map( function(d) {
if (top10nodes.indexOf(d.name) > -1) d.top10 = true;
return d;
});
force
.nodes(json.nodes)
.links(json.links)
.start();
var link = svg.selectAll(".link")
.data(json.links)
.enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(json.nodes)
.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
node.filter( function(d) { return d.top10; }).append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name });
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
});
.link {
stroke: #ccc;
}
.node text {
pointer-events: none;
font: 10px sans-serif;
}
<script src="//d3js.org/d3.v3.min.js"></script>
The idea is to include a top10 field on each node representing the fact that the connect field of the element has its value in the top 10 biggest:
var json = {"nodes":[{"name":"Myriel","group":1},{"name":"Napoleon","group":1}, ...
// Let's add a random "connect" value to nodes to simulate your dataset:
// {nodes: [{name: "Myriel", group: 1, connect: 66}, ... :
json.nodes = json.nodes
.map(n => { n.connect = Math.floor(Math.random() * 100) + 1; return n; })
// Let's get a list of the top 10 nodes based on the value of "connect":
// By the way, the sort would modify the nodes order of the json (which is
// important to draw the force layout) and thus we create a deep copy of the
// nodes to sort them:
// ["MotherPlutarch", "Simplice", "Fantine", "Gueulemer", "CountessdeLo", "Count", "Perpetue", "Champtercier", "Mme.Pontmercy"]
var top10nodes = JSON.parse(JSON.stringify(json.nodes))
.sort( function(a, b) { return b.connect - a.connect; })
.slice(0, 9)
.map(n => n.name);
// And we include a "top10" boolean on each node to able to later filter them
// when drawing the label:
json.nodes = json.nodes.map( function(d) {
if (top10nodes.indexOf(d.name) > -1) d.top10 = true;
return d;
});
This way the in the definition of labels, we can filter only nodes for which this top10 field is true:
node.filter( function(d) { return d.top10; }).append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name });

Forced directed D3 Graph setting specific image for each node

Hi I have gone through few questions and possible solutions of putting image as node in forced directed. But all of them are either putting randomly or one image for all. Is there any way i can assign particular image to particular node? Basically i am creating dynamically and fetching data from database. Any help would be highly appreciated.
hi just click the load button and heres the sample of what you want http://jsfiddle.net/elviz/V6Qr8/91/
function loadImage() {
if (LoadData) {
root = {
"name": "physics",
"imageURL": "",
"type": "user",
"children": [{
"name": "DragForce",
"imageURL": "",
"size": 1082,
"type": "user"
}, {
"name": "GravityForce",
"imageURL": "",
"size": 1336,
"type": "user"
}, {
"name": "IForce",
"imageURL": "",
"size": 319,
"type": "user"
}, {
"name": "NBodyForce",
"imageURL": "",
"size": 10498,
"type": "user"
}, {
"name": "Node 1",
"imageURL": "",
"type": "user",
"children": [{
"name": "DragForce 1.1",
"imageURL": "",
"size": 1082,
"type": "chat"
}, {
"name": "DragForce 1.2",
"imageURL": "",
"size": 1082,
"type": "message"
}]
},
{
"name": "Particle",
"imageURL": "",
"size": 2822,
"type": "user"
}, {
"name": "Simulation",
"imageURL": "",
"size": 9983,
"type": "user"
}, {
"name": "Node 2",
"imageURL": "",
"type": "user",
"children": [{
"name": "DragForce 2.1",
"imageURL": "",
"size": 1082,
"type": "message"
}, {
"name": "DragForce 2.2",
"imageURL": "",
"size": 1082,
"type": "message"
}]
},
{
"name": "Spring",
"imageURL": "",
"size": 2213,
"type": "user"
}, {
"name": "SpringForce",
"imageURL": "",
"size": 1681,
"type": "user"
}, {
"name": "Node 3",
"imageURL": "",
"type": "user",
"children": [{
"name": "DragForce 2.1",
"imageURL": "",
"size": 1082,
"type": "chat"
}, {
"name": "DragForce 3.2",
"imageURL": "",
"size": 1082,
"type": "chat"
}]
}]
};
Try as shown in fiddle:
http://jsfiddle.net/cyril123/n28k7oqo/3/
You can specify your data as and pass the image as shown below
var graph = {
"nodes": [
{"x": 469, "y": 410, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 493, "y": 364, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-09-128.png"},
{"x": 442, "y": 365, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-17-128.png"},
{"x": 467, "y": 314, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-22-128.png"},
{"x": 477, "y": 248, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-13-128.png"},
{"x": 425, "y": 207, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 402, "y": 155, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-03-128.png"},
{"x": 369, "y": 196, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 350, "y": 148, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 539, "y": 222, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 594, "y": 235, 'img': "https://cdn0.iconfinder.com/data/icons/ikooni-outline-free-basic/128/free-23-128.png"},
{"x": 582, "y": 185, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"},
{"x": 633, "y": 200, 'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"}
],
"links": [
{"source": 0, "target": 1},
{"source": 1, "target": 2},
{"source": 2, "target": 0},
{"source": 1, "target": 3},
{"source": 3, "target": 2},
{"source": 3, "target": 4},
{"source": 4, "target": 5},
{"source": 5, "target": 6},
{"source": 5, "target": 7},
{"source": 6, "target": 7},
{"source": 6, "target": 8},
{"source": 7, "target": 8},
{"source": 9, "target": 4},
{"source": 9, "target": 11},
{"source": 9, "target": 10},
{"source": 10, "target": 11},
{"source": 11, "target": 12},
{"source": 12, "target": 10}
]
}
Explanation
The x and y in the json is the probable place where you want to place the circle. Imagine you don't have x and y for any of the nodes; in such case don't pass the x and y in JSON. Something like this:
..."nodes": [
{
'img': "https://cdn1.iconfinder.com/data/icons/industry-2/96/Mine-512.png"
}, ....
Regarding the img pass the url of the image you wish to see on the node.
Like I have done above.
This will append the image to the node group:
//make groups which will hold the image and the circle
nodes = node.data(graph.nodes)
.enter().append("g");
//make a node circle in the group
var circles = nodes.append("circle")
.attr("class", "node")
.attr("r", 12)
.on("dblclick", dblclick)
.call(drag);
//make images in the group
var images = nodes.append("svg:image")
.attr("xlink:href",function(d) {return d.img})
.attr("height", "20")
.attr("width", "20");
The node group is the group which contains the circle and the image.
Like in my Arda family tree I load the images locally by the name of the person. So every person has it's own picture.
Also make sure that you have the onerror in HTML used to show a default image when the wanted image is deleted or something else. Otherwhise the Google Chrome shows an ugly red cross. Just as a tip =)
If you have any further question, just ask.

Resources