Created
April 2, 2016 09:15
-
-
Save minsukkahng/6d9c3609e042592ec0f2f4edf8cd9103 to your computer and use it in GitHub Desktop.
20대 국회 선거구
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> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<style> | |
@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css); | |
text, div, h1, h3, span { | |
font-family: 'Nanum Gothic', sans-serif; | |
font-size: 13px; | |
} | |
.background { | |
fill: #fff; | |
} | |
.province { | |
fill: #eee; | |
stroke: #555; | |
stroke-width: 1; | |
fill-opacity: 0.1; | |
stroke-opacity: 0.5; | |
cursor: pointer; | |
} | |
.precinct { | |
stroke: #fff; | |
stroke-width: 1; | |
opacity: 0.5; | |
} | |
.province-label { | |
font-size: 10px; | |
text-anchor: middle; | |
fill: #333; | |
} | |
.precinct-label { | |
font-size: 3px; | |
text-anchor: middle; | |
visibility: hidden; | |
} | |
.g_precincts { | |
pointer-events: all; | |
} | |
.province.highlighted { | |
fill-opacity: 0.01; | |
stroke-opacity: 0.9; | |
} | |
.precinct.highlighted { | |
opacity: 0.8; | |
} | |
.province.notselected { | |
fill-opacity: 0.5; | |
} | |
.province.selected { | |
fill: none; | |
stroke: #555; | |
stroke-opacity: 1.0; | |
opacity: 1.0; | |
} | |
.precinct.selected { | |
stroke: #555; | |
stroke-opacity: 1.0; | |
opacity: 0.7; | |
} | |
#info { | |
position: absolute; | |
top: 0; | |
left: 0; | |
padding: 5px; | |
width: 160px; | |
height: 35px; | |
background-color: #333; | |
color: white; | |
visibility: hidden; | |
} | |
#info h3 { | |
margin: 0 0 8px 0; | |
padding: 0 0 1px 0; | |
font-size: 14px; | |
border-bottom: 1px solid #eee; | |
} | |
#info div { | |
float: left; | |
} | |
img { | |
height: 65px; | |
margin: 0 5px 0 0; | |
float: left; | |
} | |
</style> | |
</head> | |
<body> | |
<svg></svg> | |
<div id="info"></div> | |
<p><a href="http://bl.ocks.org/minsukkahng/">19대 국회 (국회의원 정보 포함) 보기</a></p> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://d3js.org/topojson.v1.min.js"></script> | |
<script> | |
var maps_path = {20: {"provinces": "https://raw.githubusercontent.com/minsukkahng/southkorea-maps/precinct/kostat/2013/json/skorea_provinces_topo.json", "precinct": "https://raw.githubusercontent.com/minsukkahng/southkorea-maps/precinct/popong/precinct/assembly-precinct-20-topo-simplified.json"}} | |
var topo_key = {20: {"provinces": "skorea_provinces_geo", "precinct": "precincts"}} | |
var assembly_no = 20; | |
var width = 960, height = 720; | |
var active = d3.select(null); | |
var proj = d3.geo.mercator() | |
.center([128.0, 35.9]) | |
.scale(6000) | |
.translate([width/2, height/2]); | |
var path = d3.geo.path() | |
.projection(proj); | |
var svg = d3.select("svg") | |
.attr("width", width) | |
.attr("height", height); | |
svg.append("rect") | |
.attr("class", "background") | |
.attr("width", width) | |
.attr("height", height) | |
.on("click", reset); | |
var g = svg.append("g"); | |
var precinct_person = {}; | |
var gm = g.append("g"); | |
var gp = g.append("g"); | |
d3.json(maps_path[assembly_no]["provinces"], function(error, kor) { | |
var provinces = topojson.feature(kor, kor.objects[topo_key[assembly_no]["provinces"]]); | |
var g_provinces = gp.selectAll('g') | |
.data(provinces.features, function(d) { return d.properties.code; }) | |
.enter() | |
.append('g') | |
.attr('class', 'g_province'); | |
g_provinces.append('path') | |
.attr('d', path) | |
.attr('class', 'province') | |
.on("click", clicked) | |
.append("title") | |
.text(function(d) { return d.properties.name; }); | |
g_provinces.append("text") | |
.attr("class", "province-label") | |
.attr("id", function(d) { return "province-label " + d.properties.code; }) | |
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; }) | |
.attr("dy", function(d) { if( d.properties.code == 31 ) return "20px"; }) // Gyeonggi to separate from Seoul | |
.text(function(d) { return d.properties.name; }); | |
g_provinces.on("mouseover", function() { | |
d3.select(this).select("path").classed("highlighted", true); | |
}); | |
g_provinces.on("mouseout", function() { | |
d3.select(this).select("path").classed("highlighted", false); | |
}) | |
}); | |
d3.json(maps_path[assembly_no]["precinct"], function(error, kor) { | |
var precincts = topojson.feature(kor, kor.objects[topo_key[assembly_no]["precinct"]]); | |
var g_precincts = gm.selectAll('g') | |
.data(precincts.features, function(d) { return d.properties.precinct_no; }) | |
.enter() | |
.append('g') | |
.attr('class', 'g_precinct'); | |
g_precincts | |
.append('path') | |
.attr('d', path) | |
.attr('class', 'precinct') | |
.append("title") | |
.text(function(d) { return d.properties.precinct_name; }); | |
g_precincts.append("text") | |
.attr("class", "precinct-label") | |
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; }) | |
.attr("dy", ".35em") | |
.text(function(d) { return d.properties.precinct_name; }); | |
g_precincts.select("path.precinct") | |
.style("fill", function(d) { return "#999999"; }) | |
g_precincts.on("mouseover", function() { | |
d3.select(this).select("path").classed("highlighted", true); | |
var html_text = '<h3>'+d3.select(this).datum().properties.precinct_name+'</h3>'; | |
// You can add more | |
html_text += '<div></div>'; | |
var point = d3.mouse(this); | |
d3.select("#info") | |
.style("left", function(d) { return point[0]+"px"; }) | |
.style("top", function(d) { return point[1]+"px"; }) | |
.style("visibility", "visible") | |
.html(html_text); | |
}); | |
g_precincts.on("mouseout", function() { | |
d3.select(this).select("path").classed("highlighted", false); | |
d3.select("#info") | |
.style("visibility", "hidden"); | |
}) | |
}); | |
function clicked(d) { | |
if (active.node() === this) return reset(); | |
active.classed("active", false); | |
active = d3.select(this).classed("active", true); | |
var bounds = path.bounds(d), | |
dx = bounds[1][0] - bounds[0][0], | |
dy = bounds[1][1] - bounds[0][1], | |
x = (bounds[0][0] + bounds[1][0]) / 2, | |
y = (bounds[0][1] + bounds[1][1]) / 2, | |
scale = .7 / Math.max(dx / width, dy / height), | |
translate = [width / 2 - scale * x, height / 2 - scale * y]; | |
g.transition() | |
.duration(750) | |
.style("stroke-width", 1.5 / scale + "px") | |
.attr("transform", "translate(" + translate + ")scale(" + scale + ")"); | |
d3.selectAll(".province").classed("selected", false); | |
d3.selectAll(".province").classed("notselected", false); | |
d3.selectAll(".precinct").classed("selected", false); | |
d3.selectAll("text.precinct-label").style("visibility", "hidden"); | |
d3.selectAll(".province").style("stroke-width", 2 / scale + "px"); | |
d3.selectAll(".precinct").style("stroke-width", 1 / scale + "px"); | |
d3.selectAll("text.province-label").style("font-size", 14 / scale + "px"); | |
if( d3.select(this).classed("province") ) { | |
d3.selectAll(".province").classed("notselected", true); | |
d3.select(this).classed("notselected", false); | |
d3.select(this).classed("selected", true); | |
d3.selectAll("text.precinct-label") | |
.style("visibility", "visible") | |
.style("font-size", 10 / scale + "px"); | |
} | |
} | |
function reset() { | |
active.classed("active", false); | |
active = d3.select(null); | |
g.transition() | |
.duration(750) | |
.style("stroke-width", "1.5px") | |
.attr("transform", ""); | |
d3.selectAll(".province").classed("selected", false); | |
d3.selectAll(".province").classed("notselected", false); | |
d3.selectAll(".precinct").classed("selected", false); | |
d3.selectAll("text.precinct-label").style("visibility", "hidden"); | |
d3.selectAll("text.province-label").style("font-size", "10px"); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment