Is there a standard way to read and parse DOT graph files in javascript, ideally in way that will work nicely in d3?
Currently, the only thing I can think of doing is reading plain text and doing my own parsing. Hopefully this'd be reinventing the wheel though.
d3.text("graph.dot", function(error, dotGraph) {
....
)};
⚠ Solution proposed here depends on two libraries marked as unsupported by their authors.
To get Graphviz DOT files rendered in Javascript, combine the graphlib-dot and dagre-d3 libraries.
The graphlibDot.read() method takes a graph or digraph definition in DOT syntax and produces a graph object. The dagreD3.render() method can then output this graph object to SVG.
You can then use additional D3 methods to add functionality to the graph, retrieving additional node and edge attributes from the graphlib graph object as needed.
A trivial self-contained example is:
window.onload = function() {
// Parse the DOT syntax into a graphlib object.
var g = graphlibDot.read(
'digraph {\n' +
' a -> b;\n' +
' }'
)
// Render the graphlib object using d3.
var render = new dagreD3.render();
render(d3.select("svg g"), g);
// Optional - resize the SVG element based on the contents.
var svg = document.querySelector('#graphContainer');
var bbox = svg.getBBox();
svg.style.width = bbox.width + 40.0 + "px";
svg.style.height = bbox.height + 40.0 + "px";
}
svg {
overflow: hidden;
}
.node rect {
stroke: #333;
stroke-width: 1.5px;
fill: #fff;
}
.edgeLabel rect {
fill: #fff;
}
.edgePath {
stroke: #333;
stroke-width: 1.5px;
fill: none;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://dagrejs.github.io/project/graphlib-dot/v0.6.4/graphlib-dot.min.js"></script>
<script src="https://dagrejs.github.io/project/dagre-d3/v0.5.0/dagre-d3.min.js"></script>
<html>
<body>
<script type='text/javascript'>
</script>
<svg id="graphContainer">
<g/>
</svg>
</body>
</html>
Late to the party, but if you're still interested, here's a way to do it with the new d3-graphviz plug-in that I just released:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="http://viz-js.com/bower_components/viz.js/viz-lite.js"></script>
<script src="https://github.com/magjac/d3-graphviz/releases/download/v0.0.4/d3-graphviz.min.js"></script>
<div id="graph" style="text-align: center;"></div>
<script>
d3.select("#graph").graphviz()
.renderDot('digraph {a -> b}');
</script>
Same example, using latest version of graphlib-dot and dagre-d3.
window.onload = function() {
// Parse the DOT syntax into a graphlib object.
var g = graphlibDot.read(
'digraph {\n' +
' a -> b;\n' +
' }'
)
// Render the graphlib object using d3.
var renderer = dagreD3.render();
d3.select("svg g").call(renderer, g);
// Optional - resize the SVG element based on the contents.
var svg = document.querySelector('#graphContainer');
var bbox = svg.getBBox();
svg.style.width = bbox.width + 40.0 + "px";
svg.style.height = bbox.height + 40.0 + "px";
}
svg {
overflow: hidden;
}
.node rect {
stroke: #333;
stroke-width: 1.5px;
fill: #fff;
}
.edgeLabel rect {
fill: #fff;
}
.edgePath {
stroke: #333;
stroke-width: 1.5px;
fill: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="http://cpettitt.github.io/project/graphlib-dot/latest/graphlib-dot.min.js"></script>
<script src="http://cpettitt.github.io/project/dagre-d3/latest/dagre-d3.js"></script>
<html>
<body>
<script type='text/javascript'>
</script>
<svg id="graphContainer">
<g/>
</svg>
</body>
</html>
The question asks for a possibility to visualise .dot files einther in javascript or D3js. I think the solution from the highest rated answer will work for most of you.
I was unhappy because of these 3 reasons:
It involves libraries like lowdash, dagre and graphlib additionally to D3js and is heavyweight.
Parser output is not a D3js "friedly" data-structure.
Usage (API) in not D3js style.
That's why I created an adapter which will basically allow you to use .dot files with any of thousands of D3js samples by changing just one statement. If you have some D3js visualisation working on following data-structure:
{
"nodes": [ {"id": "Myriel"}, {"id": "Napoleon"}],
"links": [ {"source": "Myriel"}, {"target": "Napoleon"}]
}
Just include following script and call d3.dot:
<script src="https://cdn.jsdelivr.net/gh/gmamaladze/d3-dot-graph#1.0.0/build/d3-dot-graph.min.js"></script>
<script>
d3.dot(url, function(graph) {
...
});
</script>
instead of:
d3.json(url, function(graph) {...});
GitHub repository with code and examples
Related
I think I've hit a wall here. Not sure why my map isn't displaying at all.
I've converted the topojson file to geojson with the topojson client (https://github.com/topojson/topojson-client/blob/master/README.md)
Here's my JS file (I'm seeing my #map and background color, but nothing is rendering inside.)
var width = 900,
height = 600;
var svg = d3.select('#map')
.append('svg')
.attr('width', width)
.attr('height', height);
var projection = d3.geoAlbersUsa()
var path = d3.geoPath()
.projection(projection);
d3.json("https://gist.githubusercontent.com/Lupi7000/d770ce6f2985c3a7bac1099688e4f772/raw/d327f59834fb0f9f2201ad71c3f1711ecb5bf6de/NYTest.json")
.then(function(d) {
console.log(d)
var counties = topojson.feature(d, d.objects.cb_2015_new_york_county_20m)
console.log(counties)
svg.selectAll('path').data(counties.features)
.enter().append('path')
.attr('d', path);
});
Here's my HTML
<html>
<head>
<meta charset="UTF-8">
<title> NYS Map</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="https://unpkg.com/topojson#3.0.2/dist/topojson.min.js"></script>
<script src="https://unpkg.com/topojson-client#3"></script>
<script src="NYmap.js"></script>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>
<h3> NYS MAP CLICKABLE AND SHIT... EVENTUALLY</h3>
<div id="map"><!-- MAP CONTAINER --></div>
</body>
</html>
And my stylesheet
body {
margin: 25px;
}
#map {
width: 900px;
height: 600px;
border: 1px solid black;
background: whitesmoke;
}
path {
fill: black;
}
Any help would be appreciated, thanks!
I've console logged my data so it's coming through, but I'm not sure what I need to do to make it show up.
This question already has an answer here:
D3.js Map with Albers Projection: How to rotate it?
(1 answer)
Closed 3 years ago.
I have been pounding my head for several hours to how does my map shows super small in D3.
I've tried adjusting the scale but it doesn't seam to project correctly.
Here's my code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Manda</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<style>
.states :hover {
fill: red;
}
.state-borders {
fill: none;
stroke: #fff;
stroke-width: 0.5px;
stroke-linejoin: round;
stroke-linecap: round;
pointer-events: none;
}
svg {
background: rgb(201, 197, 197);
}
</style>
</head>
<body>
<svg></svg>
</body>
<script>
var w = 960,
h = 600;
var svg = d3.select("svg");
svg.attr("width", w).attr("height", h);
var projection = d3
.geoAlbers()
.scale(200)
.translate([w / 2, h / 2]);
var path = d3.geoPath().projection(projection);
d3.queue()
.defer(d3.json, "NCR/Mandaluyong/MandaTopo.json")
.await(ready);
function ready(err, data) {
if (err) return console.log(err);
var brgys = topojson.feature(data, data.objects.Mandaluyong).features;
svg
.selectAll(".brgy")
.data(brgys)
.enter()
.append("path")
.attr("class", "brgy")
.attr("d", path)
.attr("stroke", "black");
}
</script>
</html>
I added an stroke to emphasize the map.
Here's the MandaTopo.json. https://raw.githubusercontent.com/popoy2k/MandaLightMap/master/NCR/Mandaluyong/MandaTopo.json
Here's what i see in the svg
Click me
The projection you're using is d3.geoAlbers, which the documentation says is:
a U.S.-centric configuration of d3.geoConicEqualArea
Since it looks like your data is in the Philippines, maybe a different projection would work better for you.
I tried replacing the line var projection = d3.geoAlbers... with the following, which seemed to work pretty well:
var projection = d3
.geoMercator()
.scale(900000)
.center([121.038505, 14.588329]);
Why the result of bBox.width, bBox.height are both 0? I expect them to be both 500px, how to rectify it?
<!DOCTYPE html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.8/d3.min.js" type="text/JavaScript"></script>
<!--script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.9/d3.js" type="text/JavaScript"></script-->
<style>
rect {
stroke: #9A8B7A;
stroke-width: 1px;
fill: #CF7D1C;
}
svg{
width: 500px;
height: 500px;
background:blue;
}
</style>
<body>
</body>
<script>
var svg = d3.select("body").append("svg");
var bBox = svg.node().getBBox();
console.log(bBox.width + 'x' + bBox.height);
</script>
Try getBoundingClientRect instead of getBBox.
I am very new to Liferay.
I would like to show my graph created by D3.js inside of a portlet.
I have created the default MVC portlet.
However, I have no idea how to show my graph inside a MVC portlet.
Can you please advise?
<!DOCTYPE html>
<html>
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.chart div {
font: 10px sans-serif;
background-color: steelblue;
text-align: right;
padding: 3px;
margin: 1px;
color: white;
}
</style>
<body>
<div class="chart">
</div>
<script>
var data = [30, 86, 168, 281, 303, 365];
d3.select(".chart")
.selectAll("div")
.data(data)
.enter()
.append("div")
.style("width", function(d) { return d * 2 + "px"; })
.text(function(d) { return '$ ' + d; });
</script>
</body>
</html>
I am new to datavis and the D3 library and I'm trying to follow the tut here http://mbostock.github.com/d3/tutorial/bar-1.html
When I run the code, nothing displays on my webpage, can anyone point out the problem??
I think its something to do with the d3.select method. When I run the code and inspect it, the body is empty, so Im assuming nothing is being created. Any help would be hugely appreciated!!!
<title>3Dtut - 1</title>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.4.5"> </script>
<script type="text/javascript">
var data = [4, 8, 15, 16, 23, 42];
//container for the bar chart
var chart = d3.select("body").append("div")
.attr("class", "chart");
//adding div elements to the bar chart
chart.selectAll("div")
.data(data)
.enter().append("div")
.style("width", function(d) { return d * 10 + "px"; })
.text(function(d) { return d; });
</script>
<STYLE type="text/css">
.chart div {
font: 10px sans-serif;
background-color: steelblue;
text-align: right;
padding: 3px;
margin: 1px;
color: white;
}
</STYLE>
</head>
<body>
</body>
</html>
The problem is related to the position of your <script> .. </script> within the html document.
No body element exists yet at the moment that your script is being executed. That means that d3.select("body") will be empty, and no div.chart is being appended.
Try to move your <script> .. </script> inside the <body> .. </body> part. This will guarantee that the body element exists when your code is being executed.
Using the inside the body makes it not only available to the tag or any of the but also executes it faster. Also as div is a tag u could create a class eg. one and then use it as d3.select(".one") so that it doesn't coincide.
If you do not wish to put your <script> tags within the <body> element, you can also tell the browser to execute your d3 code (or any other JavaScript code) after the DOM is ready.
Using a library such as jQuery, you can use:
$( document ).ready(function() {
// Your d3 code here
});
This will ensure that your scripts are executed after the whole DOM is ready, including the <body> element.
For reference, examples and a shorter version of jQuery ready function, see http://learn.jquery.com/using-jquery-core/document-ready/.