Last active
November 22, 2019 21:44
-
-
Save RalucaNicola/0ad77ee982166a3ed72daed1157756a2 to your computer and use it in GitHub Desktop.
Prototype for elections map
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font-family: Arial, Helvetica, sans-serif; | |
color: #444; | |
} | |
#g1, | |
.red-party { | |
color: #e83a66; | |
} | |
#g2, | |
.blue-party { | |
color: #3a7de8; | |
} | |
div.tooltip { | |
position: absolute; | |
text-align: center; | |
font: 1em; | |
background: white; | |
padding: 0.5em; | |
pointer-events: none; | |
display: none; | |
} | |
</style> | |
</head> | |
<body> | |
<p>Imagine this is a map of elections. Each point is a municipality or simply put, an administrative unit. | |
The circle radius is proportional to the number of votes (I should change this to make the area proportional to no of votes). | |
The gray area represents votes that are obtained by the red party and the blue party. | |
You can think of it as votes that cancel each other. | |
The red party has <span class="red-party" id="red-votes"></span> votes. | |
The blue party has <span class="blue-party" id="blue-votes"></span> votes. | |
</p> | |
<button id="filter-red">Show only red party</button> | |
<button id="filter-blue">Show only blue party</button> | |
<button id="reset-filter">Reset filter</button> | |
<script src="//d3js.org/d3.v3.min.js"></script> | |
<script> | |
const margin = { top: 10, right: 30, bottom: 30, left: 30 }; | |
const width = 960 - margin.left - margin.right; | |
const height = 600 - margin.top - margin.bottom; | |
const svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
const tooltip = d3.select("body").append("div") | |
.attr("class", "tooltip") | |
.style("opacity", 0); | |
// generate random data | |
const data = []; | |
for (i = 0; i < 1000; i++) { | |
data.push({ g1: Math.floor(Math.random() * 35), g2: Math.floor(Math.random() * 45) }) | |
} | |
const opacity = 0.9; | |
const red = "#e83a66"; | |
const blue = "#3a7de8"; | |
const gray = "#ddd"; | |
const cols = 50; | |
const municipality = svg.selectAll("g") | |
.data(data) | |
.enter() | |
.append("g") | |
.attr("transform", function () { return "translate(" + Math.random() * width + ", " + Math.random() * width + ")"; }) | |
.on("mousemove", function (d, i) { | |
tooltip.transition() | |
.duration(100) | |
.style("opacity", .9) | |
.style("display", "inherit"); | |
tooltip.html("<span class='red-party'>" + d.g1 + " red votes</span> | <span class='blue-party'>" + d.g2 + " blue votes</span>") | |
.style("left", (d3.event.pageX) + "px") | |
.style("top", (d3.event.pageY - 30) + "px"); | |
}) | |
.on("mouseout", function (d, i) { | |
tooltip.transition() | |
.duration(300) | |
.style("opacity", 0) | |
.style("display", "none"); | |
}); | |
municipality.append("circle") | |
/* .attr("cy", function (d, i) { return Math.floor(i / cols) * 30 + 30; }) | |
.attr("cx", function (d, i) { return i % cols * 30 + 30; }) */ | |
.attr("cy", 0) | |
.attr("cx", 0) | |
.attr("r", function (d) { return d.g1 > d.g2 ? d.g1 / 2 : d.g2 / 2; }) | |
.attr("class", function (d) { return d.g1 > d.g2 ? "red" : "blue"; }) | |
.style("fill", function (d) { return d.g1 > d.g2 ? red : blue; }) | |
.style("opacity", opacity); | |
municipality.append("circle") | |
/* .attr("cy", function (d, i) { return Math.floor(i / cols) * 30 + 30; }) | |
.attr("cx", function (d, i) { return i % cols * 30 + 30; }) */ | |
.attr("cy", 0) | |
.attr("cx", 0) | |
.attr("r", function (d) { return d.g1 > d.g2 ? d.g2 / 2 : d.g1 / 2; }) | |
.attr("class", function (d) { return d.g1 < d.g2 ? "small red" : "small blue"; }) | |
.style("fill", function (d) { return gray; }); | |
sumG1 = data.reduce(function (s, e) { return s + e.g1 }, 0); | |
sumG2 = data.reduce(function (s, e) { return s + e.g2 }, 0); | |
d3.select("#red-votes").text(sumG1.toString()); | |
d3.select("#blue-votes").text(sumG2.toString()); | |
d3.select("#filter-red").on("click", function () { | |
d3.selectAll(".red") | |
.transition() | |
.style("fill", red) | |
.style("opacity", opacity) | |
.duration(2000); | |
d3.selectAll(".blue") | |
.transition() | |
.style("opacity", 0) | |
.duration(2000); | |
}); | |
d3.select("#filter-blue").on("click", function () { | |
d3.selectAll(".blue") | |
.transition().style("fill", blue) | |
.style("opacity", opacity) | |
.duration(2000); | |
d3.selectAll(".red") | |
.transition() | |
.style("opacity", 0) | |
.duration(2000); | |
}); | |
d3.select("#reset-filter").on("click", function () { | |
d3.selectAll(".red") | |
.transition().style("fill", red) | |
.style("opacity", opacity); | |
d3.selectAll(".blue") | |
.transition().style("fill", blue) | |
.style("opacity", opacity); | |
d3.selectAll(".small") | |
.transition().style("fill", gray) | |
.style("opacity", 1); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment