Based on special questions "We will not be in the government with ..."
- prepare the data (manually)
- helper.py create links
- koalice.html
| 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> |
| 1 | |||||||||
| 1 | 1 | ||||||||
| 1 | 1 | ||||||||
| 1 | 1 | 1 | |||||||
| 1 | 1 | ||||||||
| 1 | 1 | 1 | 1 | ||||||
| 1 | 1 | 1 | 1 | 1 | |||||
| 1 | 1 | 1 | 1 | 1 | |||||
| 1 | 1 | 1 | 1 | 1 | 1 |