Skip to content

Instantly share code, notes, and snippets.

@michalskop
Last active October 8, 2017 03:17
Show Gist options
  • Save michalskop/a2386e7d66a52dc623b116c422faa395 to your computer and use it in GitHub Desktop.
Save michalskop/a2386e7d66a52dc623b116c422faa395 to your computer and use it in GitHub Desktop.
VAA force chart

VAA coalition chart

Based on special questions "We will not be in the government with ..."

  1. prepare the data (manually)
  2. helper.py create links
  3. koalice.html
We can make this file beautiful and searchable if this error is corrected: It looks like row 2 should actually have 4 columns, instead of 3 in line 1.
source,target,value,slug
ČSSD,ANO,1
KDU,ANO,1
KDU,ČSSD,1
ODS,ČSSD,1
ODS,KDU,1
Piráti,ČSSD,1
Piráti,KDU,1
Piráti,ODS,1
SPD,ANO,1
SPD,KSČM,1
STAN,ČSSD,1
STAN,KDU,1
STAN,ODS,1
STAN,Piráti,1
TOP 09,ČSSD,1
TOP 09,KDU,1
TOP 09,ODS,1
TOP 09,Piráti,1
TOP 09,STAN,1
Zelení,ČSSD,1
Zelení,KDU,1
Zelení,Piráti,1
Zelení,STAN,1
Zelení,TOP 09,1
Svobodní,ČSSD,1
Svobodní,KDU,1
Svobodní,ODS,1
Svobodní,Piráti,1
Svobodní,SPD,1
Svobodní,TOP 09,1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bootswatch: Free themes for Bootstrap</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<link rel="stylesheet" href="bootstrap.min.css" media="screen">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<script src="http://d3js.org/d3.v3.js"></script>
<style>
path.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
}
circle {
fill: red;
stroke: #fff;
stroke-width: 1.5px;
}
text {
fill: #000;
font: 10px sans-serif;
pointer-events: none;
}
.logo {
width: 28px;
height: 28px;
border-radius: 50%;
}
.hithit {
width: 100vw;
background-color: #fed201;
padding: 10px;
}
.top {
width: 100vw;
padding: 10px;
background-color: #fed201;
}
</style>
<body>
<script>
// get the data
d3.csv("force.csv", function(error, links) {
var nodes = {};
// Compute the distinct nodes from the links.
links.forEach(function(link) {
link.source = nodes[link.source] ||
(nodes[link.source] = {name: link.source});
link.target = nodes[link.target] ||
(nodes[link.target] = {name: link.target});
link.value = +link.value;
});
var width = 476,
height = 400;
var force = d3.layout.force()
.nodes(d3.values(nodes))
.links(links)
.size([width, height])
.linkDistance(150)
.charge(-1000)
.on("tick", tick)
.start();
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height);
// build the arrow.
svg.append("svg:defs").selectAll("marker")
.data(["end"]) // Different link/path types can be defined here
// .enter().append("svg:marker") // This section adds in the arrows
// .attr("id", String)
// .attr("viewBox", "0 -5 10 10")
// .attr("refX", 15)
// .attr("refY", -1.5)
// .attr("markerWidth", 6)
// .attr("markerHeight", 6)
// .attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L00,0L0,5");
// add the links and the arrows
var path = svg.append("svg:g").selectAll("path")
.data(force.links())
.enter().append("svg:path")
// .attr("class", function(d) { return "link " + d.type; })
.attr("class", "link")
.attr("marker-end", "url(#end)");
// define the nodes
var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.call(force.drag);
// add the nodes
// node.append("circle")
// .attr("r", 5);
node.append("svg:image")
.attr('x',-25)
.attr('y',-25)
.attr('width', 50)
.attr('height', 50)
.attr('class', 'logo')
.attr("xlink:href", function(d) {
return "200x200/" + d.name + ".png"
});
// add the text
// node.append("text")
// .attr("x", 12)
// .attr("dy", ".1em")
// .text(function(d) { return d.name; });
// add the curvy lines
function tick() {
path.attr("d", function(d) {
var dx = d.target.x - d.source.x,
dy = d.target.y - d.source.y,
dr = Math.sqrt(dx * dx + dy * dy);
return "M" +
d.source.x + "," +
d.source.y + "A" +
dr + "," + dr + " 0 0,1 " +
d.target.x + "," +
d.target.y;
});
node
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; });
}
});
</script>
<div class="top text-center">
<h4>Které strany spolu chtějí vládnout.</h4>
<h4>Na základě odpovědí pro Volební kalkulačku.</h4>
<h6>Otázka zněla "Vylučujeme vládu s ... "</h6>
</div>
<div id="chart"></div>
<div class="hithit text-center">
<h5>Podpořte Volební kalkulačku na Hithitu!</h5>
<h5>www.Hithit.cz/VolebniKalkulacka</h5>
</div>
</body>
</html>
# prepare nodes for D3
import csv
import slugify
arr = ['ANO', 'ČSSD', 'KDU', 'KSČM', 'ODS', 'Piráti', 'SPD', 'STAN', 'TOP 09', 'Zelení', 'Svobodní']
with open("links.csv") as fin:
csvr = csv.reader(fin)
print('source,target,value,slug')
i = 0
for r in csvr:
j = 0
for item in r:
if str(item) == '1':
# print('{ source: ' + str(i) + ',target: ' + str(j) + '},')
print(arr[i] + ',' + arr[j] + ',1')
j += 1
i += 1
<html>
<head>
<meta charset="utf-8">
<title>D3 practice</title>
<meta name="viewport" content="width=device-width, initial-scale 1.0">
<style>
/*//////////////////////////////////////
UNIVERSAL
//////////////////////////////////////*/
* {
padding: 0;
margin: 0;
list-style-type: none;
font-weight: normal;
text-decoration: none;
box-sizing: border-box;
}
h1,
h2,
h3,
h4,
h5,
h6 {
padding: 0;
margin: 0;
font-weight: normal;
}
img,
video {
max-width: 100%;
}
input, button, select, textarea, submit {
border: none;
}
/* ---- Float clearfix ---- */
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
/*//////////////////////////////////////
TEXT TRANSFORM
//////////////////////////////////////*/
/*Uppercase*/
/*Lowercase*/
/*//////////////////////////////////////
FONTS
//////////////////////////////////////*/
/*BUNGEE INLINE*/
/*//////////////////////////////////////
COLORS
//////////////////////////////////////*/
/*STARK WHITE*/
/*//////////////////////////////////////
D3 PRACTICE
//////////////////////////////////////*/
</style>
</head>
<body class="site-container">
<div class="site-content">
</div>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-collection.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-quadtree.v1.min.js"></script>
<script src="https://d3js.org/d3-timer.v1.min.js"></script>
<script src="https://d3js.org/d3-force.v1.min.js"></script>
<script>
$(document).ready(function() {
//Width and height
var w = 500;
var h = 300;
//Original data
var dataset = {
nodes: [
{ name: "Adam" },
{ name: "Bob" },
{ name: "Carrie" },
{ name: "Donovan" },
{ name: "Edward" },
{ name: "Felicity" },
{ name: "George" },
{ name: "Hannah" },
{ name: "Iris" },
{ name: "Jerry" },
{ name: 'Karel' }
],
edges: [
{ source: 1,target: 0},
{ source: 2,target: 0},
{ source: 2,target: 1},
{ source: 4,target: 1},
{ source: 4,target: 2},
{ source: 4,target: 3},
{ source: 5,target: 1},
{ source: 5,target: 2},
{ source: 5,target: 4},
{ source: 6,target: 0},
{ source: 6,target: 3},
{ source: 7,target: 1},
{ source: 7,target: 2},
{ source: 7,target: 4},
{ source: 7,target: 5},
{ source: 8,target: 1},
{ source: 8,target: 2},
{ source: 8,target: 4},
{ source: 8,target: 5},
{ source: 8,target: 7},
{ source: 9,target: 1},
{ source: 9,target: 2},
{ source: 9,target: 5},
{ source: 9,target: 7},
{ source: 9,target: 8},
{ source: 10,target: 1},
{ source: 10,target: 2},
{ source: 10,target: 4},
{ source: 10,target: 5},
{ source: 10,target: 6},
{ source: 10,target: 8}
]
};
//Initialize a default force layout, using the nodes and edges in dataset
var force = d3.forceSimulation()
.force('link', d3.forceLink())
.force("charge", d3.forceManyBody().strength(100))
.force("x", d3.forceX(w/2))
.force("y", d3.forceY(h/2))
.on("tick", tick);
var colors = d3.scaleOrdinal(d3.schemeCategory10);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
start();
function start() {
var nodeElements = svg.selectAll(".node")
.data(dataset.nodes, function(d){return d.id});
var linkElements = svg.selectAll(".link")
.data(dataset.edges);
nodeElements.enter()
.append("circle")
.attr("class", function(d) {return "node " + d.id; })
.attr("r", 10)
.style("fill", function(d, i) {
return colors(i);
});
linkElements.enter()
.insert("line", ".node")
.attr("class", "link")
.style("stroke", "#ccc")
.style("stroke-width", 1);
nodeElements.exit().remove();
linkElements.exit().remove();
force.nodes(dataset.nodes)
force.force("link").links(dataset.edges).distance(150)
force.restart();
}
function tick() {
var nodeElements = svg.selectAll(".node");
var linkElements = svg.selectAll(".link");
nodeElements.attr("cx", function(d,i) {return d.x; })
.attr("cy", function(d) { return d.y; })
linkElements.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; });
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment