Skip to content

Instantly share code, notes, and snippets.

@aholachek
Last active June 1, 2017 17:02
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 aholachek/700f930820f2704a957c070173327789 to your computer and use it in GitHub Desktop.
Save aholachek/700f930820f2704a957c070173327789 to your computer and use it in GitHub Desktop.
Very simple responsive map of Asia
// load the data, find the svg container in the dom,
// and call createMap
d3.json('map-data.json', function(error, data){
var svg = d3.select('svg')
createMap(svg, data)
})
// put all logic in a nice reusable function
function createMap(svg, data) {
// use viewBox attributes instead of width + height
var params = svg.attr('viewBox').split(' ').map(function (n) { return parseInt(n, 10); })
var width = params[2]
var height = params[3]
var mapContainer = svg.append('g')
var projection = d3.geoMercator()
// d3's 'fitSize' magically sizes and positions the map for you
.fitSize([width, height], data);
// this is the function that generates position data from the projection
var path = d3.geoPath()
.projection(projection);
// append country outlines
var countries = mapContainer.selectAll('.country')
.data(data.features)
.enter()
.append('path')
.attr('class', 'country')
.attr('d', path)
.on('click', function(d){
var d3this = d3.select(this)
if (d3this.classed('active')){
d3.selectAll('.country').classed('active', false);
return
}
d3.selectAll('.country').classed('active', false);
d3.select(this).classed('active', true);
});
// append labels
mapContainer
.selectAll('.label')
.data(data.features)
.enter()
.append('text')
.attr('class', 'label')
.text(function (d){ return d.properties.admin; })
.attr('transform', function (d){
var centroid = path.centroid(d)
return ("translate(" + (centroid[0]) + ", " + (centroid[1]) + ")")
})
}

To view the responsive attributes of the map, open it in a new window.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
body {
/* system font stack*/
font-family: -apple-system,
system-ui,
BlinkMacSystemFont,
"Segoe UI",
"Roboto",
"Helvetica Neue",
Arial,
sans-serif;
color: hsl(0, 0%, 20%);
}
.country {
fill : hsla(0, 0%, 50%, 0.4);
stroke:white;
stroke-width: 1.5px;
cursor: pointer;
}
.country:hover {
fill : hsla(0, 0%, 50%, .6);
}
.country.active {
fill: hsl(0, 100%, 75%);
}
.country.active:hover {
fill: hsl(0, 100%, 75%);
}
.label {
font-size: .8rem;
text-anchor: middle;
fill: hsl(0, 0%, 20%);
/* don't allow labels to interfere with country clicks and hovers */
pointer-events: none;
}
/* responsive set up */
.svg-container {
display:inline-block;
position:relative;
width:100%;
padding-bottom:52%;
vertical-align:middle;
overflow: hidden;
}
.svg {
display:inline-block;
position:absolute;
top:0;
left: 0;
}
</style>
</head>
<body>
<div class="svg-container">
<svg viewBox='0 0 960 500' preserveAspectRatio='xMinYMin'/>
</div>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src=".script-compiled.js"></script>
</body>
</html>
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.
// load the data, find the svg container in the dom,
// and call createMap
d3.json('map-data.json', function(error, data){
const svg = d3.select('svg')
createMap(svg, data)
})
// put all logic in a nice reusable function
function createMap(svg, data) {
// use viewBox attributes instead of width + height
const params = svg.attr('viewBox').split(' ').map((n) => parseInt(n, 10))
const width = params[2]
const height = params[3]
const mapContainer = svg.append('g')
const projection = d3.geoMercator()
// d3's 'fitSize' magically sizes and positions the map for you
.fitSize([width, height], data);
// this is the function that generates position data from the projection
const path = d3.geoPath()
.projection(projection);
// append country outlines
const countries = mapContainer.selectAll('.country')
.data(data.features)
.enter()
.append('path')
.attr('class', 'country')
.attr('d', path)
.on('click', function(d){
const d3this = d3.select(this)
if (d3this.classed('active')){
d3.selectAll('.country').classed('active', false);
return
}
d3.selectAll('.country').classed('active', false);
d3.select(this).classed('active', true);
});
// append labels
mapContainer
.selectAll('.label')
.data(data.features)
.enter()
.append('text')
.attr('class', 'label')
.text((d)=> d.properties.admin)
.attr('transform', (d)=> {
const centroid = path.centroid(d)
return `translate(${centroid[0]}, ${centroid[1]})`
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment