score:1
Accepted answer
I'm hesitant to answer this question because you haven't asked anything concrete. But here's a quick refactor of the linked code that reads the data externally from a JSON API. I really don't see anything in the code that makes the data anything different then a conventional force layout. Something like this:
{
"nodes": [{
"x": 100,
"y": 100,
"group": 0.5
},{
"x": 200,
"y": 200,
"group": 0.2
},{
"x": 300,
"y": 300,
"group": 0.6
},{
"x": 400,
"y": 400,
"group": 0.1
},{
"x": 500,
"y": 500,
"group": 0.7
}],
"links": [{
"source": 0,
"target": 1
},{
"source": 1,
"target": 2
},{
"source": 2,
"target": 3
},{
"source": 3,
"target": 4
}]
}
The other changes are just to fix variable scoping since node
and link
are created in the d3.json
callback:
<!DOCTYPE html>
<html>
<head>
<title>Spherical Force-Directed Layout</title>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>
<!--<script src="/js/d3.v3.min.js"></script>-->
<!--<script src="/js/dat-gui/build/dat.gui.js"></script> -->
<style type="text/css">
body {
padding: 0;
margin: 0;
}
path.node {
stroke-width: 1.5px;
}
path.link {
stroke: #999;
fill-opacity: 0
}
</style>
</head>
<body>
<script type="text/javascript">
var projections = {
"Albers": d3.geo.albers(),
"Azimuthal Equal Area": d3.geo.azimuthalEqualArea(),
"Azimuthal Eqidistant": d3.geo.azimuthalEquidistant(),
"Conic Conformal": d3.geo.conicConformal(),
"Conic Equal Area": d3.geo.conicEqualArea(),
"Conic Equidistant": d3.geo.conicEquidistant(),
"Eqirectangular": d3.geo.equirectangular(),
"Gnomonic": d3.geo.gnomonic(),
"Mercator": d3.geo.mercator(),
"Orthographic": d3.geo.orthographic(),
"Stereographic": d3.geo.stereographic(),
"Transverse Mercator": d3.geo.transverseMercator(),
};
var config = {
"projection": "Orthographic",
"clip": true,
"friction": .9,
"linkStrength": 1,
"linkDistance": 20,
"charge": 30,
"gravity": .1,
"theta": .8
};
var gui = new dat.GUI();
//var projectionChanger = gui.add(config, "projection", ['equalarea', 'equidistant', 'gnomonic', 'orthographic', 'stereographic', 'rectangular']);
var projectionChanger = gui.add(config, "projection", Object.keys(projections));
//http://stackoverflow.com/a/3417242
function wrapIndex(i, i_max) {
return ((i % i_max) + i_max) % i_max;
}
projectionChanger.onChange(function(value) {
projection = projections[value]
.scale(height / 2)
.translate([(width / 2) - 125, height / 2])
.clipAngle(config["clip"] ? 90 : null)
path.projection(projections[value])
return
if (value == 'rectangular') {
path = d3.geo.path().projection(function(coordinates) {
console.log(coordinates[0], coordinates[1])
return [
wrapIndex(coordinates[0], width),
wrapIndex(coordinates[1], height),
];
});
config['clip'] = false
} else {
projection.mode(value)
path = d3.geo.path().projection(projection)
}
force.start()
});
var clipChanger = gui.add(config, "clip").listen();
clipChanger.onChange(function(value) {
projection.clipAngle(value ? 90 : null)
force.start()
});
var fl = gui.addFolder('Force Layout');
fl.open()
var frictionChanger = fl.add(config, "friction", 0, 1);
frictionChanger.onChange(function(value) {
force.friction(value)
force.start()
});
var linkDistanceChanger = fl.add(config, "linkDistance", 0, 400);
linkDistanceChanger.onChange(function(value) {
force.linkDistance(value)
force.start()
});
var linkStrengthChanger = fl.add(config, "linkStrength", 0, 1);
linkStrengthChanger.onChange(function(value) {
force.linkStrength(value)
force.start()
});
var chargeChanger = fl.add(config, "charge", 0, 500);
chargeChanger.onChange(function(value) {
force.charge(-value)
force.start()
});
var gravityChanger = fl.add(config, "gravity", 0, 1);
gravityChanger.onChange(function(value) {
force.gravity(value)
force.start()
});
var thetaChanger = fl.add(config, "theta", 0, 1);
thetaChanger.onChange(function(value) {
force.theta(value)
force.start()
});
var width = window.innerWidth,
height = window.innerHeight - 5,
fill = d3.scale.category20(),
nodes = [{
x: width / 2,
y: height / 2
}],
links = [];
var projection = projections[config["projection"]]
.scale(height / 2)
.translate([(width / 2) - 125, height / 2])
.clipAngle(config["clip"] ? 90 : null)
var path = d3.geo.path()
.projection(projection)
var force = d3.layout.force()
.linkDistance(config["linkDistance"])
.linkStrength(config["linkStrength"])
.gravity(config["gravity"])
.size([width, height])
.charge(-config["charge"]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.drag()
.origin(function() {
var r = projection.rotate();
return {
x: 2 * r[0],
y: -2 * r[1]
};
})
.on("drag", function() {
force.start();
var r = [d3.event.x / 2, -d3.event.y / 2, projection.rotate()[2]];
t0 = Date.now();
origin = r;
projection.rotate(r);
}))
var node, link;
d3.json('https://jsonblob.com/api/547d877a-0e4e-11e7-a0ba-f11a5a82ba29', function(e, data) {
if (e) console.warn(e);
link = svg.selectAll("path.link")
.data(data.links)
.enter().append("path").attr("class", "link")
node = svg.selectAll("path.node")
.data(data.nodes)
.enter().append("path").attr("class", "node")
.style("fill", function(d) {
return fill(d.group);
})
.style("stroke", function(d) {
return d3.rgb(fill(d.group)).darker();
})
.call(force.drag);
force
.nodes(data.nodes)
.links(data.links)
.on("tick", tick)
.start();
});
function tick() {
node.attr("d", function(d) {
var p = path({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [d.x, d.y]
}
});
return p ? p : 'M 0 0'
});
link.attr("d", function(d) {
var p = path({
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates": [
[d.source.x, d.source.y],
[d.target.x, d.target.y]
]
}
});
return p ? p : 'M 0 0'
});
}
</script>
</body>
</html>
Source: stackoverflow.com
Related Query
- Changing the data used by a d3 force layout
- Change the data used in a force layout
- How to update elements of D3 force layout when the underlying data changes
- How to make in d3 force layout the gravity data dependant
- d3 force directed layout - drawing links without changing the location of the nodes
- How to change the data in a force layout graph dynamically ? D3
- Changing the positions of force layout d3 dynamically
- Display an arrow head in the middle of D3 force layout link
- D3 force layout fix root node at the center
- How to speed up the force layout animation in d3.js
- how find out if force layout done placing the nodes?
- How to increase the length of a link in D3 force layout
- how to control the simulation speed of d3 force layout
- Updating the data of a pack layout from JSON call and redrawing
- Multiple instances of d3 force layout on the same page
- SVG markers don't orient properly on a d3.svg.diagonal curve used as a D3 force layout link
- D3: How to dynamically refresh a graph by changing the data file source?
- How to get the same node positions in d3's force layout graph
- How to append the arrow marker dynamically in force layout d3.js
- Log the x,y coordinates of nodes in a converged D3 force layout
- Changing nodes for images in d3.js force layout graph
- How to show the tooltip on d3 force directed layout node?
- Updating data values with HTML input and changing the data array
- how to visualize data from mysql database in force layout of d3 tool
- Changing color range in a d3 reusable donut chart depending on the number of data points
- Force Layout - Labelling and pinning down the nodes
- How to achieve "flying Arcs" as link in the force layout of D3.js
- Connected link line animation when mouse over on the node in force layout d3
- d3.js force layout graph : how to build the nodes object from scratch?
- Using data(...) in D3 force layout to update the graph
More Query from same tag
- How can I add d3 zoom and pan to a Power BI visual?
- D3 Pack Layout symmetry got changed in version greater than v4.5
- Access the text within SVG object using d3js
- Changing number displayed as svg text gradually, with D3 transition
- manipulating nvd3 chart attributes
- How do I plot points on a map using D3.js?
- How to add to text to the Zoomable Icicle d3 graph?
- return tabulate data from brush selection with d3.js
- Count and avg. with multi-level nesting in D3
- D3 Multi-Series Line Chart with ZOOM
- How to make sense of `f(array[i], i, array)` found in `d3.min()` source code?
- Using Multiple Link Types in D3 Tree Layout
- Include IE executables in Eclipse RCP project
- Chart to display data over a long time frame
- Can I use a d3 transition to stagger execution of an arbitrary function, and if so, how?
- toggling between two functions
- Select top k records for each date
- Transposing the values of d3.nest result
- Type error after making standalone d3v5 zoom with tooltip code from Mike Bostocks oberservablehq example
- How do I calculate the size attributes for my tree elements in json?
- Adding text to links that is represented in a JSON list - D3.js tree layout
- d3.js Lasso Drawing Polygon Shape Search Tool - on a google map (getting the coordinates/users in a given area)
- Trying to display circle and text by nesting in g element, failing. what is wrong?
- Ghost - Embedded JavaScript doesn't trigger d3js
- D3 Javascript loop doesn't render
- How to plot graphs using networkx and d3py
- D3 Zoom functionality is not working in Google chrome
- Drop down menu over d3 SVG
- d3 stacked bar chart not updating correctly
- D3.js - How to multiply a time domain by a scalar?