Skip to content

Instantly share code, notes, and snippets.

@oikonang
Created December 4, 2019 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oikonang/9ae1ba78e49da0445fd57ce1cf55dc1c to your computer and use it in GitHub Desktop.
Save oikonang/9ae1ba78e49da0445fd57ce1cf55dc1c to your computer and use it in GitHub Desktop.
Greece D3js
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
@import url(style.css);
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/queue.v1.min.js"></script>
<body>
<!-- Table to hold the data table, map and legend -->
<table border="0" cellpadding="10" style="overflow-y: scroll;">
<tr>
<td><div id="table_container" class="csvTable"></div></td>
<td><div id="map_container"></div></td>
<td><div id="legend_container"></div></td>
</tr>
</table>
<script>
var mw = 500; // map container width
var mh = 600; // map container height
var main_chart_svg = d3.select("#map_container")
.append("svg")
.attr({
"width":mw,
"height":mh,
});
var legend_svg = d3.select("#legend_container")
.append("svg")
.attr({
"width":200,
"height":600,
});
var hue = "g"; /* b=blue, g=green, r=red colours - from ColorBrewer */
/* break the data values into 9 ranges of €100 each */
/* max and min values already known so 400-1300 works */
var quantize = d3.scale.quantize()
.domain([400, 1300])
.range(d3.range(9).map(function(i) { return hue + i + "-9"; }));
/* declare locale so we can format values with euro symbol */
var ie = d3.locale({
"decimal": ".",
"thousands": ",",
"grouping": [3],
"currency": ["€", ""],
"dateTime": "%a %b %e %X %Y",
"date": "%d/%m/%Y",
"time": "%H:%M:%S",
"periods": ["AM", "PM"],
"days": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
"shortDays": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
"months": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
"shortMonths": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
});
var rateById = d3.map();
var lastActive = "";
var ireland;
var data;
var defaultScale = 0.6; /* default scale of map - fits nicely on standard screen */
var scale = 3; /* maximum size to zoom county */
var format = ie.numberFormat("$, #,##0d");
/* Thanks to http://stackoverflow.com/users/3128209/ameliabr for tips on creating a quantized legend */
var legend = legend_svg.selectAll('g.legendEntry')
.data(quantize.range())
.enter()
.append('g').attr('class', 'legendEntry');
legend
.append('rect')
.attr("x", 20)
.attr("y", function(d, i) {
return i * 25 + 20;
})
.attr("width", 15)
.attr("height", 15)
.attr("class", function(d){ return d;})
.style("stroke", "black")
.style("stroke-width", 1)
.on("click", function(d)
{
if (lastActive == "") {
resetAll();
d3.select(ireland).selectAll("." + d).attr("class", "highlight"); /* Highlight all counties in range selected */
}
});
legend
.append('text')
.attr("x", 40) //leave 5 pixel space after the <rect>
.attr("y", function(d, i) {
return i * 25 + 20;
})
.attr("dy", "0.8em") //place text one line *below* the x,y point
.text(function(d,i) {
var extent = quantize.invertExtent(d);
//extent will be a two-element array, format it however you want:
return format(extent[0]) + " - " + format(+extent[1])
})
.style("font-family", "sans-serif")
.style("font-size", "12px");
/* Data has key "county" and value "rental" - i.e. average rental price per county */
queue()
.defer(d3.csv, "rentals-2015-bycounty.csv", data)
.await(ready);
function ready(error, data) {
if (error) throw error;
d3.map(data, function(d) {rateById.set(d.county, +d.rental)}); /* create the data map */
d3.xml("greece.svg", "image/svg+xml", function(error, xml) { /* embed the SVG map */
if (error) throw error;
var countyTable = tabulate(data, ["county", "rental"]); /* render the data table */
var svgMap = xml.getElementsByTagName("g")[0]; /* set svgMap to root g */
ireland = main_chart_svg.node().appendChild(svgMap); /* island of Ireland map */
d3.select(ireland).selectAll("#NI") /* Group Northern Ireland together */
.attr("class", "region NI");
d3.select(ireland).selectAll("#republic") /* Group Republic of Ireland together */
.attr("class", "region republic");
d3.select(ireland).selectAll("#republic").selectAll("path") /* Map Republic counties to rental data */
.attr("class", function(d) {
return quantize(rateById.get(this.id));
})
.append("title").text(function(d) { /* add title = name of each county and average rental */
return this.parentNode.id + ", " + format(rateById.get(this.parentNode.id))
});
d3.select(ireland).selectAll("#republic").selectAll("path")
.on("mouseover", function(d)
{
if (d3.select(this).classed("active")) return; /* no need to change class when county is already selected */
d3.select(this).attr("class", "hover");
})
.on("mouseout", function(d)
{
if (d3.select(this).classed("active")) return;
d3.select(this).attr("class", function(d) { /* reset county color to quantize range */
return quantize(rateById.get(this.id))
});
})
.on("click", function (d) { zoomed(d3.select(this)); });
/* Let's add an id to each group that wraps a path */
d3.select(ireland).selectAll("#republic").selectAll("path")
.each(function(d) {
d3.select(this.parentNode).attr("id", this.id);
});
/* Now add a text box to the group with content equal to the id of the group */
d3.select(ireland).selectAll("#republic").selectAll("g")
.append("svg:text")
.text(function(d){
return this.parentNode.id;
})
.attr("x", function(d){
console.log(d3.select(this.parentNode).select("path").attr("d"));
//return 600;
//d3.select(ireland).select("path")
return getBoundingBox(d3.select(this.parentNode).select("path"))[4];
})
.attr("y", function(d){
return getBoundingBox(d3.select(this.parentNode).select("path"))[5];
})
// .attr("text-anchor","middle")
// .attr("font-family", "sans-serif")
// .attr("stroke-width", 0.5)
.classed("text", true)
// .attr("fill", "#333")
// .attr('font-size','10pt')
;
});
}
/* Thanks to http://bl.ocks.org/phil-pedruco/7557092 for the table code */
/* and style - and what a coincidence he also used a map of Ireland! */
function tabulate(data, columns) {
var table = d3.select("#table_container").append("table")
thead = table.append("thead"),
tbody = table.append("tbody");
// append the header row
thead.append("tr")
.selectAll("th")
.data(columns)
.enter()
.append("th")
.text(function(column) { return column; });
// create a row for each object in the data
var rows = tbody.selectAll("tr")
.data(data)
.enter()
.append("tr")
.on("click", function (d) { tableRowClicked(d)});
// create a cell in each row for each column
var cells = rows.selectAll("td")
.data(function(row) {
return columns.map(function(column) {
return {column: column, value: row[column]};
});
})
.enter()
.append("td")
// .attr("style", "font-family: Courier") // sets the font style
.html(function(d) {
if (d.column == "rental") return format(d.value); else return d.value;
});
return table;
}
function zoomed(d) {
/* Thanks to http://complextosimple.blogspot.ie/2012/10/zoom-and-center-with-d3.html */
/* for a simple explanation of transform scale and translation */
/* This function centers the county's bounding box in the map container */
/* The scale is set to the minimum value that enables the county to fit in the */
/* container, horizontally or vertically, up to a maximum value of 3. */
/* If the full width of container is not required, the county is horizontally centred */
/* Likewise, if the full height of the container is not required, the county is */
/* vertically centred. */
var xy = getBoundingBox(d); /* get top left co-ordinates and width and height */
if (d.classed("active")) { /* if county is active reset map scale and county colour */
d.attr("class", function(d) {
return quantize(rateById.get(this.id))
});
main_chart_svg.selectAll("#viewport")
.transition().duration(750).attr("transform", "scale(" + defaultScale + ")");
lastActive = "";
} else { /* zoom into new county */
resetAll(); /* reset county colors */
/* scale is the max number of times bounding box will fit into container, capped at 3 times */
scale = Math.min(mw/xy[1], mh/xy[3], 3);
/* tx and ty are the translations of the x and y co-ordinates */
/* the translation centers the bounding box in the container */
var tx = -xy[0] + (mw - xy[1]*scale)/(2*scale);
var ty = -xy[2] + (mh - xy[3]*scale)/(2*scale);
main_chart_svg.selectAll("#viewport")
.transition().duration(750).attr("transform", "scale(" + scale + ")translate("+ tx +"," + ty + ")");
d.attr("class", "active");
lastActive = d.attr("id");
}
}
function reset(selection) {
/* resets the color of a single county */
if (selection != "")
d3.select(ireland).select("#" + selection).attr("class", function(d) {
return quantize(rateById.get(this.id))
});
}
function resetAll() {
/* resets the color of all counties */
d3.select(ireland).selectAll("#republic").selectAll("path")
.attr("class", function(d) {
return quantize(rateById.get(this.id))
});
}
function tableRowClicked(x) {
/* resets colors and zooms into new county */
resetAll();
lastActive = x.county;
zoomed(d3.select(ireland).selectAll("#" + x.county).select("path"));
}
function getBoundingBox(selection) {
/* get x,y co-ordinates of top-left of bounding box and width and height */
var element = selection.node(),
bbox = element.getBBox();
cx = bbox.x + bbox.width/2;
cy = bbox.y + bbox.height/2;
return [bbox.x, bbox.width, bbox.y, bbox.height, cx, cy];
}
d3.select(self.frameElement).style("height", "650px");
</script>
type bedrooms address rental county
All property types All bedrooms Carlow 633.84 Carlow
All property types All bedrooms Cavan 453.01 Cavan
All property types All bedrooms Clare 524.19 Clare
All property types All bedrooms Cork 806.69 Cork
All property types All bedrooms Donegal 452.97 Donegal
All property types All bedrooms Dublin 1207.37 Dublin
All property types All bedrooms Galway 829.52 Galway
All property types All bedrooms Kerry 553.56 Kerry
All property types All bedrooms Kildare 887.66 Kildare
All property types All bedrooms Kilkenny 644.59 Kilkenny
All property types All bedrooms Laois 567.85 Laois
All property types All bedrooms Leitrim 414.23 Leitrim
All property types All bedrooms Limerick 643.55 Limerick
All property types All bedrooms Longford 422.36 Longford
All property types All bedrooms Louth 672.48 Louth
All property types All bedrooms Mayo 514.76 Mayo
All property types All bedrooms Meath 765.04 Meath
All property types All bedrooms Monaghan 499.16 Monaghan
All property types All bedrooms Offaly 545.5 Offaly
All property types All bedrooms Roscommon 462.79 Roscommon
All property types All bedrooms Sligo 600.72 Sligo
All property types All bedrooms Tipperary 539.24 Tipperary
All property types All bedrooms Waterford 554.23 Waterford
All property types All bedrooms Westmeath 568.02 Westmeath
All property types All bedrooms Wexford 560.88 Wexford
All property types All bedrooms Wicklow 911.88 Wicklow
/* style.css */
.region.republic {
fill: #fee391;
stroke: #333;
stroke-width: 1px;
}
.active
{fill: #f29929;
}
.hover
{fill: #fee391;
}
.highlight
{fill: #fec44f;
}
.region.NI {
fill: #aaa;
stroke: #aaa;
}
rect {
fill: none;
pointer-events: all;
}
/* Colors taken from colorbrewer2.org - blue */
.b0-9 { fill:rgb(247,251,255); }
.b1-9 { fill:rgb(222,235,247); }
.b2-9 { fill:rgb(198,219,239); }
.b3-9 { fill:rgb(158,202,225); }
.b4-9 { fill:rgb(107,174,214); }
.b5-9 { fill:rgb(66,146,198); }
.b6-9 { fill:rgb(33,113,181); }
.b7-9 { fill:rgb(8,81,156); }
.b8-9 { fill:rgb(8,48,107); }
/* Colors taken from colorbrewer2.org - red */
.r0-9 { fill:rgb(255,245,240); }
.r1-9 { fill:rgb(254,224,210); }
.r2-9 { fill:rgb(252,187,161); }
.r3-9 { fill:rgb(252,146,114); }
.r4-9 { fill:rgb(251,106,74); }
.r5-9 { fill:rgb(239,59,44); }
.r6-9 { fill:rgb(203,24,29); }
.r7-9 { fill:rgb(165,15,21); }
.r8-9 { fill:rgb(103,0,13); }
/* Colors taken from colorbrewer2.org - green */
.g0-9 { fill:rgb(247,252,245); }
.g1-9 { fill:rgb(229,245,224); }
.g2-9 { fill:rgb(199,233,192); }
.g3-9 { fill:rgb(161,217,155); }
.g4-9 { fill:rgb(116,196,118); }
.g5-9 { fill:rgb(65,171,93); }
.g6-9 { fill:rgb(35,139,69); }
.g7-9 { fill:rgb(0,109,44); }
.g8-9 { fill:rgb(0,68,27); }
.text { stroke:#333;
text-anchor: middle;
font-family: "sans-serif";
stroke-width: 0.5;
fill: #333;
font-size: 10pt;
}
.csvTable table {
border-collapse: collapse;
text-align: left;
width: 100%;
}
.csvTable {
font: normal 12px/120% Arial, Helvetica, sans-serif;
background: #fff;
overflow: hidden;
border: 1px solid #063;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.csvTable table td, .csvTable table th {
padding: 3px 10px;
}
.csvTable table thead th {
background: 0;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#006699',endColorstr='#00557F');
background-color: #006D2C;
color: #FFF;
font-size: 15px;
font-weight: 700;
border-left: 1px solid #0070A8;
}
.csvTable table thead th:first-child {
border: none;
}
.csvTable table tbody td {
color: #006633; /* #00496B */
border-left: 1px solid #E1EEF4;
font-size: 12px;
border-bottom: 1px solid #E1EEF4;
font-weight: 400;
}
.csvTable table tbody td:first-child {
border-left: none;
}
.csvTable table tbody tr:last-child td {
border-bottom: none;
}
.csvTable tr:hover td {
background-color: #063;
color: white;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment